Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Backport C-API needed for OpenSSL C-ext 2.x.
Browse files Browse the repository at this point in the history
brixen committed Jun 15, 2015
1 parent a97b41b commit 203f021
Showing 8 changed files with 425 additions and 20 deletions.
53 changes: 49 additions & 4 deletions vm/builtin/data.cpp
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@ namespace rubinius {
RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rdata(0));

rdata->data = data_ptr;
rdata->dmark = mark;
rdata->dfree = free;
rdata->d.untyped.dmark = mark;
rdata->d.untyped.dfree = free;

data->internal_ = rdata;

@@ -47,16 +47,60 @@ namespace rubinius {
return data;
}

Data* Data::create_typed(STATE, void* data_ptr, const struct rb_data_type_struct_shadow* type) {
Data* data;

data = state->new_object<Data>(G(data));
data->freed_ = false;

// Data is just a heap alias for the handle, so go ahead and create
// the handle and populate it as an RData now.
capi::Handle* handle = data->handle(state);

assert(!handle && "can't already have a handle, it's brand new!");

handle = state->memory()->add_capi_handle(state, data);

// Don't call ->ref() on handle! We don't want the handle to keep the object
// alive by default. The handle needs to have the lifetime of the object.

RDataShadow* rdata = reinterpret_cast<RDataShadow*>(handle->as_rtypeddata(0));

rdata->data = data_ptr;
rdata->d.typed.typed = 1;
rdata->d.typed.type = type;

data->internal_ = rdata;

if(type->function.dmark || type->function.dfree) {
state->memory()->needs_finalization(data, (FinalizerFunction)&Data::finalize);
}

state->vm()->metrics().m.ruby_metrics.memory_data_objects_total++;

return data;
}

void* Data::data() {
return rdata()->data;
}

Data::FreeFunctor Data::free() {
return rdata()->dfree;
RDataShadow* data = rdata();
if(typed()) {
return data->d.typed.type->function.dfree;
} else {
return data->d.untyped.dfree;
}
}

Data::MarkFunctor Data::mark() {
return rdata()->dmark;
RDataShadow* data = rdata();
if(typed()) {
return data->d.typed.type->function.dmark;
} else {
return data->d.untyped.dmark;
}
}

void Data::finalize(STATE, Data* data) {
@@ -126,4 +170,5 @@ namespace rubinius {
capi::set_current_mark(cur);
}
}

}
47 changes: 46 additions & 1 deletion vm/builtin/data.hpp
Original file line number Diff line number Diff line change
@@ -7,9 +7,40 @@ namespace rubinius {
// Copied from here because you can't include capi/include/ruby.h into
// our C++ files.

struct RDataShadow {
struct rb_data_type_struct_shadow {
const char *wrap_struct_name;
struct {
void (*dmark)(void*);
void (*dfree)(void*);
size_t (*dsize)(const void *);
void *reserved[2]; /* For future extension.
This array *must* be filled with ZERO. */
} function;
const struct rb_data_type_struct_shadow* parent;
void *data; /* This area can be used for any purpose
by a programmer who define the type. */
};

// This union crazyness is needed because these should be compatible
// for the data pointer. It is valid behavior to use DATA_PTR on both
// typed and untyped and get a valid result back.
// MRI constructs this differently, but this approach allows us to
// use this in a slightly more type safe and explicit way.
struct RUntypedDataShadow {
void (*dmark)(void*);
void (*dfree)(void*);
};

struct RTypedDataShadow {
const struct rb_data_type_struct_shadow* type;
native_int typed;
};

struct RDataShadow {
union {
RUntypedDataShadow untyped;
RTypedDataShadow typed;
} d;
void *data;
};

@@ -36,6 +67,9 @@ namespace rubinius {
/** New Data instance. */
static Data* create(STATE, void* data, MarkFunctor mark, FreeFunctor free);

/** New typed Data instance. */
static Data* create_typed(STATE, void* data, const struct rb_data_type_struct_shadow* type);

static void finalize(STATE, Data* data);

bool freed_p() const {
@@ -54,6 +88,17 @@ namespace rubinius {
return internal_;
}

bool typed() {
return rdata()->d.typed.typed == 1;
}

const struct rb_data_type_struct_shadow* data_type() {
if(typed()) {
return rdata()->d.typed.type;
}
return NULL;
}

void* data();
FreeFunctor free();
MarkFunctor mark();
77 changes: 77 additions & 0 deletions vm/capi/data.cpp
Original file line number Diff line number Diff line change
@@ -33,6 +33,29 @@ namespace rubinius {
return rdata;
}
}

RTypedData* Handle::as_rtypeddata(NativeMethodEnvironment* env) {
Data* data = c_as<Data>(object_);

if(data->freed_p()) {
rb_raise(rb_eArgError, "Data object has already been freed");
}

if(type_ == cRData) {
return as_.rtypeddata;
} else {
type_ = cRData;

RTypedData* rtypeddata = new RTypedData;
rtypeddata->data = 0;
rtypeddata->type = 0;
rtypeddata->typed_flag = 1;

as_.rtypeddata = rtypeddata;

return rtypeddata;
}
}
}
}

@@ -60,4 +83,58 @@ extern "C" {

return env->get_handle(data);
}

struct RTypedData* capi_rtypeddata_struct(VALUE data_handle) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

Handle* handle = Handle::from(data_handle);
env->check_tracked_handle(handle, false);

return handle->as_rtypeddata(env);
}

