From 6175ca03be6d0d51359f9017123708987d0f5eb7 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Wed, 15 Aug 2007 23:23:39 +0000 Subject: add tag v1_8_5_91 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_5_91@13046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ruby_1_8_5/ext/dl/dl.c | 728 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 728 insertions(+) create mode 100644 ruby_1_8_5/ext/dl/dl.c (limited to 'ruby_1_8_5/ext/dl/dl.c') diff --git a/ruby_1_8_5/ext/dl/dl.c b/ruby_1_8_5/ext/dl/dl.c new file mode 100644 index 0000000000..71c353bda3 --- /dev/null +++ b/ruby_1_8_5/ext/dl/dl.c @@ -0,0 +1,728 @@ +/* + * $Id: dl.c,v 1.20.2.5 2005/12/16 13:32:06 ttate Exp $ + */ + +#include +#include +#include +#include "dl.h" + +VALUE rb_mDL; +VALUE rb_eDLError; +VALUE rb_eDLTypeError; + +static VALUE DLFuncTable; +static void *rb_dl_callback_table[CALLBACK_TYPES][MAX_CALLBACK]; +static ID id_call; + +static int +rb_dl_scan_callback_args(long stack[], const char *proto, + int *argc, VALUE argv[]) +{ + int i; + long *sp; + VALUE val; + + sp = stack; + for (i=1; proto[i]; i++) { + switch (proto[i]) { + case 'C': + { + char v; + v = (char)(*sp); + sp++; + val = INT2NUM(v); + } + break; + case 'H': + { + short v; + v = (short)(*sp); + sp++; + val = INT2NUM(v); + } + break; + case 'I': + { + int v; + v = (int)(*sp); + sp++; + val = INT2NUM(v); + } + break; + case 'L': + { + long v; + v = (long)(*sp); + sp++; + val = INT2NUM(v); + } + break; + case 'F': + { + float v; + memcpy(&v, sp, sizeof(float)); + sp += sizeof(float)/sizeof(long); + val = rb_float_new(v); + } + break; + case 'D': + { + double v; + memcpy(&v, sp, sizeof(double)); + sp += sizeof(double)/sizeof(long); + val = rb_float_new(v); + } + break; + case 'P': + { + void *v; + memcpy(&v, sp, sizeof(void*)); + sp++; + val = rb_dlptr_new(v, 0, 0); + } + break; + case 'S': + { + char *v; + memcpy(&v, sp, sizeof(void*)); + sp++; + val = rb_tainted_str_new2(v); + } + break; + default: + rb_raise(rb_eDLTypeError, "unsupported type `%c'", proto[i]); + break; + } + argv[i-1] = val; + } + *argc = (i - 1); + + return (*argc); +} + +#include "callback.func" + +static void +init_dl_func_table(){ +#include "cbtable.func" +} + +void * +dlmalloc(size_t size) +{ + DEBUG_CODE2({ + void *ptr; + + printf("dlmalloc(%d)",size); + ptr = xmalloc(size); + printf(":0x%x\n",ptr); + return ptr; + }, + { + return xmalloc(size); + }); +} + +void * +dlrealloc(void *ptr, size_t size) +{ + DEBUG_CODE({ + printf("dlrealloc(0x%x,%d)\n",ptr,size); + }); + return xrealloc(ptr, size); +} + +void +dlfree(void *ptr) +{ + DEBUG_CODE({ + printf("dlfree(0x%x)\n",ptr); + }); + xfree(ptr); +} + +char* +dlstrdup(const char *str) +{ + char *newstr; + + newstr = (char*)dlmalloc(strlen(str)+1); + strcpy(newstr,str); + + return newstr; +} + +size_t +dlsizeof(const char *cstr) +{ + size_t size; + int i, len, n, dlen; + char *d; + + len = strlen(cstr); + size = 0; + for (i=0; ilen; + *size = sizeof(float) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FLOAT: + ary[i] = (float)(RFLOAT(e)->value); + break; + case T_NIL: + ary[i] = 0.0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static double * +c_darray(VALUE v, long *size) +{ + int i, len; + double *ary; + VALUE e; + + len = RARRAY(v)->len; + *size = sizeof(double) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FLOAT: + ary[i] = (double)(RFLOAT(e)->value); + break; + case T_NIL: + ary[i] = 0.0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static long * +c_larray(VALUE v, long *size) +{ + int i, len; + long *ary; + VALUE e; + + len = RARRAY(v)->len; + *size = sizeof(long) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FIXNUM: + case T_BIGNUM: + ary[i] = (long)(NUM2INT(e)); + break; + case T_NIL: + ary[i] = 0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static int * +c_iarray(VALUE v, long *size) +{ + int i, len; + int *ary; + VALUE e; + + len = RARRAY(v)->len; + *size = sizeof(int) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FIXNUM: + case T_BIGNUM: + ary[i] = (int)(NUM2INT(e)); + break; + case T_NIL: + ary[i] = 0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static short * +c_harray(VALUE v, long *size) +{ + int i, len; + short *ary; + VALUE e; + + len = RARRAY(v)->len; + *size = sizeof(short) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FIXNUM: + case T_BIGNUM: + ary[i] = (short)(NUM2INT(e)); + break; + case T_NIL: + ary[i] = 0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static char * +c_carray(VALUE v, long *size) +{ + int i, len; + char *ary; + VALUE e; + + len = RARRAY(v)->len; + *size = sizeof(char) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + case T_FIXNUM: + case T_BIGNUM: + ary[i] = (char)(NUM2INT(e)); + break; + case T_NIL: + ary[i] = 0; + break; + default: + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + break; + } + } + + return ary; +} + +static void * +c_parray(VALUE v, long *size) +{ + int i, len; + void **ary; + VALUE e, tmp; + + len = RARRAY(v)->len; + *size = sizeof(void*) * len; + ary = dlmalloc(*size); + for (i=0; i < len; i++) { + e = rb_ary_entry(v, i); + switch (TYPE(e)) { + default: + tmp = rb_check_string_type(e); + if (NIL_P(tmp)) { + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + } + e = tmp; + /* fall through */ + case T_STRING: + rb_check_safe_str(e); + { + char *str, *src; + src = RSTRING(e)->ptr; + str = dlstrdup(src); + ary[i] = (void*)str; + } + break; + case T_NIL: + ary[i] = NULL; + break; + case T_DATA: + if (rb_obj_is_kind_of(e, rb_cDLPtrData)) { + struct ptr_data *pdata; + Data_Get_Struct(e, struct ptr_data, pdata); + ary[i] = (void*)(pdata->ptr); + } + else{ + e = rb_funcall(e, rb_intern("to_ptr"), 0); + if (rb_obj_is_kind_of(e, rb_cDLPtrData)) { + struct ptr_data *pdata; + Data_Get_Struct(e, struct ptr_data, pdata); + ary[i] = (void*)(pdata->ptr); + } + else{ + rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i); + } + } + break; + } + } + + return ary; +} + +void * +rb_ary2cary(char t, VALUE v, long *size) +{ + int len; + VALUE val0; + + val0 = rb_check_array_type(v); + if(NIL_P(val0)) { + rb_raise(rb_eDLTypeError, "an array is expected."); + } + v = val0; + + len = RARRAY(v)->len; + if (len == 0) { + return NULL; + } + + if (!size) { + size = ALLOCA_N(long,1); + } + + val0 = rb_ary_entry(v,0); + switch (TYPE(val0)) { + case T_FIXNUM: + case T_BIGNUM: + switch (t) { + case 'C': case 'c': + return (void*)c_carray(v,size); + case 'H': case 'h': + return (void*)c_harray(v,size); + case 'I': case 'i': + return (void*)c_iarray(v,size); + case 'L': case 'l': case 0: + return (void*)c_larray(v,size); + default: + rb_raise(rb_eDLTypeError, "type mismatch"); + } + case T_STRING: + return (void*)c_parray(v,size); + case T_FLOAT: + switch (t) { + case 'F': case 'f': + return (void*)c_farray(v,size); + case 'D': case 'd': case 0: + return (void*)c_darray(v,size); + } + rb_raise(rb_eDLTypeError, "type mismatch"); + case T_DATA: + if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) { + return (void*)c_parray(v,size); + } + else{ + val0 = rb_funcall(val0, rb_intern("to_ptr"), 0); + if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) { + return (void*)c_parray(v,size); + } + } + rb_raise(rb_eDLTypeError, "type mismatch"); + case T_NIL: + return (void*)c_parray(v, size); + default: + rb_raise(rb_eDLTypeError, "unsupported type"); + } +} + +VALUE +rb_str_to_ptr(VALUE self) +{ + char *ptr; + int len; + + len = RSTRING(self)->len; + ptr = (char*)dlmalloc(len + 1); + memcpy(ptr, RSTRING(self)->ptr, len); + ptr[len] = '\0'; + return rb_dlptr_new((void*)ptr,len,dlfree); +} + +VALUE +rb_ary_to_ptr(int argc, VALUE argv[], VALUE self) +{ + void *ptr; + VALUE t; + long size; + + switch (rb_scan_args(argc, argv, "01", &t)) { + case 1: + ptr = rb_ary2cary(StringValuePtr(t)[0], self, &size); + break; + case 0: + ptr = rb_ary2cary(0, self, &size); + break; + } + return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil; +} + +VALUE +rb_io_to_ptr(VALUE self) +{ + OpenFile *fptr; + FILE *fp; + + GetOpenFile(self, fptr); + fp = fptr->f; + + return fp ? rb_dlptr_new(fp, 0, 0) : Qnil; +} + +VALUE +rb_dl_dlopen(int argc, VALUE argv[], VALUE self) +{ + rb_secure(4); + return rb_class_new_instance(argc, argv, rb_cDLHandle); +} + +VALUE +rb_dl_malloc(VALUE self, VALUE size) +{ + rb_secure(4); + return rb_dlptr_malloc(DLNUM2LONG(size), dlfree); +} + +VALUE +rb_dl_strdup(VALUE self, VALUE str) +{ + SafeStringValue(str); + return rb_dlptr_new(strdup(RSTRING(str)->ptr), RSTRING(str)->len, dlfree); +} + +static VALUE +rb_dl_sizeof(VALUE self, VALUE str) +{ + return INT2NUM(dlsizeof(StringValuePtr(str))); +} + +static VALUE +rb_dl_callback(int argc, VALUE argv[], VALUE self) +{ + VALUE type, proc; + int rettype, entry, i; + char fname[127]; + + rb_secure(4); + proc = Qnil; + switch (rb_scan_args(argc, argv, "11", &type, &proc)) { + case 1: + if (rb_block_given_p()) { + proc = rb_block_proc(); + } + else{ + proc = Qnil; + } + default: + break; + } + + StringValue(type); + switch (RSTRING(type)->ptr[0]) { + case '0': + rettype = 0x00; + break; + case 'C': + rettype = 0x01; + break; + case 'H': + rettype = 0x02; + break; + case 'I': + rettype = 0x03; + break; + case 'L': + rettype = 0x04; + break; + case 'F': + rettype = 0x05; + break; + case 'D': + rettype = 0x06; + break; + case 'P': + rettype = 0x07; + break; + default: + rb_raise(rb_eDLTypeError, "unsupported type `%c'", RSTRING(type)->ptr[0]); + } + + entry = -1; + for (i=0; i < MAX_CALLBACK; i++) { + if (rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(rettype), INT2NUM(i))) == Qnil) { + entry = i; + break; + } + } + if (entry < 0) { + rb_raise(rb_eDLError, "too many callbacks are defined."); + } + + rb_hash_aset(DLFuncTable, + rb_assoc_new(INT2NUM(rettype),INT2NUM(entry)), + rb_assoc_new(type,proc)); + sprintf(fname, "rb_dl_callback_func_%d_%d", rettype, entry); + return rb_dlsym_new((void (*)())rb_dl_callback_table[rettype][entry], + fname, RSTRING(type)->ptr); +} + +static VALUE +rb_dl_remove_callback(VALUE mod, VALUE sym) +{ + freefunc_t f; + int i, j; + + rb_secure(4); + f = rb_dlsym2csym(sym); + for (i=0; i < CALLBACK_TYPES; i++) { + for (j=0; j < MAX_CALLBACK; j++) { + if (rb_dl_callback_table[i][j] == f) { + rb_hash_aset(DLFuncTable, rb_assoc_new(INT2NUM(i),INT2NUM(j)),Qnil); + break; + } + } + } + return Qnil; +} + +void +Init_dl() +{ + void Init_dlptr(); + void Init_dlsym(); + void Init_dlhandle(); + + id_call = rb_intern("call"); + + rb_mDL = rb_define_module("DL"); + + rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError); + rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError); + + DLFuncTable = rb_hash_new(); + init_dl_func_table(); + rb_define_const(rb_mDL, "FuncTable", DLFuncTable); + + rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); + rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); + rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW)); + + rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT)); + rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); + rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); + rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); + rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); + rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); + + rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG)); + rb_define_const(rb_mDL, "DLSTACK", rb_tainted_str_new2(DLSTACK_METHOD)); + + rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1); + rb_define_module_function(rb_mDL, "callback", rb_dl_callback, -1); + rb_define_module_function(rb_mDL, "define_callback", rb_dl_callback, -1); + rb_define_module_function(rb_mDL, "remove_callback", rb_dl_remove_callback, 1); + rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1); + rb_define_module_function(rb_mDL, "strdup", rb_dl_strdup, 1); + rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1); + + Init_dlptr(); + Init_dlsym(); + Init_dlhandle(); + + rb_define_const(rb_mDL, "FREE", rb_dlsym_new(dlfree, "free", "0P")); + + rb_define_method(rb_cString, "to_ptr", rb_str_to_ptr, 0); + rb_define_method(rb_cArray, "to_ptr", rb_ary_to_ptr, -1); + rb_define_method(rb_cIO, "to_ptr", rb_io_to_ptr, 0); +} -- cgit v1.2.3