summaryrefslogtreecommitdiff
path: root/ext/fiddle
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fiddle')
-rw-r--r--ext/fiddle/closure.c316
-rw-r--r--ext/fiddle/closure.h8
-rw-r--r--ext/fiddle/conversions.c141
-rw-r--r--ext/fiddle/conversions.h44
-rw-r--r--ext/fiddle/depend4
-rw-r--r--ext/fiddle/extconf.rb58
-rw-r--r--ext/fiddle/fiddle.c458
-rw-r--r--ext/fiddle/fiddle.h143
-rw-r--r--ext/fiddle/function.c245
-rw-r--r--ext/fiddle/function.h8
-rw-r--r--ext/fiddle/handle.c469
-rw-r--r--ext/fiddle/lib/fiddle.rb46
-rw-r--r--ext/fiddle/lib/fiddle/closure.rb48
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb176
-rw-r--r--ext/fiddle/lib/fiddle/function.rb17
-rw-r--r--ext/fiddle/lib/fiddle/import.rb314
-rw-r--r--ext/fiddle/lib/fiddle/pack.rb128
-rw-r--r--ext/fiddle/lib/fiddle/struct.rb243
-rw-r--r--ext/fiddle/lib/fiddle/types.rb71
-rw-r--r--ext/fiddle/lib/fiddle/value.rb112
-rw-r--r--ext/fiddle/pointer.c716
-rw-r--r--ext/fiddle/win32/extconf.rb3
-rw-r--r--ext/fiddle/win32/lib/win32/registry.rb845
-rw-r--r--ext/fiddle/win32/lib/win32/resolv.rb379
24 files changed, 0 insertions, 4992 deletions
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
deleted file mode 100644
index 121a08ea19..0000000000
--- a/ext/fiddle/closure.c
+++ /dev/null
@@ -1,316 +0,0 @@
-#include <fiddle.h>
-
-VALUE cFiddleClosure;
-
-typedef struct {
- void * code;
- ffi_closure *pcl;
- ffi_cif cif;
- int argc;
- ffi_type **argv;
-} fiddle_closure;
-
-#if defined(USE_FFI_CLOSURE_ALLOC)
-#elif defined(__OpenBSD__) || defined(__APPLE__) || defined(__linux__)
-# define USE_FFI_CLOSURE_ALLOC 0
-#elif defined(RUBY_LIBFFI_MODVERSION) && RUBY_LIBFFI_MODVERSION < 3000005 && \
- (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64))
-# define USE_FFI_CLOSURE_ALLOC 0
-#else
-# define USE_FFI_CLOSURE_ALLOC 1
-#endif
-
-static void
-dealloc(void * ptr)
-{
- fiddle_closure * cls = (fiddle_closure *)ptr;
-#if USE_FFI_CLOSURE_ALLOC
- ffi_closure_free(cls->pcl);
-#else
- munmap(cls->pcl, sizeof(cls->pcl));
-#endif
- if (cls->argv) xfree(cls->argv);
- xfree(cls);
-}
-
-static size_t
-closure_memsize(const void * ptr)
-{
- fiddle_closure * cls = (fiddle_closure *)ptr;
- size_t size = 0;
-
- if (ptr) {
- size += sizeof(*cls);
-#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
- size += ffi_raw_size(&cls->cif);
-#endif
- size += sizeof(*cls->argv);
- size += sizeof(ffi_closure);
- }
- return size;
-}
-
-const rb_data_type_t closure_data_type = {
- "fiddle/closure",
- {0, dealloc, closure_memsize,},
-};
-
-void
-callback(ffi_cif *cif, void *resp, void **args, void *ctx)
-{
- VALUE self = (VALUE)ctx;
- VALUE rbargs = rb_iv_get(self, "@args");
- VALUE ctype = rb_iv_get(self, "@ctype");
- int argc = RARRAY_LENINT(rbargs);
- VALUE params = rb_ary_tmp_new(argc);
- VALUE ret;
- VALUE cPointer;
- int i, type;
-
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- for (i = 0; i < argc; i++) {
- type = NUM2INT(RARRAY_PTR(rbargs)[i]);
- switch (type) {
- case TYPE_VOID:
- argc = 0;
- break;
- case TYPE_INT:
- rb_ary_push(params, INT2NUM(*(int *)args[i]));
- break;
- case -TYPE_INT:
- rb_ary_push(params, UINT2NUM(*(unsigned int *)args[i]));
- break;
- case TYPE_VOIDP:
- rb_ary_push(params,
- rb_funcall(cPointer, rb_intern("[]"), 1,
- PTR2NUM(*(void **)args[i])));
- break;
- case TYPE_LONG:
- rb_ary_push(params, LONG2NUM(*(long *)args[i]));
- break;
- case -TYPE_LONG:
- rb_ary_push(params, ULONG2NUM(*(unsigned long *)args[i]));
- break;
- case TYPE_CHAR:
- rb_ary_push(params, INT2NUM(*(signed char *)args[i]));
- break;
- case -TYPE_CHAR:
- rb_ary_push(params, UINT2NUM(*(unsigned char *)args[i]));
- break;
- case TYPE_SHORT:
- rb_ary_push(params, INT2NUM(*(signed short *)args[i]));
- break;
- case -TYPE_SHORT:
- rb_ary_push(params, UINT2NUM(*(unsigned short *)args[i]));
- break;
- case TYPE_DOUBLE:
- rb_ary_push(params, rb_float_new(*(double *)args[i]));
- break;
- case TYPE_FLOAT:
- rb_ary_push(params, rb_float_new(*(float *)args[i]));
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- rb_ary_push(params, LL2NUM(*(LONG_LONG *)args[i]));
- break;
- case -TYPE_LONG_LONG:
- rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)args[i]));
- break;
-#endif
- default:
- rb_raise(rb_eRuntimeError, "closure args: %d", type);
- }
- }
-
- ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_PTR(params));
- RB_GC_GUARD(params);
-
- type = NUM2INT(ctype);
- switch (type) {
- case TYPE_VOID:
- break;
- case TYPE_LONG:
- *(long *)resp = NUM2LONG(ret);
- break;
- case -TYPE_LONG:
- *(unsigned long *)resp = NUM2ULONG(ret);
- break;
- case TYPE_CHAR:
- case TYPE_SHORT:
- case TYPE_INT:
- *(ffi_sarg *)resp = NUM2INT(ret);
- break;
- case -TYPE_CHAR:
- case -TYPE_SHORT:
- case -TYPE_INT:
- *(ffi_arg *)resp = NUM2UINT(ret);
- break;
- case TYPE_VOIDP:
- *(void **)resp = NUM2PTR(ret);
- break;
- case TYPE_DOUBLE:
- *(double *)resp = NUM2DBL(ret);
- break;
- case TYPE_FLOAT:
- *(float *)resp = (float)NUM2DBL(ret);
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- *(LONG_LONG *)resp = NUM2LL(ret);
- break;
- case -TYPE_LONG_LONG:
- *(unsigned LONG_LONG *)resp = NUM2ULL(ret);
- break;
-#endif
- default:
- rb_raise(rb_eRuntimeError, "closure retval: %d", type);
- }
-}
-
-static VALUE
-allocate(VALUE klass)
-{
- fiddle_closure * closure;
-
- VALUE i = TypedData_Make_Struct(klass, fiddle_closure,
- &closure_data_type, closure);
-
-#if USE_FFI_CLOSURE_ALLOC
- closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code);
-#else
- closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
-#endif
-
- return i;
-}
-
-static VALUE
-initialize(int rbargc, VALUE argv[], VALUE self)
-{
- VALUE ret;
- VALUE args;
- VALUE abi;
- fiddle_closure * cl;
- ffi_cif * cif;
- ffi_closure *pcl;
- ffi_status result;
- int i, argc;
-
- if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi))
- abi = INT2NUM(FFI_DEFAULT_ABI);
-
- Check_Type(args, T_ARRAY);
-
- argc = RARRAY_LENINT(args);
-
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
-
- cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
-
- for (i = 0; i < argc; i++) {
- int type = NUM2INT(RARRAY_PTR(args)[i]);
- cl->argv[i] = INT2FFI_TYPE(type);
- }
- cl->argv[argc] = NULL;
-
- rb_iv_set(self, "@ctype", ret);
- rb_iv_set(self, "@args", args);
-
- cif = &cl->cif;
- pcl = cl->pcl;
-
- result = ffi_prep_cif(cif, NUM2INT(abi), argc,
- INT2FFI_TYPE(NUM2INT(ret)),
- cl->argv);
-
- if (FFI_OK != result)
- rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
-
-#if USE_FFI_CLOSURE_ALLOC
- result = ffi_prep_closure_loc(pcl, cif, callback,
- (void *)self, cl->code);
-#else
- result = ffi_prep_closure(pcl, cif, callback, (void *)self);
- cl->code = (void *)pcl;
- i = mprotect(pcl, sizeof(pcl), PROT_READ | PROT_EXEC);
- if (i) {
- rb_sys_fail("mprotect");
- }
-#endif
-
- if (FFI_OK != result)
- rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
-
- return self;
-}
-
-static VALUE
-to_i(VALUE self)
-{
- fiddle_closure * cl;
- void *code;
-
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl);
-
- code = cl->code;
-
- return PTR2NUM(code);
-}
-
-void
-Init_fiddle_closure()
-{
-#if 0
- mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */
-#endif
-
- /*
- * Document-class: Fiddle::Closure
- *
- * == Description
- *
- * An FFI closure wrapper, for handling callbacks.
- *
- * == Example
- *
- * closure = Class.new(Fiddle::Closure) {
- * def call
- * 10
- * end
- * }.new(Fiddle::TYPE_INT, [])
- * #=> #<#<Class:0x0000000150d308>:0x0000000150d240>
- * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
- * #=> #<Fiddle::Function:0x00000001516e58>
- * func.call
- * #=> 10
- */
- cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject);
-
- rb_define_alloc_func(cFiddleClosure, allocate);
-
- /*
- * Document-method: new
- *
- * call-seq: new(ret, args, abi = Fiddle::DEFAULT)
- *
- * Construct a new Closure object.
- *
- * * +ret+ is the C type to be returned
- * * +args+ is an Array of arguments, passed to the callback function
- * * +abi+ is the abi of the closure
- *
- * If there is an error in preparing the ffi_cif or ffi_prep_closure,
- * then a RuntimeError will be raised.
- */
- rb_define_method(cFiddleClosure, "initialize", initialize, -1);
-
- /*
- * Document-method: to_i
- *
- * Returns the memory address for this closure
- */
- rb_define_method(cFiddleClosure, "to_i", to_i, 0);
-}
-/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/closure.h b/ext/fiddle/closure.h
deleted file mode 100644
index 1e870e2285..0000000000
--- a/ext/fiddle/closure.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef FIDDLE_CLOSURE_H
-#define FIDDLE_CLOSURE_H
-
-#include <fiddle.h>
-
-void Init_fiddle_closure();
-
-#endif
diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
deleted file mode 100644
index d40ddc1f38..0000000000
--- a/ext/fiddle/conversions.c
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <fiddle.h>
-
-ffi_type *
-int_to_ffi_type(int type)
-{
- int signed_p = 1;
-
- if (type < 0) {
- type = -1 * type;
- signed_p = 0;
- }
-
-#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t)
-
- switch (type) {
- case TYPE_VOID:
- return &ffi_type_void;
- case TYPE_VOIDP:
- return &ffi_type_pointer;
- case TYPE_CHAR:
- return rb_ffi_type_of(char);
- case TYPE_SHORT:
- return rb_ffi_type_of(short);
- case TYPE_INT:
- return rb_ffi_type_of(int);
- case TYPE_LONG:
- return rb_ffi_type_of(long);
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- return rb_ffi_type_of(long_long);
-#endif
- case TYPE_FLOAT:
- return &ffi_type_float;
- case TYPE_DOUBLE:
- return &ffi_type_double;
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- }
- return &ffi_type_pointer;
-}
-
-void
-value_to_generic(int type, VALUE src, fiddle_generic * dst)
-{
- switch (type) {
- case TYPE_VOID:
- break;
- case TYPE_VOIDP:
- dst->pointer = NUM2PTR(rb_Integer(src));
- break;
- case TYPE_CHAR:
- dst->schar = (signed char)NUM2INT(src);
- break;
- case -TYPE_CHAR:
- dst->uchar = (unsigned char)NUM2UINT(src);
- break;
- case TYPE_SHORT:
- dst->sshort = (unsigned short)NUM2INT(src);
- break;
- case -TYPE_SHORT:
- dst->sshort = (signed short)NUM2UINT(src);
- break;
- case TYPE_INT:
- dst->sint = NUM2INT(src);
- break;
- case -TYPE_INT:
- dst->uint = NUM2UINT(src);
- break;
- case TYPE_LONG:
- dst->slong = NUM2LONG(src);
- break;
- case -TYPE_LONG:
- dst->ulong = NUM2ULONG(src);
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- dst->slong_long = NUM2LL(src);
- break;
- case -TYPE_LONG_LONG:
- dst->ulong_long = NUM2ULL(src);
- break;
-#endif
- case TYPE_FLOAT:
- dst->ffloat = (float)NUM2DBL(src);
- break;
- case TYPE_DOUBLE:
- dst->ddouble = NUM2DBL(src);
- break;
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- }
-}
-
-VALUE
-generic_to_value(VALUE rettype, fiddle_generic retval)
-{
- int type = NUM2INT(rettype);
- VALUE cPointer;
-
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- switch (type) {
- case TYPE_VOID:
- return Qnil;
- case TYPE_VOIDP:
- return rb_funcall(cPointer, rb_intern("[]"), 1,
- PTR2NUM((void *)retval.pointer));
- case TYPE_CHAR:
- return INT2NUM((signed char)retval.fffi_sarg);
- case -TYPE_CHAR:
- return INT2NUM((unsigned char)retval.fffi_arg);
- case TYPE_SHORT:
- return INT2NUM((signed short)retval.fffi_sarg);
- case -TYPE_SHORT:
- return INT2NUM((unsigned short)retval.fffi_arg);
- case TYPE_INT:
- return INT2NUM((signed int)retval.fffi_sarg);
- case -TYPE_INT:
- return UINT2NUM((unsigned int)retval.fffi_arg);
- case TYPE_LONG:
- return LONG2NUM(retval.slong);
- case -TYPE_LONG:
- return ULONG2NUM(retval.ulong);
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- return LL2NUM(retval.slong_long);
- case -TYPE_LONG_LONG:
- return ULL2NUM(retval.ulong_long);
-#endif
- case TYPE_FLOAT:
- return rb_float_new(retval.ffloat);
- case TYPE_DOUBLE:
- return rb_float_new(retval.ddouble);
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- }
-
- UNREACHABLE;
-}
-
-/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h
deleted file mode 100644
index d0a08d6bc0..0000000000
--- a/ext/fiddle/conversions.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef FIDDLE_CONVERSIONS_H
-#define FIDDLE_CONVERSIONS_H
-
-#include <fiddle.h>
-
-typedef union
-{
- ffi_arg fffi_arg; /* rvalue smaller than unsigned long */
- ffi_sarg fffi_sarg; /* rvalue smaller than signed long */
- unsigned char uchar; /* ffi_type_uchar */
- signed char schar; /* ffi_type_schar */
- unsigned short ushort; /* ffi_type_sshort */
- signed short sshort; /* ffi_type_ushort */
- unsigned int uint; /* ffi_type_uint */
- signed int sint; /* ffi_type_sint */
- unsigned long ulong; /* ffi_type_ulong */
- signed long slong; /* ffi_type_slong */
- float ffloat; /* ffi_type_float */
- double ddouble; /* ffi_type_double */
-#if HAVE_LONG_LONG
- unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */
- signed LONG_LONG slong_long; /* ffi_type_ulong_long */
-#endif
- void * pointer; /* ffi_type_pointer */
-} fiddle_generic;
-
-ffi_type * int_to_ffi_type(int type);
-void value_to_generic(int type, VALUE src, fiddle_generic * dst);
-VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
-
-#define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst))
-#define INT2FFI_TYPE(_type) int_to_ffi_type(_type)
-#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval))
-
-#if SIZEOF_VOIDP == SIZEOF_LONG
-# define PTR2NUM(x) (ULONG2NUM((unsigned long)(x)))
-# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
-#else
-/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */
-# define PTR2NUM(x) (ULL2NUM((unsigned long long)(x)))
-# define NUM2PTR(x) ((void*)(NUM2ULL(x)))
-#endif
-
-#endif
diff --git a/ext/fiddle/depend b/ext/fiddle/depend
deleted file mode 100644
index e786dc71d2..0000000000
--- a/ext/fiddle/depend
+++ /dev/null
@@ -1,4 +0,0 @@
-$(OBJS): $(HDRS) $(ruby_headers) \
- $(hdrdir)/ruby/io.h \
- $(hdrdir)/ruby/encoding.h \
- $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
deleted file mode 100644
index 9c7991ec44..0000000000
--- a/ext/fiddle/extconf.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'mkmf'
-
-# :stopdoc:
-
-dir_config 'libffi'
-
-pkg_config("libffi")
-if ver = pkg_config("libffi", "modversion")
- $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver.split('.') }})
-end
-
-unless have_header('ffi.h')
- if have_header('ffi/ffi.h')
- $defs.push(format('-DUSE_HEADER_HACKS'))
- else
- raise "ffi.h is missing. Please install libffi."
- end
-end
-
-unless have_library('ffi') || have_library('libffi')
- raise "libffi is missing. Please install libffi."
-end
-
-have_header 'sys/mman.h'
-
-if have_header "dlfcn.h"
- have_library "dl"
-
- %w{ dlopen dlclose dlsym }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-
- have_func "dlerror"
-elsif have_header "windows.h"
- %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-end
-
-have_const('FFI_STDCALL', 'ffi.h') || have_const('FFI_STDCALL', 'ffi/ffi.h')
-
-config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h")))
-types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil}
-types.each do |type, signed|
- if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config
- if size = $2 and size != 'VOIDP'
- size = types.fetch(size) {size}
- $defs << format("-DTYPE_%s=TYPE_%s", signed||type, size)
- end
- if signed
- check_signedness(type.downcase, "stddef.h")
- end
- end
-end
-
-create_makefile 'fiddle'
-
-# :startdoc:
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
deleted file mode 100644
index 89644301aa..0000000000
--- a/ext/fiddle/fiddle.c
+++ /dev/null
@@ -1,458 +0,0 @@
-#include <fiddle.h>
-
-VALUE mFiddle;
-VALUE rb_eFiddleError;
-
-#ifndef TYPE_SSIZE_T
-# if SIZEOF_SIZE_T == SIZEOF_INT
-# define TYPE_SSIZE_T TYPE_INT
-# elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define TYPE_SSIZE_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
-# define TYPE_SSIZE_T TYPE_LONG_LONG
-# endif
-#endif
-#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
-
-#ifndef TYPE_PTRDIFF_T
-# if SIZEOF_PTRDIFF_T == SIZEOF_INT
-# define TYPE_PTRDIFF_T TYPE_INT
-# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG_LONG
-# endif
-#endif
-
-#ifndef TYPE_INTPTR_T
-# if SIZEOF_INTPTR_T == SIZEOF_INT
-# define TYPE_INTPTR_T TYPE_INT
-# elif SIZEOF_INTPTR_T == SIZEOF_LONG
-# define TYPE_INTPTR_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
-# define TYPE_INTPTR_T TYPE_LONG_LONG
-# endif
-#endif
-#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
-
-void Init_fiddle_pointer(void);
-
-/*
- * call-seq: Fiddle.malloc(size)
- *
- * Allocate +size+ bytes of memory and return the integer memory address
- * for the allocated memory.
- */
-static VALUE
-rb_fiddle_malloc(VALUE self, VALUE size)
-{
- void *ptr;
-
- rb_secure(4);
- ptr = (void*)ruby_xmalloc(NUM2INT(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.realloc(addr, size)
- *
- * Change the size of the memory allocated at the memory location +addr+ to
- * +size+ bytes. Returns the memory address of the reallocated memory, which
- * may be different than the address passed in.
- */
-static VALUE
-rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
-{
- void *ptr = NUM2PTR(addr);
-
- rb_secure(4);
- ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.free(addr)
- *
- * Free the memory at address +addr+
- */
-VALUE
-rb_fiddle_free(VALUE self, VALUE addr)
-{
- void *ptr = NUM2PTR(addr);
-
- rb_secure(4);
- ruby_xfree(ptr);
- return Qnil;
-}
-
-/*
- * call-seq: Fiddle.dlunwrap(addr)
- *
- * Returns the hexadecimal representation of a memory pointer address +addr+
- *
- * Example:
- *
- * lib = Fiddle.dlopen('/lib64/libc-2.15.so')
- * => #<Fiddle::Handle:0x00000001342460>
- *
- * lib['strcpy'].to_s(16)
- * => "7f59de6dd240"
- *
- * Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16)))
- * => "7f59de6dd240"
- */
-VALUE
-rb_fiddle_ptr2value(VALUE self, VALUE addr)
-{
- rb_secure(4);
- return (VALUE)NUM2PTR(addr);
-}
-
-/*
- * call-seq: Fiddle.dlwrap(val)
- *
- * Returns a memory pointer of a function's hexadecimal address location +val+
- *
- * Example:
- *
- * lib = Fiddle.dlopen('/lib64/libc-2.15.so')
- * => #<Fiddle::Handle:0x00000001342460>
- *
- * Fiddle.dlwrap(lib['strcpy'].to_s(16))
- * => 25522520
- */
-static VALUE
-rb_fiddle_value2ptr(VALUE self, VALUE val)
-{
- return PTR2NUM((void*)val);
-}
-
-void Init_fiddle_handle(void);
-
-void
-Init_fiddle(void)
-{
- /*
- * Document-module: Fiddle
- *
- * A libffi wrapper for Ruby.
- *
- * == Description
- *
- * Fiddle is an extension to translate a foreign function interface (FFI)
- * with ruby.
- *
- * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library
- * which provides a portable interface that allows code written in one
- * language to clal code written in another language.
- *
- * == Example
- *
- * Here we will use Fiddle::Function to wrap {floor(3) from
- * libm}[http://linux.die.net/man/3/floor]
- *
- * require 'fiddle'
- *
- * libm = Fiddle.dlopen('/lib/libm.so.6')
- *
- * floor = Fiddle::Function.new(
- * libm['floor'],
- * [Fiddle::TYPE_DOUBLE],
- * Fiddle::TYPE_DOUBLE
- * )
- *
- * puts floor.call(3.14159) #=> 3.0
- *
- *
- */
- mFiddle = rb_define_module("Fiddle");
-
- /*
- * Document-class: Fiddle::DLError
- *
- * standard dynamic load exception
- */
- rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
-
- /* Document-const: TYPE_VOID
- *
- * C type - void
- */
- rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID));
-
- /* Document-const: TYPE_VOIDP
- *
- * C type - void*
- */
- rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP));
-
- /* Document-const: TYPE_CHAR
- *
- * C type - char
- */
- rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR));
-
- /* Document-const: TYPE_SHORT
- *
- * C type - short
- */
- rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT));
-
- /* Document-const: TYPE_INT
- *
- * C type - int
- */
- rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT));
-
- /* Document-const: TYPE_LONG
- *
- * C type - long
- */
- rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG));
-
-#if HAVE_LONG_LONG
- /* Document-const: TYPE_LONG_LONG
- *
- * C type - long long
- */
- rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
-#endif
-
- /* Document-const: TYPE_FLOAT
- *
- * C type - float
- */
- rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT));
-
- /* Document-const: TYPE_DOUBLE
- *
- * C type - double
- */
- rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
-
- /* Document-const: TYPE_SIZE_T
- *
- * C type - size_t
- */
- rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T));
-
- /* Document-const: TYPE_SSIZE_T
- *
- * C type - ssize_t
- */
- rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T));
-
- /* Document-const: TYPE_PTRDIFF_T
- *
- * C type - ptrdiff_t
- */
- rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
-
- /* Document-const: TYPE_INTPTR_T
- *
- * C type - intptr_t
- */
- rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T));
-
- /* Document-const: TYPE_UINTPTR_T
- *
- * C type - uintptr_t
- */
- rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T));
-
- /* Document-const: ALIGN_VOIDP
- *
- * The alignment size of a void*
- */
- rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
-
- /* Document-const: ALIGN_CHAR
- *
- * The alignment size of a char
- */
- rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR));
-
- /* Document-const: ALIGN_SHORT
- *
- * The alignment size of a short
- */
- rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
-
- /* Document-const: ALIGN_INT
- *
- * The alignment size of an int
- */
- rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT));
-
- /* Document-const: ALIGN_LONG
- *
- * The alignment size of a long
- */
- rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
-
-#if HAVE_LONG_LONG
- /* Document-const: ALIGN_LONG_LONG
- *
- * The alignment size of a long long
- */
- rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
-#endif
-
- /* Document-const: ALIGN_FLOAT
- *
- * The alignment size of a float
- */
- rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
-
- /* Document-const: ALIGN_DOUBLE
- *
- * The alignment size of a double
- */
- rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
-
- /* Document-const: ALIGN_SIZE_T
- *
- * The alignment size of a size_t
- */
- rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));
-
- /* Document-const: ALIGN_SSIZE_T
- *
- * The alignment size of a ssize_t
- */
- rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */
-
- /* Document-const: ALIGN_PTRDIFF_T
- *
- * The alignment size of a ptrdiff_t
- */
- rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));
-
- /* Document-const: ALIGN_INTPTR_T
- *
- * The alignment size of a intptr_t
- */
- rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));
-
- /* Document-const: ALIGN_UINTPTR_T
- *
- * The alignment size of a uintptr_t
- */
- rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));
-
- /* Document-const: WINDOWS
- *
- * Returns a boolean regarding whether the host is WIN32
- */
-#if defined(_WIN32)
- rb_define_const(mFiddle, "WINDOWS", Qtrue);
-#else
- rb_define_const(mFiddle, "WINDOWS", Qfalse);
-#endif
-
- /* Document-const: SIZEOF_VOIDP
- *
- * size of a void*
- */
- rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
-
- /* Document-const: SIZEOF_CHAR
- *
- * size of a char
- */
- rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
-
- /* Document-const: SIZEOF_SHORT
- *
- * size of a short
- */
- rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
-
- /* Document-const: SIZEOF_INT
- *
- * size of an int
- */
- rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int)));
-
- /* Document-const: SIZEOF_LONG
- *
- * size of a long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long)));
-
-#if HAVE_LONG_LONG
- /* Document-const: SIZEOF_LONG_LONG
- *
- * size of a long long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
-#endif
-
- /* Document-const: SIZEOF_FLOAT
- *
- * size of a float
- */
- rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
-
- /* Document-const: SIZEOF_DOUBLE
- *
- * size of a double
- */
- rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
-
- /* Document-const: SIZEOF_SIZE_T
- *
- * size of a size_t
- */
- rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t)));
-
- /* Document-const: SIZEOF_SSIZE_T
- *
- * size of a ssize_t
- */
- rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */
-
- /* Document-const: SIZEOF_PTRDIFF_T
- *
- * size of a ptrdiff_t
- */
- rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t)));
-
- /* Document-const: SIZEOF_INTPTR_T
- *
- * size of a intptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t)));
-
- /* Document-const: SIZEOF_UINTPTR_T
- *
- * size of a uintptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
-
- /* Document-const: RUBY_FREE
- *
- * Address of the ruby_xfree() function
- */
- rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));
-
- /* Document-const: BUILD_RUBY_PLATFORM
- *
- * Platform built against (i.e. "x86_64-linux", etc.)
- *
- * See also RUBY_PLATFORM
- */
- rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));
-
- rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
- rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
- rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
- rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
- rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
-
- Init_fiddle_function();
- Init_fiddle_closure();
- Init_fiddle_handle();
- Init_fiddle_pointer();
-}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
deleted file mode 100644
index b37c37bc65..0000000000
--- a/ext/fiddle/fiddle.h
+++ /dev/null
@@ -1,143 +0,0 @@
-#ifndef FIDDLE_H
-#define FIDDLE_H
-
-#include <ruby.h>
-#include <errno.h>
-
-#if defined(_WIN32)
-#include <windows.h>
-#endif
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#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(_WIN32)
-# include <windows.h>
-# define dlopen(name,flag) ((void*)LoadLibrary(name))
-# define dlerror() strerror(rb_w32_map_errno(GetLastError()))
-# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
-# define RTLD_LAZY -1
-# define RTLD_NOW -1
-# define RTLD_GLOBAL -1
-# endif
-#endif
-
-#ifdef USE_HEADER_HACKS
-#include <ffi/ffi.h>
-#else
-#include <ffi.h>
-#endif
-
-#undef ffi_type_uchar
-#undef ffi_type_schar
-#undef ffi_type_ushort
-#undef ffi_type_sshort
-#undef ffi_type_uint
-#undef ffi_type_sint
-#undef ffi_type_ulong
-#undef ffi_type_slong
-
-#if CHAR_BIT == 8
-# define ffi_type_uchar ffi_type_uint8
-# define ffi_type_schar ffi_type_sint8
-#else
-# error "CHAR_BIT not supported"
-#endif
-
-# if SIZEOF_SHORT == 2
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-# elif SIZEOF_SHORT == 4
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-# else
-# error "short size not supported"
-# endif
-
-# if SIZEOF_INT == 2
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-# elif SIZEOF_INT == 4
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-# elif SIZEOF_INT == 8
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-# else
-# error "int size not supported"
-# endif
-
-# if SIZEOF_LONG == 4
-# define ffi_type_ulong ffi_type_uint32
-# define ffi_type_slong ffi_type_sint32
-# elif SIZEOF_LONG == 8
-# define ffi_type_ulong ffi_type_uint64
-# define ffi_type_slong ffi_type_sint64
-# else
-# error "long size not supported"
-# endif
-
-#if HAVE_LONG_LONG
-# if SIZEOF_LONG_LONG == 8
-# define ffi_type_slong_long ffi_type_sint64
-# define ffi_type_ulong_long ffi_type_uint64
-# else
-# error "long long size not supported"
-# endif
-#endif
-
-#include <closure.h>
-#include <conversions.h>
-#include <function.h>
-
-/* FIXME
- * These constants need to match up with DL. We need to refactor this to use
- * the DL header files or vice versa.
- */
-
-#define TYPE_VOID 0
-#define TYPE_VOIDP 1
-#define TYPE_CHAR 2
-#define TYPE_SHORT 3
-#define TYPE_INT 4
-#define TYPE_LONG 5
-#if HAVE_LONG_LONG
-#define TYPE_LONG_LONG 6
-#endif
-#define TYPE_FLOAT 7
-#define TYPE_DOUBLE 8
-
-#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
-
-#define ALIGN_VOIDP ALIGN_OF(void*)
-#define ALIGN_SHORT ALIGN_OF(short)
-#define ALIGN_CHAR ALIGN_OF(char)
-#define ALIGN_INT ALIGN_OF(int)
-#define ALIGN_LONG ALIGN_OF(long)
-#if HAVE_LONG_LONG
-#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG)
-#endif
-#define ALIGN_FLOAT ALIGN_OF(float)
-#define ALIGN_DOUBLE ALIGN_OF(double)
-
-extern VALUE mFiddle;
-extern VALUE rb_eFiddleError;
-
-VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
-
-#endif
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
deleted file mode 100644
index 72a1a6238d..0000000000
--- a/ext/fiddle/function.c
+++ /dev/null
@@ -1,245 +0,0 @@
-#include <fiddle.h>
-
-VALUE cFiddleFunction;
-
-static void
-deallocate(void *p)
-{
- ffi_cif *ptr = p;
- if (ptr->arg_types) xfree(ptr->arg_types);
- xfree(ptr);
-}
-
-static size_t
-function_memsize(const void *p)
-{
- /* const */ffi_cif *ptr = (ffi_cif *)p;
- size_t size = 0;
-
- if (ptr) {
- size += sizeof(*ptr);
-#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
- size += ffi_raw_size(ptr);
-#endif
- }
- return size;
-}
-
-const rb_data_type_t function_data_type = {
- "fiddle/function",
- {0, deallocate, function_memsize,},
-};
-
-static VALUE
-allocate(VALUE klass)
-{
- ffi_cif * cif;
-
- return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif);
-}
-
-VALUE
-rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
-{
- VALUE argv[3];
-
- argv[0] = address;
- argv[1] = arg_types;
- argv[2] = ret_type;
-
- return rb_class_new_instance(3, argv, cFiddleFunction);
-}
-
-static int
-parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
-{
- if (key == ID2SYM(rb_intern("name"))) {
- rb_iv_set(self, "@name", value);
- } else {
- rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE, key);
- }
- return ST_CONTINUE;
-}
-
-static VALUE
-initialize(int argc, VALUE argv[], VALUE self)
-{
- ffi_cif * cif;
- ffi_type **arg_types;
- ffi_status result;
- VALUE ptr, args, ret_type, abi, kwds;
- int i;
-
- rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds);
- if(NIL_P(abi)) abi = INT2NUM(FFI_DEFAULT_ABI);
-
- Check_Type(args, T_ARRAY);
-
- rb_iv_set(self, "@ptr", ptr);
- rb_iv_set(self, "@args", args);
- rb_iv_set(self, "@return_type", ret_type);
- rb_iv_set(self, "@abi", abi);
-
- if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
-
- arg_types = xcalloc(RARRAY_LEN(args) + 1, sizeof(ffi_type *));
-
- for (i = 0; i < RARRAY_LEN(args); i++) {
- int type = NUM2INT(RARRAY_PTR(args)[i]);
- arg_types[i] = INT2FFI_TYPE(type);
- }
- arg_types[RARRAY_LEN(args)] = NULL;
-
- result = ffi_prep_cif (
- cif,
- NUM2INT(abi),
- RARRAY_LENINT(args),
- INT2FFI_TYPE(NUM2INT(ret_type)),
- arg_types);
-
- if (result)
- rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
-
- return self;
-}
-
-static VALUE
-function_call(int argc, VALUE argv[], VALUE self)
-{
- ffi_cif * cif;
- fiddle_generic retval;
- fiddle_generic *generic_args;
- void **values;
- VALUE cfunc, types, cPointer;
- int i;
-
- cfunc = rb_iv_get(self, "@ptr");
- types = rb_iv_get(self, "@args");
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- if(argc != RARRAY_LENINT(types)) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
- argc, RARRAY_LENINT(types));
- }
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
-
- values = xcalloc((size_t)argc + 1, (size_t)sizeof(void *));
- generic_args = xcalloc((size_t)argc, (size_t)sizeof(fiddle_generic));
-
- for (i = 0; i < argc; i++) {
- VALUE type = RARRAY_PTR(types)[i];
- VALUE src = argv[i];
-
- if(NUM2INT(type) == TYPE_VOIDP) {
- if(NIL_P(src)) {
- src = INT2FIX(0);
- } else if(cPointer != CLASS_OF(src)) {
- src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
- }
- src = rb_Integer(src);
- }
-
- VALUE2GENERIC(NUM2INT(type), src, &generic_args[i]);
- values[i] = (void *)&generic_args[i];
- }
- values[argc] = NULL;
-
- ffi_call(cif, NUM2PTR(rb_Integer(cfunc)), &retval, values);
-
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
-#if defined(_WIN32)
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
-#endif
-
- xfree(values);
- xfree(generic_args);
-
- return GENERIC2VALUE(rb_iv_get(self, "@return_type"), retval);
-}
-
-void
-Init_fiddle_function(void)
-{
- /*
- * Document-class: Fiddle::Function
- *
- * == Description
- *
- * A representation of a C function
- *
- * == Examples
- *
- * === 'strcpy'
- *
- * @libc = Fiddle.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::Handle:0x00000001d7a8d8>
- * f = Fiddle::Function.new(
- * @libc['strcpy'],
- * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
- * Fiddle::TYPE_VOIDP)
- * #=> #<Fiddle::Function:0x00000001d8ee00>
- * buff = "000"
- * #=> "000"
- * str = f.call(buff, "123")
- * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
- * str.to_s
- * => "123"
- *
- * === ABI check
- *
- * @libc = DL.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::Handle:0x00000001d7a8d8>
- * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
- * #=> #<Fiddle::Function:0x00000001d8ee00>
- * f.abi == Fiddle::Function::DEFAULT
- * #=> true
- */
- cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject);
-
- /*
- * Document-const: DEFAULT
- *
- * Default ABI
- *
- */
- rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI));
-
-#ifdef HAVE_CONST_FFI_STDCALL
- /*
- * Document-const: STDCALL
- *
- * FFI implementation of WIN32 stdcall convention
- *
- */
- rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL));
-#endif
-
- rb_define_alloc_func(cFiddleFunction, allocate);
-
- /*
- * Document-method: call
- *
- * Calls the constructed Function, with +args+
- *
- * For an example see Fiddle::Function
- *
- */
- rb_define_method(cFiddleFunction, "call", function_call, -1);
-
- /*
- * Document-method: new
- * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
- *
- * Constructs a Function object.
- * * +ptr+ is a referenced function, of a Fiddle::Handle
- * * +args+ is an Array of arguments, passed to the +ptr+ function
- * * +ret_type+ is the return type of the function
- * * +abi+ is the ABI of the function
- *
- */
- rb_define_method(cFiddleFunction, "initialize", initialize, -1);
-}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/function.h b/ext/fiddle/function.h
deleted file mode 100644
index e5465ab64f..0000000000
--- a/ext/fiddle/function.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef FIDDLE_FUNCTION_H
-#define FIDDLE_FUNCTION_H
-
-#include <fiddle.h>
-
-void Init_fiddle_function();
-
-#endif
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
deleted file mode 100644
index 832ff3319a..0000000000
--- a/ext/fiddle/handle.c
+++ /dev/null
@@ -1,469 +0,0 @@
-#include <ruby.h>
-#include <fiddle.h>
-
-VALUE rb_cHandle;
-
-struct dl_handle {
- void *ptr;
- int open;
- int enable_close;
-};
-
-#ifdef _WIN32
-# ifndef _WIN32_WCE
-static void *
-w32_coredll(void)
-{
- MEMORY_BASIC_INFORMATION m;
- memset(&m, 0, sizeof(m));
- if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL;
- return m.AllocationBase;
-}
-# endif
-
-static int
-w32_dlclose(void *ptr)
-{
-# ifndef _WIN32_WCE
- if( ptr == w32_coredll() ) return 0;
-# endif
- if( FreeLibrary((HMODULE)ptr) ) return 0;
- return errno = rb_w32_map_errno(GetLastError());
-}
-#define dlclose(ptr) w32_dlclose(ptr)
-#endif
-
-static void
-fiddle_handle_free(void *ptr)
-{
- struct dl_handle *fiddle_handle = ptr;
- if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){
- dlclose(fiddle_handle->ptr);
- }
-}
-
-static size_t
-fiddle_handle_memsize(const void *ptr)
-{
- return ptr ? sizeof(struct dl_handle) : 0;
-}
-
-static const rb_data_type_t fiddle_handle_data_type = {
- "fiddle/handle",
- {0, fiddle_handle_free, fiddle_handle_memsize,},
-};
-
-/*
- * call-seq: close
- *
- * Close this handle.
- *
- * Calling close more than once will raise a Fiddle::DLError exception.
- */
-static VALUE
-rb_fiddle_handle_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if(fiddle_handle->open) {
- int ret = dlclose(fiddle_handle->ptr);
- fiddle_handle->open = 0;
-
- /* Check dlclose for successful return value */
- if(ret) {
-#if defined(HAVE_DLERROR)
- rb_raise(rb_eFiddleError, "%s", dlerror());
-#else
- rb_raise(rb_eFiddleError, "could not close handle");
-#endif
- }
- return INT2NUM(ret);
- }
- rb_raise(rb_eFiddleError, "dlclose() called too many times");
-
- UNREACHABLE;
-}
-
-static VALUE
-rb_fiddle_handle_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct dl_handle *fiddle_handle;
-
- obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->ptr = 0;
- fiddle_handle->open = 0;
- fiddle_handle->enable_close = 0;
-
- return obj;
-}
-
-static VALUE
-predefined_fiddle_handle(void *handle)
-{
- VALUE obj = rb_fiddle_handle_s_allocate(rb_cHandle);
- struct dl_handle *fiddle_handle = DATA_PTR(obj);
-
- fiddle_handle->ptr = handle;
- fiddle_handle->open = 1;
- OBJ_FREEZE(obj);
- return obj;
-}
-
-/*
- * call-seq:
- * new(lib = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- *
- * Create a new handler that opens library named +lib+ with +flags+. If no
- * library is specified, RTLD_DEFAULT is used.
- */
-static VALUE
-rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
-{
- void *ptr;
- struct dl_handle *fiddle_handle;
- VALUE lib, flag;
- char *clib;
- int cflag;
- const char *err;
-
- switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){
- case 0:
- clib = NULL;
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- 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_fiddle_handle_new");
- }
-
- rb_secure(2);
-
-#if defined(_WIN32)
- if( !clib ){
- HANDLE rb_libruby_handle(void);
- ptr = rb_libruby_handle();
- }
- else if( STRCASECMP(clib, "libc") == 0
-# ifdef RUBY_COREDLL
- || STRCASECMP(clib, RUBY_COREDLL) == 0
- || STRCASECMP(clib, RUBY_COREDLL".dll") == 0
-# endif
- ){
-# ifdef _WIN32_WCE
- ptr = dlopen("coredll.dll", cflag);
-# else
- ptr = w32_coredll();
-# endif
- }
- else
-#endif
- ptr = dlopen(clib, cflag);
-#if defined(HAVE_DLERROR)
- if( !ptr && (err = dlerror()) ){
- rb_raise(rb_eFiddleError, "%s", err);
- }
-#else
- if( !ptr ){
- err = dlerror();
- rb_raise(rb_eFiddleError, "%s", err);
- }
-#endif
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){
- dlclose(fiddle_handle->ptr);
- }
- fiddle_handle->ptr = ptr;
- fiddle_handle->open = 1;
- fiddle_handle->enable_close = 0;
-
- if( rb_block_given_p() ){
- rb_ensure(rb_yield, self, rb_fiddle_handle_close, self);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq: enable_close
- *
- * Enable a call to dlclose() when this handle is garbage collected.
- */
-static VALUE
-rb_fiddle_handle_enable_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->enable_close = 1;
- return Qnil;
-}
-
-/*
- * call-seq: disable_close
- *
- * Disable a call to dlclose() when this handle is garbage collected.
- */
-static VALUE
-rb_fiddle_handle_disable_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->enable_close = 0;
- return Qnil;
-}
-
-/*
- * call-seq: close_enabled?
- *
- * Returns +true+ if dlclose() will be called when this handle is garbage collected.
- *
- * See man(3) dlclose() for more info.
- */
-static VALUE
-rb_fiddle_handle_close_enabled_p(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
-
- if(fiddle_handle->enable_close) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the memory address for this handle.
- */
-static VALUE
-rb_fiddle_handle_to_i(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- return PTR2NUM(fiddle_handle);
-}
-
-static VALUE fiddle_handle_sym(void *handle, const char *symbol);
-
-/*
- * Document-method: sym
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+.
- */
-static VALUE
-rb_fiddle_handle_sym(VALUE self, VALUE sym)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if( ! fiddle_handle->open ){
- rb_raise(rb_eFiddleError, "closed handle");
- }
-
- return fiddle_handle_sym(fiddle_handle->ptr, StringValueCStr(sym));
-}
-
-#ifndef RTLD_NEXT
-#define RTLD_NEXT NULL
-#endif
-#ifndef RTLD_DEFAULT
-#define RTLD_DEFAULT NULL
-#endif
-
-/*
- * Document-method: sym
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+. The function
- * is searched via dlsym on RTLD_NEXT.
- *
- * See man(3) dlsym() for more info.
- */
-static VALUE
-rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
-{
- return fiddle_handle_sym(RTLD_NEXT, StringValueCStr(sym));
-}
-
-static VALUE
-fiddle_handle_sym(void *handle, const char *name)
-{
-#if defined(HAVE_DLERROR)
- const char *err;
-# define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
-#else
-# define CHECK_DLERROR
-#endif
- void (*func)();
-
- rb_secure(2);
-#ifdef HAVE_DLERROR
- dlerror();
-#endif
- func = (void (*)())(VALUE)dlsym(handle, name);
- CHECK_DLERROR;
-#if defined(FUNC_STDCALL)
- if( !func ){
- int i;
- int len = (int)strlen(name);
- char *name_n;
-#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
- {
- char *name_a = (char*)xmalloc(len+2);
- strcpy(name_a, name);
- name_n = name_a;
- name_a[len] = 'A';
- name_a[len+1] = '\0';
- func = dlsym(handle, name_a);
- CHECK_DLERROR;
- if( func ) goto found;
- name_n = xrealloc(name_a, len+6);
- }
-#else
- name_n = (char*)xmalloc(len+6);
-#endif
- memcpy(name_n, name, len);
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- if( func ) goto found;
- name_n[len-1] = 'A';
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- found:
- xfree(name_n);
- }
-#endif
- if( !func ){
- rb_raise(rb_eFiddleError, "unknown symbol \"%s\"", name);
- }
-
- return PTR2NUM(func);
-}
-
-void
-Init_fiddle_handle(void)
-{
- /*
- * Document-class: Fiddle::Handle
- *
- * The Fiddle::Handle is the manner to access the dynamic library
- *
- * == Example
- *
- * === Setup
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * === Setup, with flags
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * See RTLD_LAZY and RTLD_GLOBAL
- *
- * === Addresses to symbols
- *
- * strcpy_addr = @handle['strcpy']
- * => 140062278451968
- *
- * or
- *
- * strcpy_addr = @handle.sym('strcpy')
- * => 140062278451968
- *
- */
- rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
- rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate);
- rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1);
- rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1);
-
- /* Document-const: NEXT
- *
- * A predefined pseudo-handle of RTLD_NEXT
- *
- * Which will find the next occurrence of a function in the search order
- * after the current library.
- */
- rb_define_const(rb_cHandle, "NEXT", predefined_fiddle_handle(RTLD_NEXT));
-
- /* Document-const: DEFAULT
- *
- * A predefined pseudo-handle of RTLD_DEFAULT
- *
- * Which will find the first occurrence of the desired symbol using the
- * default library search order
- */
- rb_define_const(rb_cHandle, "DEFAULT", predefined_fiddle_handle(RTLD_DEFAULT));
-
- /* Document-const: RTLD_GLOBAL
- *
- * rtld Fiddle::Handle flag.
- *
- * The symbols defined by this library will be made available for symbol
- * resolution of subsequently loaded libraries.
- */
- rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
-
- /* Document-const: RTLD_LAZY
- *
- * rtld Fiddle::Handle flag.
- *
- * Perform lazy binding. Only resolve symbols as the code that references
- * them is executed. If the symbol is never referenced, then it is never
- * resolved. (Lazy binding is only performed for function references;
- * references to variables are always immediately bound when the library
- * is loaded.)
- */
- rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
-
- /* Document-const: RTLD_NOW
- *
- * rtld Fiddle::Handle flag.
- *
- * If this value is specified or the environment variable LD_BIND_NOW is
- * set to a nonempty string, all undefined symbols in the library are
- * resolved before Fiddle.dlopen returns. If this cannot be done an error
- * is returned.
- */
- rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW));
-
- rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1);
- rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0);
- rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
- rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
- rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
- rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
- rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
- rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0);
-}
-
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
deleted file mode 100644
index c8a7ef1b05..0000000000
--- a/ext/fiddle/lib/fiddle.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'fiddle.so'
-require 'fiddle/function'
-require 'fiddle/closure'
-
-module Fiddle
- if WINDOWS
- # Returns the last win32 +Error+ of the current executing +Thread+ or nil
- # if none
- def self.win32_last_error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
- end
-
- # Sets the last win32 +Error+ of the current executing +Thread+ to +error+
- def self.win32_last_error= error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
- end
- end
-
- # Returns the last +Error+ of the current executing +Thread+ or nil if none
- def self.last_error
- Thread.current[:__FIDDLE_LAST_ERROR__]
- end
-
- # Sets the last +Error+ of the current executing +Thread+ to +error+
- def self.last_error= error
- Thread.current[:__DL2_LAST_ERROR__] = error
- Thread.current[:__FIDDLE_LAST_ERROR__] = error
- end
-
- # call-seq: dlopen(library) => Fiddle::Handle
- #
- # Creates a new handler that opens +library+, and returns an instance of
- # Fiddle::Handle.
- #
- # See Fiddle::Handle.new for more.
- def dlopen library
- Fiddle::Handle.new library
- end
- module_function :dlopen
-
- # Add constants for backwards compat
-
- RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc:
- RTLD_LAZY = Handle::RTLD_LAZY # :nodoc:
- RTLD_NOW = Handle::RTLD_NOW # :nodoc:
-end
diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb
deleted file mode 100644
index beb90ecbe5..0000000000
--- a/ext/fiddle/lib/fiddle/closure.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-module Fiddle
- class Closure
-
- # the C type of the return of the FFI closure
- attr_reader :ctype
-
- # arguments of the FFI closure
- attr_reader :args
-
- # Extends Fiddle::Closure to allow for building the closure in a block
- class BlockCaller < Fiddle::Closure
-
- # == Description
- #
- # Construct a new BlockCaller object.
- #
- # * +ctype+ is the C type to be returned
- # * +args+ are passed the callback
- # * +abi+ is the abi of the closure
- #
- # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+,
- # then a RuntimeError will be raised.
- #
- # == Example
- #
- # include Fiddle
- #
- # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
- # one
- # end
- #
- # func = Function.new(cb, [TYPE_INT], TYPE_INT)
- #
- def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block
- super(ctype, args, abi)
- @block = block
- end
-
- # Calls the constructed BlockCaller, with +args+
- #
- # For an example see Fiddle::Closure::BlockCaller.new
- #
- def call *args
- @block.call(*args)
- end
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb
deleted file mode 100644
index 43fb184a12..0000000000
--- a/ext/fiddle/lib/fiddle/cparser.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-module Fiddle
- # A mixin that provides methods for parsing C struct and prototype signatures.
- #
- # == Example
- # require 'fiddle/import'
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_ctype('int increment(int)')
- # #=> ["increment", Fiddle::TYPE_INT, [Fiddle::TYPE_INT]]
- #
- module CParser
- # Parses a C struct's members
- #
- # Example:
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_struct_signature(['int i', 'char c'])
- # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]]
- #
- def parse_struct_signature(signature, tymap=nil)
- if( signature.is_a?(String) )
- signature = signature.split(/\s*,\s*/)
- end
- mems = []
- tys = []
- signature.each{|msig|
- tks = msig.split(/\s+(\*)?/)
- ty = tks[0..-2].join(" ")
- member = tks[-1]
-
- case ty
- when /\[(\d+)\]/
- n = $1.to_i
- ty.gsub!(/\s*\[\d+\]/,"")
- ty = [ty, n]
- when /\[\]/
- ty.gsub!(/\s*\[\]/, "*")
- end
-
- case member
- when /\[(\d+)\]/
- ty = [ty, $1.to_i]
- member.gsub!(/\s*\[\d+\]/,"")
- when /\[\]/
- ty = ty + "*"
- member.gsub!(/\s*\[\]/, "")
- end
-
- mems.push(member)
- tys.push(parse_ctype(ty,tymap))
- }
- return tys, mems
- end
-
- # Parses a C prototype signature
- #
- # If Hash +tymap+ is provided, the return value and the arguments from the
- # +signature+ are expected to be keys, and the value will be the C type to
- # be looked up.
- #
- # Example:
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_signature('double sum(double, double)')
- # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]]
- #
- def parse_signature(signature, tymap=nil)
- tymap ||= {}
- signature = signature.gsub(/\s+/, " ").strip
- case signature
- when /^([\w@\*\s]+)\(([\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, parse_ctype(ret, tymap), args.collect{|arg| parse_ctype(arg, tymap)}]
- else
- raise(RuntimeError,"can't parse the function prototype: #{signature}")
- end
- end
-
- # Given a String of C type +ty+, returns the corresponding Fiddle constant.
- #
- # +ty+ can also accept an Array of C type Strings, and will be returned in
- # a corresponding Array.
- #
- # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the
- # value will be the C type to be looked up.
- #
- # Example:
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_ctype('int')
- # #=> Fiddle::TYPE_INT
- #
- # parse_ctype('double')
- # #=> Fiddle::TYPE_DOUBLE
- #
- # parse_ctype('unsigned char')
- # #=> -Fiddle::TYPE_CHAR
- #
- def parse_ctype(ty, tymap=nil)
- tymap ||= {}
- case ty
- when Array
- return [parse_ctype(ty[0], tymap), ty[1]]
- when "void"
- return TYPE_VOID
- when "char"
- return TYPE_CHAR
- when "unsigned char"
- return -TYPE_CHAR
- when "short"
- return TYPE_SHORT
- when "unsigned short"
- return -TYPE_SHORT
- when "int"
- return TYPE_INT
- when "unsigned int", 'uint'
- return -TYPE_INT
- when "long"
- return TYPE_LONG
- when "unsigned long"
- return -TYPE_LONG
- when "long long"
- if( defined?(TYPE_LONG_LONG) )
- return TYPE_LONG_LONG
- else
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- when "unsigned long long"
- if( defined?(TYPE_LONG_LONG) )
- return -TYPE_LONG_LONG
- else
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- when "float"
- return TYPE_FLOAT
- when "double"
- return TYPE_DOUBLE
- when "size_t"
- return TYPE_SIZE_T
- when "ssize_t"
- return TYPE_SSIZE_T
- when "ptrdiff_t"
- return TYPE_PTRDIFF_T
- when "intptr_t"
- return TYPE_INTPTR_T
- when "uintptr_t"
- return TYPE_UINTPTR_T
- when /\*/, /\[\s*\]/
- return TYPE_VOIDP
- else
- if( tymap[ty] )
- return parse_ctype(tymap[ty], tymap)
- else
- raise(DLError, "unknown type: #{ty}")
- end
- end
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb
deleted file mode 100644
index ab7496e944..0000000000
--- a/ext/fiddle/lib/fiddle/function.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Fiddle
- class Function
- # The ABI of the Function.
- attr_reader :abi
-
- # The address of this function
- attr_reader :ptr
-
- # The name of this function
- attr_reader :name
-
- # The integer memory location of this function
- def to_i
- ptr.to_i
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb
deleted file mode 100644
index 8b948e8f23..0000000000
--- a/ext/fiddle/lib/fiddle/import.rb
+++ /dev/null
@@ -1,314 +0,0 @@
-require 'fiddle'
-require 'fiddle/struct'
-require 'fiddle/cparser'
-
-module Fiddle
-
- # Used internally by Fiddle::Importer
- class CompositeHandler
- # Create a new handler with the open +handlers+
- #
- # Used internally by Fiddle::Importer.dlload
- def initialize(handlers)
- @handlers = handlers
- end
-
- # Array of the currently loaded libraries.
- def handlers()
- @handlers
- end
-
- # Returns the address as an Integer from any handlers with the function
- # named +symbol+.
- #
- # Raises a DLError if the handle is closed.
- def sym(symbol)
- @handlers.each{|handle|
- if( handle )
- begin
- addr = handle.sym(symbol)
- return addr
- rescue DLError
- end
- end
- }
- return nil
- end
-
- # See Fiddle::CompositeHandler.sym
- def [](symbol)
- sym(symbol)
- end
- end
-
- # A DSL that provides the means to dynamically load libraries and build
- # modules around them including calling extern functions within the C
- # library that has been loaded.
- #
- # == Example
- #
- # require 'fiddle'
- # require 'fiddle/import'
- #
- # module LibSum
- # extend Fiddle::Importer
- # dlload './libsum.so'
- # extern 'double sum(double*, int)'
- # extern 'double split(double)'
- # end
- #
- module Importer
- include Fiddle
- include CParser
- extend Importer
-
- # Creates an array of handlers for the given +libs+, can be an instance of
- # Fiddle::Handle, Fiddle::Importer, or will create a new istance of
- # Fiddle::Handle using Fiddle.dlopen
- #
- # Raises a DLError if the library cannot be loaded.
- #
- # See Fiddle.dlopen
- def dlload(*libs)
- handles = libs.collect{|lib|
- case lib
- when nil
- nil
- when Handle
- lib
- when Importer
- lib.handlers
- else
- begin
- Fiddle.dlopen(lib)
- rescue DLError
- raise(DLError, "can't load #{lib}")
- end
- end
- }.flatten()
- @handler = CompositeHandler.new(handles)
- @func_map = {}
- @type_alias = {}
- end
-
- # Sets the type alias for +alias_type+ as +orig_type+
- def typealias(alias_type, orig_type)
- @type_alias[alias_type] = orig_type
- end
-
- # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine
- # the C type and the appropriate Fiddle constant.
- def sizeof(ty)
- case ty
- when String
- ty = parse_ctype(ty, @type_alias).abs()
- case ty
- when TYPE_CHAR
- return SIZEOF_CHAR
- when TYPE_SHORT
- return SIZEOF_SHORT
- when TYPE_INT
- return SIZEOF_INT
- when TYPE_LONG
- return SIZEOF_LONG
- when TYPE_LONG_LONG
- return SIZEOF_LONG_LON
- when TYPE_FLOAT
- return SIZEOF_FLOAT
- when TYPE_DOUBLE
- return SIZEOF_DOUBLE
- when TYPE_VOIDP
- return SIZEOF_VOIDP
- else
- raise(DLError, "unknown type: #{ty}")
- end
- when Class
- if( ty.instance_methods().include?(:to_ptr) )
- return ty.size()
- end
- end
- return Pointer[ty].size()
- end
-
- def parse_bind_options(opts)
- h = {}
- while( opt = opts.shift() )
- case opt
- when :stdcall, :cdecl
- h[:call_type] = opt
- when :carried, :temp, :temporal, :bind
- h[:callback_type] = opt
- h[:carrier] = opts.shift()
- else
- h[opt] = true
- end
- end
- h
- end
- private :parse_bind_options
-
- # :stopdoc:
- CALL_TYPE_TO_ABI = Hash.new { |h, k|
- raise RuntimeError, "unsupported call type: #{k}"
- }.merge({ :stdcall => (Function::STDCALL rescue Function::DEFAULT),
- :cdecl => Function::DEFAULT,
- nil => Function::DEFAULT
- }).freeze
- private_constant :CALL_TYPE_TO_ABI
- # :startdoc:
-
- # Creates a global method from the given C +signature+.
- def extern(signature, *opts)
- symname, ctype, argtype = parse_signature(signature, @type_alias)
- opt = parse_bind_options(opts)
- f = import_function(symname, ctype, argtype, opt[:call_type])
- name = symname.gsub(/@.+/,'')
- @func_map[name] = f
- # define_method(name){|*args,&block| f.call(*args,&block)}
- begin
- /^(.+?):(\d+)/ =~ caller.first
- file, line = $1, $2.to_i
- rescue
- file, line = __FILE__, __LINE__+3
- end
- module_eval(<<-EOS, file, line)
- def #{name}(*args, &block)
- @func_map['#{name}'].call(*args,&block)
- end
- EOS
- module_function(name)
- f
- end
-
- # Creates a global method from the given C +signature+ using the given
- # +opts+ as bind parameters with the given block.
- def bind(signature, *opts, &blk)
- name, ctype, argtype = parse_signature(signature, @type_alias)
- h = parse_bind_options(opts)
- case h[:callback_type]
- when :bind, nil
- f = bind_function(name, ctype, argtype, h[:call_type], &blk)
- else
- raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
- end
- @func_map[name] = f
- #define_method(name){|*args,&block| f.call(*args,&block)}
- begin
- /^(.+?):(\d+)/ =~ caller.first
- file, line = $1, $2.to_i
- rescue
- file, line = __FILE__, __LINE__+3
- end
- module_eval(<<-EOS, file, line)
- def #{name}(*args,&block)
- @func_map['#{name}'].call(*args,&block)
- end
- EOS
- module_function(name)
- f
- end
-
- # Creates a class to wrap the C struct described by +signature+.
- #
- # MyStruct = struct ['int i', 'char c']
- def struct(signature)
- tys, mems = parse_struct_signature(signature, @type_alias)
- Fiddle::CStructBuilder.create(CStruct, tys, mems)
- end
-
- # Creates a class to wrap the C union described by +signature+.
- #
- # MyUnion = union ['int i', 'char c']
- def union(signature)
- tys, mems = parse_struct_signature(signature, @type_alias)
- Fiddle::CStructBuilder.create(CUnion, tys, mems)
- end
-
- # Returns the function mapped to +name+, that was created by either
- # Fiddle::Importer.extern or Fiddle::Importer.bind
- def [](name)
- @func_map[name]
- end
-
- # Creates a class to wrap the C struct with the value +ty+
- #
- # See also Fiddle::Importer.struct
- def create_value(ty, val=nil)
- s = struct([ty + " value"])
- ptr = s.malloc()
- if( val )
- ptr.value = val
- end
- return ptr
- end
- alias value create_value
-
- # Returns a new instance of the C struct with the value +ty+ at the +addr+
- # address.
- def import_value(ty, addr)
- s = struct([ty + " value"])
- ptr = s.new(addr)
- return ptr
- end
-
-
- # The Fiddle::CompositeHandler instance
- #
- # Will raise an error if no handlers are open.
- def handler
- @handler or raise "call dlload before importing symbols and functions"
- end
-
- # Returns a new Fiddle::Pointer instance at the memory address of the given
- # +name+ symbol.
- #
- # Raises a DLError if the +name+ doesn't exist.
- #
- # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym
- def import_symbol(name)
- addr = handler.sym(name)
- if( !addr )
- raise(DLError, "cannot find the symbol: #{name}")
- end
- Pointer.new(addr)
- end
-
- # Returns a new Fiddle::Function instance at the memory address of the given
- # +name+ function.
- #
- # Raises a DLError if the +name+ doesn't exist.
- #
- # * +argtype+ is an Array of arguments, passed to the +name+ function.
- # * +ctype+ is the return type of the function
- # * +call_type+ is the ABI of the function
- #
- # See also Fiddle:Function.new
- #
- # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym
- def import_function(name, ctype, argtype, call_type = nil)
- addr = handler.sym(name)
- if( !addr )
- raise(DLError, "cannot find the function: #{name}()")
- end
- Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type],
- name: name)
- end
-
- # Returns a new closure wrapper for the +name+ function.
- #
- # * +ctype+ is the return type of the function
- # * +argtype+ is an Array of arguments, passed to the callback function
- # * +call_type+ is the abi of the closure
- # * +block+ is passed to the callback
- #
- # See Fiddle::Closure
- def bind_function(name, ctype, argtype, call_type = nil, &block)
- abi = CALL_TYPE_TO_ABI[call_type]
- closure = Class.new(Fiddle::Closure) {
- define_method(:call, block)
- }.new(ctype, argtype, abi)
-
- Function.new(closure, argtype, ctype, abi, name: name)
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb
deleted file mode 100644
index e4e9542cc0..0000000000
--- a/ext/fiddle/lib/fiddle/pack.rb
+++ /dev/null
@@ -1,128 +0,0 @@
-require 'fiddle'
-
-module Fiddle
- module PackInfo # :nodoc: all
- ALIGN_MAP = {
- TYPE_VOIDP => ALIGN_VOIDP,
- TYPE_CHAR => ALIGN_CHAR,
- TYPE_SHORT => ALIGN_SHORT,
- TYPE_INT => ALIGN_INT,
- TYPE_LONG => ALIGN_LONG,
- TYPE_FLOAT => ALIGN_FLOAT,
- TYPE_DOUBLE => ALIGN_DOUBLE,
- -TYPE_CHAR => ALIGN_CHAR,
- -TYPE_SHORT => ALIGN_SHORT,
- -TYPE_INT => ALIGN_INT,
- -TYPE_LONG => ALIGN_LONG,
- }
-
- PACK_MAP = {
- TYPE_VOIDP => ((SIZEOF_VOIDP == SIZEOF_LONG_LONG) ? "q" : "l!"),
- TYPE_CHAR => "c",
- TYPE_SHORT => "s!",
- TYPE_INT => "i!",
- TYPE_LONG => "l!",
- TYPE_FLOAT => "f",
- TYPE_DOUBLE => "d",
- -TYPE_CHAR => "c",
- -TYPE_SHORT => "s!",
- -TYPE_INT => "i!",
- -TYPE_LONG => "l!",
- }
-
- SIZE_MAP = {
- TYPE_VOIDP => SIZEOF_VOIDP,
- TYPE_CHAR => SIZEOF_CHAR,
- TYPE_SHORT => SIZEOF_SHORT,
- TYPE_INT => SIZEOF_INT,
- TYPE_LONG => SIZEOF_LONG,
- TYPE_FLOAT => SIZEOF_FLOAT,
- TYPE_DOUBLE => SIZEOF_DOUBLE,
- -TYPE_CHAR => SIZEOF_CHAR,
- -TYPE_SHORT => SIZEOF_SHORT,
- -TYPE_INT => SIZEOF_INT,
- -TYPE_LONG => SIZEOF_LONG,
- }
- if defined?(TYPE_LONG_LONG)
- ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[-TYPE_LONG_LONG] = ALIGN_LONG_LONG
- PACK_MAP[TYPE_LONG_LONG] = PACK_MAP[-TYPE_LONG_LONG] = "q"
- SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[-TYPE_LONG_LONG] = SIZEOF_LONG_LONG
- end
-
- def align(addr, align)
- d = addr % align
- if( d == 0 )
- addr
- else
- addr + (align - d)
- end
- end
- module_function :align
- end
-
- class Packer # :nodoc: all
- include PackInfo
-
- def self.[](*types)
- new(types)
- end
-
- def initialize(types)
- parse_types(types)
- end
-
- def size()
- @size
- end
-
- def pack(ary)
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- ary.pack(@template)
- when SIZEOF_LONG_LONG
- ary.pack(@template)
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
-
- def unpack(ary)
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- ary.join().unpack(@template)
- when SIZEOF_LONG_LONG
- ary.join().unpack(@template)
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
-
- private
-
- def parse_types(types)
- @template = ""
- addr = 0
- types.each{|t|
- orig_addr = addr
- if( t.is_a?(Array) )
- addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP])
- else
- addr = align(orig_addr, ALIGN_MAP[t])
- end
- d = addr - orig_addr
- if( d > 0 )
- @template << "x#{d}"
- end
- if( t.is_a?(Array) )
- @template << (PACK_MAP[t[0]] * t[1])
- addr += (SIZE_MAP[t[0]] * t[1])
- else
- @template << PACK_MAP[t]
- addr += SIZE_MAP[t]
- end
- }
- addr = align(addr, ALIGN_MAP[TYPE_VOIDP])
- @size = addr
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb
deleted file mode 100644
index 695a4d2247..0000000000
--- a/ext/fiddle/lib/fiddle/struct.rb
+++ /dev/null
@@ -1,243 +0,0 @@
-require 'fiddle'
-require 'fiddle/value'
-require 'fiddle/pack'
-
-module Fiddle
- # C struct shell
- class CStruct
- # accessor to Fiddle::CStructEntity
- def CStruct.entity_class
- CStructEntity
- end
- end
-
- # C union shell
- class CUnion
- # accessor to Fiddle::CUnionEntity
- def CUnion.entity_class
- CUnionEntity
- end
- end
-
- # Used to construct C classes (CUnion, CStruct, etc)
- #
- # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
- # easy-to-use manner.
- module CStructBuilder
- # Construct a new class given a C:
- # * class +klass+ (CUnion, CStruct, or other that provide an
- # #entity_class)
- # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types
- # constants)
- # * corresponding +members+
- #
- # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
- # easy-to-use manner.
- #
- # Example:
- #
- # require 'fiddle/struct'
- # require 'fiddle/cparser'
- #
- # include Fiddle::CParser
- #
- # types, members = parse_struct_signature(['int i','char c'])
- #
- # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
- #
- # obj = MyStruct.allocate
- #
- def create(klass, types, members)
- new_class = Class.new(klass){
- define_method(:initialize){|addr|
- @entity = klass.entity_class.new(addr, types)
- @entity.assign_names(members)
- }
- define_method(:to_ptr){ @entity }
- define_method(:to_i){ @entity.to_i }
- members.each{|name|
- define_method(name){ @entity[name] }
- define_method(name + "="){|val| @entity[name] = val }
- }
- }
- size = klass.entity_class.size(types)
- new_class.module_eval(<<-EOS, __FILE__, __LINE__+1)
- def new_class.size()
- #{size}
- end
- def new_class.malloc()
- addr = Fiddle.malloc(#{size})
- new(addr)
- end
- EOS
- return new_class
- end
- module_function :create
- end
-
- # A C struct wrapper
- class CStructEntity < Fiddle::Pointer
- include PackInfo
- include ValueUtil
-
- # Allocates a C struct with the +types+ provided.
- #
- # When the instance is garbage collected, the C function +func+ is called.
- def CStructEntity.malloc(types, func = nil)
- addr = Fiddle.malloc(CStructEntity.size(types))
- CStructEntity.new(addr, types, func)
- end
-
- # Returns the offset for the packed sizes for the given +types+.
- #
- # Fiddle::CStructEntity.size(
- # [ Fiddle::TYPE_DOUBLE,
- # Fiddle::TYPE_INT,
- # Fiddle::TYPE_CHAR,
- # Fiddle::TYPE_VOIDP ]) #=> 24
- def CStructEntity.size(types)
- offset = 0
-
- max_align = types.map { |type, count = 1|
- last_offset = offset
-
- align = PackInfo::ALIGN_MAP[type]
- offset = PackInfo.align(last_offset, align) +
- (PackInfo::SIZE_MAP[type] * count)
-
- align
- }.max
-
- PackInfo.align(offset, max_align)
- end
-
- # Wraps the C pointer +addr+ as a C struct with the given +types+.
- #
- # When the instance is garbage collected, the C function +func+ is called.
- #
- # See also Fiddle::Pointer.new
- def initialize(addr, types, func = nil)
- set_ctypes(types)
- super(addr, @size, func)
- end
-
- # Set the names of the +members+ in this C struct
- def assign_names(members)
- @members = members
- end
-
- # Calculates the offsets and sizes for the given +types+ in the struct.
- def set_ctypes(types)
- @ctypes = types
- @offset = []
- offset = 0
-
- max_align = types.map { |type, count = 1|
- orig_offset = offset
- align = ALIGN_MAP[type]
- offset = PackInfo.align(orig_offset, align)
-
- @offset << offset
-
- offset += (SIZE_MAP[type] * count)
-
- align
- }.max
-
- @size = PackInfo.align(offset, max_align)
- end
-
- # Fetch struct member +name+
- def [](name)
- idx = @members.index(name)
- if( idx.nil? )
- raise(ArgumentError, "no such member: #{name}")
- end
- ty = @ctypes[idx]
- if( ty.is_a?(Array) )
- r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
- else
- r = super(@offset[idx], SIZE_MAP[ty.abs])
- end
- packer = Packer.new([ty])
- val = packer.unpack([r])
- case ty
- when Array
- case ty[0]
- when TYPE_VOIDP
- val = val.collect{|v| Pointer.new(v)}
- end
- when TYPE_VOIDP
- val = Pointer.new(val[0])
- else
- val = val[0]
- end
- if( ty.is_a?(Integer) && (ty < 0) )
- return unsigned_value(val, ty)
- elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return val.collect{|v| unsigned_value(v,ty[0])}
- else
- return val
- end
- end
-
- # Set struct member +name+, to value +val+
- def []=(name, val)
- idx = @members.index(name)
- if( idx.nil? )
- raise(ArgumentError, "no such member: #{name}")
- end
- ty = @ctypes[idx]
- packer = Packer.new([ty])
- val = wrap_arg(val, ty, [])
- buff = packer.pack([val].flatten())
- super(@offset[idx], buff.size, buff)
- if( ty.is_a?(Integer) && (ty < 0) )
- return unsigned_value(val, ty)
- elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return val.collect{|v| unsigned_value(v,ty[0])}
- else
- return val
- end
- end
-
- def to_s() # :nodoc:
- super(@size)
- end
- end
-
- # A C union wrapper
- class CUnionEntity < CStructEntity
- include PackInfo
-
- # Allocates a C union the +types+ provided.
- #
- # When the instance is garbage collected, the C function +func+ is called.
- def CUnionEntity.malloc(types, func=nil)
- addr = Fiddle.malloc(CUnionEntity.size(types))
- CUnionEntity.new(addr, types, func)
- end
-
- # Returns the size needed for the union with the given +types+.
- #
- # Fiddle::CUnionEntity.size(
- # [ Fiddle::TYPE_DOUBLE,
- # Fiddle::TYPE_INT,
- # Fiddle::TYPE_CHAR,
- # Fiddle::TYPE_VOIDP ]) #=> 8
- def CUnionEntity.size(types)
- types.map { |type, count = 1|
- PackInfo::SIZE_MAP[type] * count
- }.max
- end
-
- # Calculate the necessary offset and for each union member with the given
- # +types+
- def set_ctypes(types)
- @ctypes = types
- @offset = Array.new(types.length, 0)
- @size = self.class.size types
- end
- end
-end
-
diff --git a/ext/fiddle/lib/fiddle/types.rb b/ext/fiddle/lib/fiddle/types.rb
deleted file mode 100644
index 02c1d25a37..0000000000
--- a/ext/fiddle/lib/fiddle/types.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-module Fiddle
- # Adds Windows type aliases to the including class for use with
- # Fiddle::Importer.
- #
- # The aliases added are:
- # * ATOM
- # * BOOL
- # * BYTE
- # * DWORD
- # * DWORD32
- # * DWORD64
- # * HANDLE
- # * HDC
- # * HINSTANCE
- # * HWND
- # * LPCSTR
- # * LPSTR
- # * PBYTE
- # * PDWORD
- # * PHANDLE
- # * PVOID
- # * PWORD
- # * UCHAR
- # * UINT
- # * ULONG
- # * WORD
- module Win32Types
- def included(m) # :nodoc:
- m.module_eval{
- typealias "DWORD", "unsigned long"
- typealias "PDWORD", "unsigned long *"
- typealias "DWORD32", "unsigned long"
- typealias "DWORD64", "unsigned long long"
- typealias "WORD", "unsigned short"
- typealias "PWORD", "unsigned short *"
- typealias "BOOL", "int"
- typealias "ATOM", "int"
- typealias "BYTE", "unsigned char"
- typealias "PBYTE", "unsigned char *"
- typealias "UINT", "unsigned int"
- typealias "ULONG", "unsigned long"
- typealias "UCHAR", "unsigned char"
- typealias "HANDLE", "uintptr_t"
- typealias "PHANDLE", "void*"
- typealias "PVOID", "void*"
- typealias "LPCSTR", "char*"
- typealias "LPSTR", "char*"
- typealias "HINSTANCE", "unsigned int"
- typealias "HDC", "unsigned int"
- typealias "HWND", "unsigned int"
- }
- end
- module_function :included
- end
-
- # Adds basic type aliases to the including class for use with Fiddle::Importer.
- #
- # The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and
- # +ulong+ and +u_long+ (<tt>unsigned long</tt>)
- module BasicTypes
- def included(m) # :nodoc:
- m.module_eval{
- typealias "uint", "unsigned int"
- typealias "u_int", "unsigned int"
- typealias "ulong", "unsigned long"
- typealias "u_long", "unsigned long"
- }
- end
- module_function :included
- end
-end
diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb
deleted file mode 100644
index 8d71e47ce6..0000000000
--- a/ext/fiddle/lib/fiddle/value.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-require 'fiddle'
-
-module Fiddle
- module ValueUtil #:nodoc: all
- def unsigned_value(val, ty)
- case ty.abs
- when TYPE_CHAR
- [val].pack("c").unpack("C")[0]
- when TYPE_SHORT
- [val].pack("s!").unpack("S!")[0]
- when TYPE_INT
- [val].pack("i!").unpack("I!")[0]
- when TYPE_LONG
- [val].pack("l!").unpack("L!")[0]
- when TYPE_LONG_LONG
- [val].pack("q").unpack("Q")[0]
- else
- val
- end
- end
-
- def signed_value(val, ty)
- case ty.abs
- when TYPE_CHAR
- [val].pack("C").unpack("c")[0]
- when TYPE_SHORT
- [val].pack("S!").unpack("s!")[0]
- when TYPE_INT
- [val].pack("I!").unpack("i!")[0]
- when TYPE_LONG
- [val].pack("L!").unpack("l!")[0]
- when TYPE_LONG_LONG
- [val].pack("Q").unpack("q")[0]
- else
- val
- end
- end
-
- def wrap_args(args, tys, funcs, &block)
- result = []
- tys ||= []
- args.each_with_index{|arg, idx|
- result.push(wrap_arg(arg, tys[idx], funcs, &block))
- }
- result
- end
-
- def wrap_arg(arg, ty, funcs = [], &block)
- funcs ||= []
- case arg
- when nil
- return 0
- when Pointer
- return arg.to_i
- when IO
- case ty
- when TYPE_VOIDP
- return Pointer[arg].to_i
- else
- return arg.to_i
- end
- when Function
- if( block )
- arg.bind_at_call(&block)
- funcs.push(arg)
- elsif !arg.bound?
- raise(RuntimeError, "block must be given.")
- end
- return arg.to_i
- when String
- if( ty.is_a?(Array) )
- return arg.unpack('C*')
- else
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- return [arg].pack("p").unpack("l!")[0]
- when SIZEOF_LONG_LONG
- return [arg].pack("p").unpack("q")[0]
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
- when Float, Integer
- return arg
- when Array
- if( ty.is_a?(Array) ) # used only by struct
- case ty[0]
- when TYPE_VOIDP
- return arg.collect{|v| Integer(v)}
- when TYPE_CHAR
- if( arg.is_a?(String) )
- return val.unpack('C*')
- end
- end
- return arg
- else
- return arg
- end
- else
- if( arg.respond_to?(:to_ptr) )
- return arg.to_ptr.to_i
- else
- begin
- return Integer(arg)
- rescue
- raise(ArgumentError, "unknown argument type: #{arg.class}")
- end
- end
- end
- end
- end
-end
diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
deleted file mode 100644
index fb9b31012f..0000000000
--- a/ext/fiddle/pointer.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby/ruby.h>
-#include <ruby/io.h>
-#include <ctype.h>
-#include <fiddle.h>
-
-VALUE rb_cPointer;
-
-typedef void (*freefunc_t)(void*);
-
-struct ptr_data {
- void *ptr;
- long size;
- freefunc_t free;
- VALUE wrap[2];
-};
-
-#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj)))
-
-static inline freefunc_t
-get_freefunc(VALUE func, volatile VALUE *wrap)
-{
- VALUE addrnum;
- if (NIL_P(func)) {
- *wrap = 0;
- return NULL;
- }
- addrnum = rb_Integer(func);
- *wrap = (addrnum != func) ? func : 0;
- return (freefunc_t)(VALUE)NUM2PTR(addrnum);
-}
-
-static ID id_to_ptr;
-
-static void
-fiddle_ptr_mark(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->wrap[0]) {
- rb_gc_mark(data->wrap[0]);
- }
- if (data->wrap[1]) {
- rb_gc_mark(data->wrap[1]);
- }
-}
-
-static void
-fiddle_ptr_free(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->ptr) {
- if (data->free) {
- (*(data->free))(data->ptr);
- }
- }
-}
-
-static size_t
-fiddle_ptr_memsize(const void *ptr)
-{
- const struct ptr_data *data = ptr;
- return data ? sizeof(*data) + data->size : 0;
-}
-
-static const rb_data_type_t fiddle_ptr_data_type = {
- "fiddle/pointer",
- {fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
-};
-
-static VALUE
-rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
-{
- struct ptr_data *data;
- VALUE val;
-
- rb_secure(4);
- val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
- data->ptr = ptr;
- data->free = func;
- data->size = size;
- OBJ_TAINT(val);
-
- return val;
-}
-
-static VALUE
-rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
-{
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func);
-}
-
-static VALUE
-rb_fiddle_ptr_malloc(long size, freefunc_t func)
-{
- void *ptr;
-
- rb_secure(4);
- ptr = ruby_xmalloc((size_t)size);
- memset(ptr,0,(size_t)size);
- return rb_fiddle_ptr_new(ptr, size, func);
-}
-
-static void *
-rb_fiddle_ptr2cptr(VALUE val)
-{
- struct ptr_data *data;
- void *ptr;
-
- if (rb_obj_is_kind_of(val, rb_cPointer)) {
- TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data);
- ptr = data->ptr;
- }
- else if (val == Qnil) {
- ptr = NULL;
- }
- else{
- rb_raise(rb_eTypeError, "Fiddle::Pointer was expected");
- }
-
- return ptr;
-}
-
-static VALUE
-rb_fiddle_ptr_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct ptr_data *data;
-
- rb_secure(4);
- obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
- data->ptr = 0;
- data->size = 0;
- data->free = 0;
-
- return obj;
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.new(address) => fiddle_cptr
- * new(address, size) => fiddle_cptr
- * new(address, size, freefunc) => fiddle_cptr
- *
- * Create a new pointer to +address+ with an optional +size+ and +freefunc+.
- *
- * +freefunc+ will be called when the instance is garbage collected.
- */
-static VALUE
-rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
-{
- VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
- struct ptr_data *data;
- void *p = NULL;
- freefunc_t f = NULL;
- long s = 0;
-
- if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
- VALUE addrnum = rb_Integer(ptr);
- if (addrnum != ptr) wrap = ptr;
- p = NUM2PTR(addrnum);
- }
- if (argc >= 2) {
- s = NUM2LONG(size);
- }
- if (argc >= 3) {
- f = get_freefunc(sym, &funcwrap);
- }
-
- if (p) {
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (data->ptr && data->free) {
- /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
- (*(data->free))(data->ptr);
- }
- data->wrap[0] = wrap;
- data->wrap[1] = funcwrap;
- data->ptr = p;
- data->size = s;
- data->free = f;
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- *
- * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
- *
- * Allocate +size+ bytes of memory and associate it with an optional
- * +freefunc+ that will be called when the pointer is garbage collected.
- *
- * +freefunc+ must be an address pointing to a function or an instance of
- * Fiddle::Function
- */
-static VALUE
-rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
-{
- VALUE size, sym, obj, wrap = 0;
- long s;
- freefunc_t f;
-
- switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
- case 1:
- s = NUM2LONG(size);
- f = NULL;
- break;
- case 2:
- s = NUM2LONG(size);
- f = get_freefunc(sym, &wrap);
- break;
- default:
- rb_bug("rb_fiddle_ptr_s_malloc");
- }
-
- obj = rb_fiddle_ptr_malloc(s,f);
- if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
-
- return obj;
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the integer memory location of this pointer.
- */
-static VALUE
-rb_fiddle_ptr_to_i(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return PTR2NUM(data->ptr);
-}
-
-/*
- * call-seq: to_value
- *
- * Cast this pointer to a ruby object.
- */
-static VALUE
-rb_fiddle_ptr_to_value(VALUE self)
-{
- struct ptr_data *data;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return (VALUE)(data->ptr);
-}
-
-/*
- * call-seq: ptr
- *
- * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for
- * this pointer.
- *
- * Analogous to the star operator in C.
- */
-static VALUE
-rb_fiddle_ptr_ptr(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0);
-}
-
-/*
- * call-seq: ref
- *
- * Returns a new Fiddle::Pointer instance that is a reference pointer for this
- * pointer.
- *
- * Analogous to the ampersand operator in C.
- */
-static VALUE
-rb_fiddle_ptr_ref(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return rb_fiddle_ptr_new(&(data->ptr),0,0);
-}
-
-/*
- * call-seq: null?
- *
- * Returns +true+ if this is a null pointer.
- */
-static VALUE
-rb_fiddle_ptr_null_p(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return data->ptr ? Qfalse : Qtrue;
-}
-
-/*
- * call-seq: free=(function)
- *
- * Set the free function for this pointer to +function+ in the given
- * Fiddle::Function.
- */
-static VALUE
-rb_fiddle_ptr_free_set(VALUE self, VALUE val)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- data->free = get_freefunc(val, &data->wrap[1]);
-
- return Qnil;
-}
-
-/*
- * call-seq: free => Fiddle::Function
- *
- * Get the free function for this pointer.
- *
- * Returns a new instance of Fiddle::Function.
- *
- * See Fiddle::Function.new
- */
-static VALUE
-rb_fiddle_ptr_free_get(VALUE self)
-{
- struct ptr_data *pdata;
- VALUE address;
- VALUE arg_types;
- VALUE ret_type;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
-
- if (!pdata->free)
- return Qnil;
-
- address = PTR2NUM(pdata->free);
- ret_type = INT2NUM(TYPE_VOID);
- arg_types = rb_ary_new();
- rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));
-
- return rb_fiddle_new_function(address, arg_types, ret_type);
-}
-
-/*
- * call-seq:
- *
- * ptr.to_s => string
- * ptr.to_s(len) => string
- *
- * Returns the pointer contents as a string.
- *
- * When called with no arguments, this method will return the contents until
- * the first NULL byte.
- *
- * When called with +len+, a string of +len+ bytes will be returned.
- *
- * See to_str
- */
-static VALUE
-rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, 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_fiddle_ptr_to_s");
- }
-
- return val;
-}
-
-/*
- * call-seq:
- *
- * ptr.to_str => string
- * ptr.to_str(len) => string
- *
- * Returns the pointer contents as a string.
- *
- * When called with no arguments, this method will return the contents with the
- * length of this pointer's +size+.
- *
- * When called with +len+, a string of +len+ bytes will be returned.
- *
- * See to_s
- */
-static VALUE
-rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, 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_fiddle_ptr_to_str");
- }
-
- return val;
-}
-
-/*
- * call-seq: inspect
- *
- * Returns a string formatted with an easily readable representation of the
- * internal state of the pointer.
- */
-static VALUE
-rb_fiddle_ptr_inspect(VALUE self)
-{
- struct ptr_data *data;
- char str[1024];
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- snprintf(str, 1023, "#<%s:%p ptr=%p size=%ld free=%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
- return rb_str_new2(str);
-}
-
-/*
- * call-seq:
- * ptr == other => true or false
- * ptr.eql?(other) => true or false
- *
- * Returns true if +other+ wraps the same pointer, otherwise returns
- * false.
- */
-static VALUE
-rb_fiddle_ptr_eql(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;
-
- ptr1 = rb_fiddle_ptr2cptr(self);
- ptr2 = rb_fiddle_ptr2cptr(other);
-
- return ptr1 == ptr2 ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- * ptr <=> other => -1, 0, 1, or nil
- *
- * Returns -1 if less than, 0 if equal to, 1 if greater than +other+.
- *
- * Returns nil if +ptr+ cannot be compared to +other+.
- */
-static VALUE
-rb_fiddle_ptr_cmp(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
- SIGNED_VALUE diff;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;
-
- ptr1 = rb_fiddle_ptr2cptr(self);
- ptr2 = rb_fiddle_ptr2cptr(other);
- diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
- if (!diff) return INT2FIX(0);
- return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
-}
-
-/*
- * call-seq:
- * ptr + n => new cptr
- *
- * Returns a new pointer instance that has been advanced +n+ bytes.
- */
-static VALUE
-rb_fiddle_ptr_plus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_fiddle_ptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0);
-}
-
-/*
- * call-seq:
- * ptr - n => new cptr
- *
- * Returns a new pointer instance that has been moved back +n+ bytes.
- */
-static VALUE
-rb_fiddle_ptr_minus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_fiddle_ptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0);
-}
-
-/*
- * call-seq:
- * ptr[index] -> an_integer
- * ptr[start, length] -> a_string
- *
- * Returns integer stored at _index_.
- *
- * If _start_ and _length_ are given, a string containing the bytes from
- * _start_ of _length_ will be returned.
- */
-static VALUE
-rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1;
- VALUE retval = Qnil;
- size_t offset, len;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
- case 1:
- offset = NUM2ULONG(arg0);
- retval = INT2NUM(*((char *)data->ptr + offset));
- break;
- case 2:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- retval = rb_tainted_str_new((char *)data->ptr + offset, len);
- break;
- default:
- rb_bug("rb_fiddle_ptr_aref()");
- }
- return retval;
-}
-
-/*
- * call-seq:
- * ptr[index] = int -> int
- * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr
- *
- * Set the value at +index+ to +int+.
- *
- * Or, set the memory at +start+ until +length+ with the contents of +string+,
- * the memory from +dl_cptr+, or the memory pointed at by the memory address
- * +addr+.
- */
-static VALUE
-rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1, arg2;
- VALUE retval = Qnil;
- size_t offset, len;
- void *mem;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
- case 2:
- offset = NUM2ULONG(arg0);
- ((char*)data->ptr)[offset] = NUM2UINT(arg1);
- retval = arg1;
- break;
- case 3:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- if (RB_TYPE_P(arg2, T_STRING)) {
- mem = StringValuePtr(arg2);
- }
- else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
- mem = rb_fiddle_ptr2cptr(arg2);
- }
- else{
- mem = NUM2PTR(arg2);
- }
- memcpy((char *)data->ptr + offset, mem, len);
- retval = arg2;
- break;
- default:
- rb_bug("rb_fiddle_ptr_aset()");
- }
- return retval;
-}
-
-/*
- * call-seq: size=(size)
- *
- * Set the size of this pointer to +size+
- */
-static VALUE
-rb_fiddle_ptr_size_set(VALUE self, VALUE size)
-{
- RPTR_DATA(self)->size = NUM2LONG(size);
- return size;
-}
-
-/*
- * call-seq: size
- *
- * Get the size of this pointer.
- */
-static VALUE
-rb_fiddle_ptr_size_get(VALUE self)
-{
- return LONG2NUM(RPTR_DATA(self)->size);
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer[val] => cptr
- * to_ptr(val) => cptr
- *
- * Get the underlying pointer for ruby object +val+ and return it as a
- * Fiddle::Pointer object.
- */
-static VALUE
-rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
-{
- VALUE ptr, wrap = val, vptr;
-
- if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
- rb_io_t *fptr;
- FILE *fp;
- GetOpenFile(val, fptr);
- fp = rb_io_stdio_file(fptr);
- ptr = rb_fiddle_ptr_new(fp, 0, NULL);
- }
- else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
- char *str = StringValuePtr(val);
- ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
- }
- else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
- if (rb_obj_is_kind_of(vptr, rb_cPointer)){
- ptr = vptr;
- wrap = 0;
- }
- else{
- rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
- }
- }
- else{
- VALUE num = rb_Integer(val);
- if (num == val) wrap = 0;
- ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
- }
- OBJ_INFECT(ptr, val);
- if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
- return ptr;
-}
-
-void
-Init_fiddle_pointer(void)
-{
- id_to_ptr = rb_intern("to_ptr");
-
- /* Document-class: Fiddle::Pointer
- *
- * Fiddle::Pointer is a class to handle C pointers
- *
- */
- rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject);
- rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate);
- rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1);
- rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1);
- rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1);
- rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
- rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
- rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0);
- rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0);
- rb_define_method(rb_cPointer, "ptr", rb_fiddle_ptr_ptr, 0);
- rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0);
- rb_define_method(rb_cPointer, "ref", rb_fiddle_ptr_ref, 0);
- rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0);
- rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0);
- rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1);
- rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1);
- rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0);
- rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1);
- rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1);
- rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1);
- rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1);
- rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1);
- rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1);
- rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1);
- rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
- rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
-
- /* Document-const: NULL
- *
- * A NULL pointer
- */
- rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0));
-}
diff --git a/ext/fiddle/win32/extconf.rb b/ext/fiddle/win32/extconf.rb
deleted file mode 100644
index c4efee8149..0000000000
--- a/ext/fiddle/win32/extconf.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-if compiled?('fiddle') and $mswin||$mingw||$cygwin
- create_makefile('win32')
-end
diff --git a/ext/fiddle/win32/lib/win32/registry.rb b/ext/fiddle/win32/lib/win32/registry.rb
deleted file mode 100644
index f1aa3640a8..0000000000
--- a/ext/fiddle/win32/lib/win32/registry.rb
+++ /dev/null
@@ -1,845 +0,0 @@
-require 'fiddle/import'
-module Win32
-
-=begin rdoc
-= Win32 Registry
-
-win32/registry is registry accessor library for Win32 platform.
-It uses fiddle/import 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
-
---- info
-
---- 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 the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article.
-
-=end rdoc
-
- class Registry
-
- #
- # For detail, see the MSDN[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.
- 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
- module Kernel32
- extend Fiddle::Importer
- dlload "kernel32.dll"
- end
- FormatMessageA = Kernel32.extern "int FormatMessageA(int, void *, int, int, void *, int, void *)", :stdcall
- def initialize(code)
- @code = code
- msg = "\0".force_encoding(Encoding::ASCII_8BIT) * 1024
- len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
- msg = msg[0, len].force_encoding(Encoding.find(Encoding.locale_charmap))
- super msg.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 method 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.to_s)
- end
- end
-
- #
- # Win32 APIs
- #
- module API
- extend Fiddle::Importer
- dlload "advapi32.dll"
- [
- "long RegOpenKeyExA(void *, void *, long, long, void *)",
- "long RegCreateKeyExA(void *, void *, long, long, long, long, void *, void *, void *)",
- "long RegEnumValueA(void *, long, void *, void *, void *, void *, void *, void *)",
- "long RegEnumKeyExA(void *, long, void *, void *, void *, void *, void *, void *)",
- "long RegQueryValueExA(void *, void *, void *, void *, void *, void *)",
- "long RegSetValueExA(void *, void *, long, long, void *, long)",
- "long RegDeleteValue(void *, void *)",
- "long RegDeleteKey(void *, void *)",
- "long RegFlushKey(void *)",
- "long RegCloseKey(void *)",
- "long RegQueryInfoKey(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)",
- ].each do |fn|
- cfunc = extern fn, :stdcall
- const_set cfunc.name.intern, cfunc
- 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
-
- #
- # Replace %\w+% into the environment value of what is contained between the %'s
- # This method is used for REG_EXPAND_SZ.
- #
- # For detail, see expandEnvironmentStrings[http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp] \Win32 \API.
- #
- def self.expand_environ(str)
- str.gsub(/%([^%]+)%/) { ENV[$1] || ENV[$1.upcase] || $& }
- 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
-
- #
- # Convert registry type value to readable string.
- #
- def self.type2name(type)
- @@type2name[type] || type.to_s
- end
-
- #
- # Convert 64-bit FILETIME integer into Time object.
- #
- def self.wtime2time(wtime)
- Time.at((wtime - 116444736000000000) / 10000000)
- end
-
- #
- # Convert Time object or Integer object into 64-bit FILETIME.
- #
- def self.time2wtime(time)
- time.to_i * 10000000 + 116444736000000000
- end
-
- #
- # constructor
- #
- private_class_method :new
-
- #
- # --- 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 the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp].
- # If block is given, the key is closed automatically.
- 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
-
- #
- # --- 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.
- #
- 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
-
- # Returns key handle value.
- attr_reader :hkey
- # Win32::Registry object of parent key, or nil if predefeined key.
- attr_reader :parent
- # Same as subkey value of Registry.open or
- # Registry.create method.
- attr_reader :keyname
- # Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY).
- attr_reader :disposition
-
- #
- # Returns if key is created ((*newly*)).
- # (see Registry.create) -- basically you call create
- # then when you call created? on the instance returned
- # it will tell if it was successful or not
- #
- def created?
- @disposition == REG_CREATED_NEW_KEY
- end
-
- #
- # Returns if key is not closed.
- #
- def open?
- !@hkey.nil?
- end
-
- #
- # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'.
- #
- 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 is not allowed
- #
- def _dump(depth)
- raise TypeError, "can't dump Win32::Registry"
- end
-
- #
- # Same as Win32::Registry.open (self, subkey, desired, opt)
- #
- def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk)
- self.class.open(self, subkey, desired, opt, &blk)
- end
-
- #
- # Same as Win32::Registry.create (self, subkey, desired, opt)
- #
- def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
- self.class.create(self, subkey, desired, opt, &blk)
- end
-
- #
- # Close key.
- #
- # After close, most method raise an error.
- #
- def close
- API.CloseKey(@hkey)
- @hkey = @parent = @keyname = nil
- @hkeyfinal[0] = nil
- end
-
- #
- # Enumerate values.
- #
- 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
-
- #
- # Enumerate subkeys.
- #
- # subkey is String which contains name of subkey.
- # wtime is last write time as FILETIME (64-bit integer).
- # (see Registry.wtime2time)
- #
- 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
-
- #
- # return keys as an array
- #
- def keys
- keys_ary = []
- each_key { |key,| keys_ary << key }
- keys_ary
- end
-
- # 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.
- 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
-
- #
- # 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.
- #
- 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
-
- # 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.
- def read_s(name)
- read(name, REG_SZ)[1]
- end
-
- #
- # 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.
- #
- 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
-
- #
- # 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.
- #
- def read_i(name)
- read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1]
- end
-
- #
- # 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.
- #
- def read_bin(name)
- read(name, REG_BINARY)[1]
- end
-
- #
- # 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.
- #
- 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
-
- #
- # 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
- #
- 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
-
- #
- # 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).
- #
- def write_s(name, value)
- write name, REG_SZ, value.to_s
- end
-
- #
- # 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).
- #
- def write_i(name, value)
- write name, REG_DWORD, value.to_i
- end
-
- #
- # 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).
- #
- def write_bin(name, value)
- write name, REG_BINARY, value.to_s
- end
-
- #
- # Delete a registry value named name.
- # We can not delete the `default' value.
- #
- def delete_value(name)
- API.DeleteValue(@hkey, name)
- end
- alias delete delete_value
-
- #
- # 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.
- #
- 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
-
- #
- # Write all the attributes into the registry file.
- #
- def flush
- API.FlushKey @hkey
- end
-
- #
- # 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[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API.
- #
- def info
- API.QueryInfoKey(@hkey)
- end
-
- #
- # Returns an item of key information.
- #
- %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/fiddle/win32/lib/win32/resolv.rb b/ext/fiddle/win32/lib/win32/resolv.rb
deleted file mode 100644
index 1315f32c61..0000000000
--- a/ext/fiddle/win32/lib/win32/resolv.rb
+++ /dev/null
@@ -1,379 +0,0 @@
-=begin
-= Win32 DNS and DHCP I/F
-
-=end
-
-require "fiddle/import"
-require 'win32/registry'
-
-module Win32
- module Resolv
- API = Registry::API
-
- def self.get_hosts_path
- path = get_hosts_dir
- path = File.expand_path('hosts', path)
- 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
-
-module Kernel32
- extend Fiddle::Importer
- dlload "kernel32"
-end
-getv = Kernel32.extern "int GetVersionExA(void *)", :stdcall
-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+\./ =~ nvdom
- devo = $'
- end
- end
- end
- rescue Registry::Error
- end
- end
-
- reg.open('Interfaces') do |h|
- h.each_key do |iface,|
- h.open(iface) do |regif|
- begin
- [ 'NameServer', 'DhcpNameServer' ].each do |key|
- begin
- ns = regif.read_s(key)
- rescue
- else
- unless ns.empty?
- nameserver.concat(ns.split(/[,\s]\s*/))
- break
- end
- 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
- module WSock32
- extend Fiddle::Importer
- dlload "wsock32.dll"
- end
- WsControl = WSock32.extern "int WsControl(int, int, void *, void *, void *, void *", :stdcall
- WSAGetLastError = WSock32.extern "int WSAGetLastError(void)", :stdcall
-
- 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