VALUE rb_data_typed_object_alloc(VALUE klass, void* ptr, const rb_data_type_t* type) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();

if(!klass) klass = rb_cObject;

Class* data_klass = c_as<Class>(env->get_object(klass));

Data* data = Data::create_typed(env->state(), ptr, reinterpret_cast<const struct rb_data_type_struct_shadow*>(type));

data->klass(env->state(), data_klass);

return env->get_handle(data);
}

int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent) {
while (child) {
if (child == parent) return 1;
child = child->parent;
}
return 0;
}

void* rb_check_typeddata(VALUE obj, const rb_data_type_t* data_type) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
const char* mesg = "wrong argument type %s (expected %s)";
Data* data = c_as<Data>(env->get_object(obj));
if(!data->typed()) {
rb_raise(rb_eTypeError, mesg, rb_obj_classname(obj), data_type->wrap_struct_name);
}

const rb_data_type_t* other_type = reinterpret_cast<const rb_data_type_t*>(data->data_type());

if (!rb_typeddata_inherited_p(other_type, data_type)) {
rb_raise(rb_eTypeError, mesg, other_type->wrap_struct_name, data_type->wrap_struct_name);
}
return data->data();
}

int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
Data* data = try_as<Data>(env->get_object(obj));
if(!data || !data->typed()) return 0;
return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type);
}
}
27 changes: 27 additions & 0 deletions vm/capi/file.cpp
Original file line number Diff line number Diff line change
@@ -28,11 +28,38 @@ extern "C" {
return Handle::from(file)->as_rfile(env);
}

int rb_cloexec_dup(int fd) {
return fcntl(fd, F_DUPFD_CLOEXEC, 3);
}

VALUE rb_file_open(const char* name, const char* mode) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
VALUE n = env->get_handle(String::create(env->state(), name));
VALUE m = env->get_handle(String::create(env->state(), mode));

return rb_funcall(rb_cFile, rb_intern("open"), 2, n, m);
}

FILE * rb_io_stdio_file(rb_io_t *fptr) {
return fptr->f;
}

VALUE rb_file_path_value(volatile VALUE* obj) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
STATE = env->state();

if(!kind_of<String>(env->get_object(*obj))) {
*obj = rb_funcall(env->get_handle(G(type)), rb_intern("coerce_to_path"), 1, *obj);
}

return *obj;
}

VALUE rb_file_open_str(VALUE name, const char* mode) {
NativeMethodEnvironment* env = NativeMethodEnvironment::get();
VALUE m = env->get_handle(String::create(env->state(), mode));

FilePathValue(name);
return rb_funcall(rb_cFile, rb_intern("open"), 2, name, m);
}
}
5 changes: 4 additions & 1 deletion vm/capi/handle.hpp
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@

#include "detection.hpp"

#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
#if defined(__APPLE__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070
#ifndef RBX_HAVE_TR1_HASH
#include "missing/leopard_hashtable.hpp"
#endif
@@ -23,6 +23,7 @@
struct RArray;
struct RString;
struct RData;
struct RTypedData;
struct RFloat;
struct RIO;
struct RFile;
@@ -58,6 +59,7 @@ namespace rubinius {
RArray* rarray;
RString* rstring;
RData* rdata;
RTypedData* rtypeddata;
RFloat* rfloat;
RIO* rio;
RFile* rfile;
@@ -191,6 +193,7 @@ namespace rubinius {
}

RData* as_rdata(NativeMethodEnvironment* env);
RTypedData* as_rtypeddata(NativeMethodEnvironment* env);
RArray* as_rarray(NativeMethodEnvironment* env);
RString* as_rstring(NativeMethodEnvironment* env, int cache_level);
RFloat* as_rfloat(NativeMethodEnvironment* env);
15 changes: 13 additions & 2 deletions vm/capi/hash.cpp
Original file line number Diff line number Diff line change
@@ -43,11 +43,16 @@ extern "C" {
}

VALUE rb_hash_lookup(VALUE self, VALUE key) {
VALUE entry = capi_fast_call(self, rb_intern("find_item"), 1, key);
return rb_hash_lookup2(self, key, Qnil);
}

VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def) {
VALUE entry = capi_fast_call(hash, rb_intern("find_item"), 1, key);

if(entry != Qnil) {
return capi_fast_call(entry, rb_intern("value"), 0);
} else {
return Qnil;
return def;
}
}

@@ -83,4 +88,10 @@ extern "C" {
}
}
}

VALUE rb_hash_set_ifnone(VALUE hash, VALUE def) {
capi_fast_call(hash, rb_intern("default="), 1, def);

return hash;
}
}
4 changes: 4 additions & 0 deletions vm/capi/symbol.cpp
Original file line number Diff line number Diff line change
@@ -40,4 +40,8 @@ extern "C" {
Object* p = reinterpret_cast<Symbol*>(sym)->is_cvar_p(env->state());
return CBOOL(p) ? Qtrue : Qfalse;
}

VALUE rb_sym2str(VALUE sym) {
return rb_id2str(SYM2ID(sym));
}
}
217 changes: 205 additions & 12 deletions vm/include/capi/ruby.h
Original file line number Diff line number Diff line change
@@ -89,7 +89,101 @@
# endif
#endif

#define LONG_LONG long long
#if SIZEOF_LONG_LONG > 0
# define LONG_LONG long long
#endif

#if SIZEOF_LONG == SIZEOF_VOIDP
# define SIGNED_VALUE long
# define SIZEOF_VALUE SIZEOF_LONG
# define PRI_VALUE_PREFIX "l"
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
# define SIGNED_VALUE LONG_LONG
# define LONG_LONG_VALUE 1
# define SIZEOF_VALUE SIZEOF_LONG_LONG
# define PRI_VALUE_PREFIX "ll"
#else
# error ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
#endif

#ifndef PRI_INT_PREFIX
#define PRI_INT_PREFIX ""
#endif
#ifndef PRI_LONG_PREFIX
#define PRI_LONG_PREFIX "l"
#endif

#if SIZEOF_LONG == 8
#define PRI_64_PREFIX PRI_LONG_PREFIX
#elif SIZEOF_LONG_LONG == 8
#define PRI_64_PREFIX PRI_LL_PREFIX
#endif

#define RUBY_PRI_VALUE_MARK "\v"
#if defined PRIdPTR && !defined PRI_VALUE_PREFIX
#define PRIdVALUE PRIdPTR
#define PRIoVALUE PRIoPTR
#define PRIuVALUE PRIuPTR
#define PRIxVALUE PRIxPTR
#define PRIXVALUE PRIXPTR
#define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK
#else
#define PRIdVALUE PRI_VALUE_PREFIX"d"
#define PRIoVALUE PRI_VALUE_PREFIX"o"
#define PRIuVALUE PRI_VALUE_PREFIX"u"
#define PRIxVALUE PRI_VALUE_PREFIX"x"
#define PRIXVALUE PRI_VALUE_PREFIX"X"
#define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK
#endif
#ifndef PRI_VALUE_PREFIX
# define PRI_VALUE_PREFIX ""
#endif

#ifndef PRI_TIMET_PREFIX
# if SIZEOF_TIME_T == SIZEOF_INT
# define PRI_TIMET_PREFIX
# elif SIZEOF_TIME_T == SIZEOF_LONG
# define PRI_TIMET_PREFIX "l"
# elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
# define PRI_TIMET_PREFIX PRI_LL_PREFIX
# endif
#endif

#if defined PRI_PTRDIFF_PREFIX
#elif SIZEOF_PTRDIFF_T == SIZEOF_INT
# define PRI_PTRDIFF_PREFIX ""
#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
# define PRI_PTRDIFF_PREFIX "l"
#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX
#endif
#define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d"
#define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i"
#define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o"
#define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u"
#define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x"
#define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X"

#if defined PRI_SIZE_PREFIX
#elif SIZEOF_SIZE_T == SIZEOF_INT
# define PRI_SIZE_PREFIX ""
#elif SIZEOF_SIZE_T == SIZEOF_LONG
# define PRI_SIZE_PREFIX "l"
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
# define PRI_SIZE_PREFIX PRI_LL_PREFIX
#endif
#define PRIdSIZE PRI_SIZE_PREFIX"d"
#define PRIiSIZE PRI_SIZE_PREFIX"i"
#define PRIoSIZE PRI_SIZE_PREFIX"o"
#define PRIuSIZE PRI_SIZE_PREFIX"u"
#define PRIxSIZE PRI_SIZE_PREFIX"x"
#define PRIXSIZE PRI_SIZE_PREFIX"X"

#ifdef __GNUC__
#define RB_UNUSED_VAR(x) x __attribute__ ((unused))
#else
#define RB_UNUSED_VAR(x) x
#endif

#ifndef RUBY_EXTERN
#define RUBY_EXTERN extern
@@ -219,6 +313,9 @@ struct RString {
#define RSTRING(str) capi_rstring_struct(str, RSTRING_CACHE_UNSAFE)
#endif

#define RSTRING_GETMEM(rb_str, c_str, c_str_len) \
((c_str) = RSTRING_PTR(rb_str), (c_str_len) = RSTRING_LEN(rb_str))

struct RArray {
ssize_t len;
struct {
@@ -238,6 +335,7 @@ struct RData {
};

#define RDATA(d) capi_rdata_struct(d)
#define RTYPEDDATA(d) capi_rtypeddata_struct(d)

struct RFloat {
double value;
@@ -250,6 +348,8 @@ struct RFloat {
#define RHASH(obj) ({ C_API_RHASH_is_not_supported_in_Rubinius })
#define RHASH_TBL(obj) ({ C_API_RHASH_TBL_is_not_supported_in_Rubinius })

#define RHASH_SET_IFNONE(hash, def) rb_hash_set_ifnone(hash, def)

typedef struct rb_io_t {
VALUE handle;
int fd;
@@ -381,9 +481,19 @@ struct RFile {
/** Reallocate memory allocated with ALLOC or ALLOC_N. */
#define REALLOC_N(ptr, type, n) (ptr)=(type*)realloc(ptr, sizeof(type) * (n));

#define ZALLOC_N(type,n) ((type*)xcalloc((n),sizeof(type)))
#define ZALLOC(type) (ZALLOC_N(type,1))

#define ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n))
#define ALLOCV_N(type, v, n) ((type*)ALLOCV((v), sizeof(type)*(n)))
#define ALLOCV_END(v) rb_free_tmp_buffer(&(v))

/** Interrupt checking (no-op). */
#define CHECK_INTS /* No-op */

#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \
VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg

/** Rubinius doesn't need gc guards */
#define RB_GC_GUARD /* No-op */

@@ -482,6 +592,7 @@ VALUE rb_uint2big(unsigned long number);

/** The length of string str. */
#define RSTRING_LEN(str) rb_str_len(str)
#define RSTRING_LENINT(str) rb_str_len(str)

/** The pointer to the string str's data. */
#ifdef RUBY_READONLY_STRING
@@ -513,11 +624,15 @@ VALUE rb_uint2big(unsigned long number);

#define Check_SafeStr(x)

#define FilePathValue(v) rb_file_path_value(&(v))

/** Retrieve the ID given a Symbol handle. */
#define SYM2ID(sym) (sym)

/** Return an integer type id for the object. @see rb_type() */
#define TYPE(handle) rb_type(handle)
#define rb_type_p(obj, type) (rb_type(obj) == (type))
#define RB_TYPE_P(obj, type) rb_type_p(obj, type)

/** Alias to rb_type. This is not exactly the same as in MRI, but it makes sure
+ * that it won't segfault if you give BUILTIN_TYPE an immediate such as a Fixnum
@@ -592,6 +707,7 @@ VALUE rb_uint2big(unsigned long number);

struct RArray* capi_rarray_struct(VALUE array);
struct RData* capi_rdata_struct(VALUE data);
struct RTypedData* capi_rtypeddata_struct(VALUE data);
struct RString* capi_rstring_struct(VALUE string, int cache_level);
struct RFloat* capi_rfloat_struct(VALUE data);
struct RIO* capi_rio_struct(VALUE handle);
@@ -625,19 +741,78 @@ VALUE rb_uint2big(unsigned long number);
VALUE rb_equal(VALUE a, VALUE b);
VALUE rb_class_inherited_p(VALUE mod, VALUE arg);

#define Data_Make_Struct(klass, type, mark, free, sval) (\
sval = ALLOC(type), \
memset(sval, 0, sizeof(type)), \
Data_Wrap_Struct(klass, mark, free, sval)\
)
typedef struct rb_data_type_struct rb_data_type_t;

struct rb_data_type_struct {
const char *wrap_struct_name;
struct {
void (*dmark)(void*);
void (*dfree)(void*);
size_t (*dsize)(const void *);
void *reserved[2]; /* For future extension.
This array *must* be filled with ZERO. */
} function;
const rb_data_type_t *parent;
void *data; /* This area can be used for any purpose
by a programmer who define the type. */
VALUE flags; /* FL_WB_PROTECTED */
};

#define HAVE_TYPE_RB_DATA_TYPE_T 1
#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
#define HAVE_RB_DATA_TYPE_T_PARENT 1

struct RTypedData {
const rb_data_type_t *type;
VALUE typed_flag; /* 1 or not */
void *data;
};

#define Data_Wrap_Struct(klass, mark, free, sval) \
rb_data_object_alloc(klass, (void*)sval, (RUBY_DATA_FUNC)mark, \
(RUBY_DATA_FUNC)free)
#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1)
#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type)
#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)

VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *);
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *);
void *rb_check_typeddata(VALUE, const rb_data_type_t *);

#define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t))
#define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1)
#define RUBY_NEVER_FREE ((RUBY_DATA_FUNC)0)
#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE

/* bits for rb_data_type_struct::flags */
#define RUBY_TYPED_FREE_IMMEDIATELY 0xcafebeef
#define RUBY_TYPED_WB_PROTECTED 0xbeefcafe

#define Data_Wrap_Struct(klass,mark,free,sval)\
rb_data_object_alloc((klass),(sval),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free))

#define Data_Make_Struct(klass,type,mark,free,sval) (\
(sval) = ALLOC(type),\
memset((sval), 0, sizeof(type)),\
Data_Wrap_Struct((klass),(mark),(free),(sval))\
)

#define TypedData_Wrap_Struct(klass,data_type,sval)\
rb_data_typed_object_alloc((klass),(sval),(data_type))

#define TypedData_Make_Struct(klass, type, data_type, sval) (\
(sval) = ALLOC(type),\
memset((sval), 0, sizeof(type)),\
TypedData_Wrap_Struct((klass),(data_type),(sval))\
)

#define Data_Get_Struct(obj,type,sval) do {\
Check_Type((obj), T_DATA); \
(sval) = (type*)DATA_PTR(obj);\
} while (0)

#define Data_Get_Struct(obj,type,sval) do {\
Check_Type(obj, T_DATA); \
sval = (type*)DATA_PTR(obj);\
#define TypedData_Get_Struct(obj,type,data_type,sval) do {\
(sval) = (type*)rb_check_typeddata((obj), (data_type)); \
} while (0)

/** Return Qtrue if obj is an immediate, Qfalse or Qnil. */
@@ -859,6 +1034,7 @@ VALUE rb_uint2big(unsigned long number);

/** Returns String representation of the class' name. */
VALUE rb_class_name(VALUE klass);
#define rb_class_path(k) rb_class_name(k)

/** Calls the class method 'inherited' on super passing the class.
* If super is NULL, calls Object.inherited. */
@@ -874,6 +1050,9 @@ VALUE rb_uint2big(unsigned long number);
/** Returns the Class object this object is an instance of. */
VALUE rb_class_of(VALUE object);

/** Returns the superclass of a class. */
VALUE rb_class_superclass(VALUE klass);

/** Returns the first superclass of an object that isn't a singleton or
* intermediate.
*/
@@ -1061,6 +1240,9 @@ VALUE rb_uint2big(unsigned long number);

VALUE rb_vsprintf(const char *format, va_list varargs);

/** Returns a duplicate file discriptor with close-on-exec flag set. */
int rb_cloexec_dup(int fd);

/** Returns a File opened with the specified mode. */
VALUE rb_file_open(const char* name, const char* mode);

@@ -1115,6 +1297,8 @@ VALUE rb_uint2big(unsigned long number);
/** Return the value associated with the key, excluding default values. */
VALUE rb_hash_lookup(VALUE self, VALUE key);

VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def);

/** Set the value associated with the key. */
VALUE rb_hash_aset(VALUE self, VALUE key, VALUE value);

@@ -1136,6 +1320,8 @@ VALUE rb_uint2big(unsigned long number);
int (*func)(ANYARGS),
VALUE farg);

VALUE rb_hash_set_ifnone(VALUE hash, VALUE def);

void rb_eof_error();

VALUE rb_io_addstr(VALUE, VALUE);
@@ -1233,6 +1419,8 @@ VALUE rb_uint2big(unsigned long number);
ID rb_intern(const char* string);
ID rb_intern2(const char* string, long len);

VALUE rb_sym2str(VALUE sym);

/** Coerce x and y and perform 'x func y' */
VALUE rb_num_coerce_bin(VALUE x, VALUE y, ID func);

@@ -1572,6 +1760,9 @@ VALUE rb_uint2big(unsigned long number);
* to check that length is greater than 0 properly */
VALUE rb_str_new(const char* string, long length);

/** Create a String from a C string. Alias of rb_str_new2. */
VALUE rb_str_new_cstr(const char* string);

/** Create a String from a C string. */
VALUE rb_str_new2(const char* string);

@@ -1760,6 +1951,8 @@ VALUE rb_uint2big(unsigned long number);

NORETURN(void rb_notimplement());

NORETURN(VALUE rb_f_notimplement(int argc, VALUE *argv, VALUE obj));

/** Raises an ArgumentError exception. */
NORETURN(void rb_invalid_str(const char *str, const char *type));

0 comments on commit 203f021

Please sign in to comment.