[ruby-talk:02623] Re: Requiring more flexible require
From:
Aleksi Niemel<aleksi.niemela@...>
Date:
2000-05-07 22:32:07 UTC
List:
ruby-talk #2623
I lost my 24h internet connection permanently, so sorry for the delay :).
In message "[ruby-talk:02604] Requiring more flexible require"
on 00/04/28, mrilu <mrilu@ale.cx> writes:
|I thought to ask and provide an opportunity for someone to give me
|a glimpse of deep reasoning behind 'require'. Why it figures out the
|name of the initialization routine from given filename and why it
|looks strictly for the library file named as the given filename?
I got three replies, but I thought to answer only once and for all.
For Fukushima Masaki:
>> Then I want to use these from Ruby so I make wrappers (with SWIG) for
>> both libraries, and make new shared libs libfoo_wrap.so and
libbar_wrap.so.
>> I really like to have them named _wrap because I have already programs
>> which are using the libxxx.so versions. And I really like to have them
>> prefixed 'lib' because on the C side the 'ld -lname' looks for
libname.so.
>> (I know I could cope with symlinks, but it feels clumsy for this one.)
>I wonder why you need to use 'ld' with Ruby extension.
>How do you use 'ld -lfoo_wrap' or 'ld -lbar_wrap'?
You're right. My mistake. I don't link against wrapped library.
Normally there's no need to access foo_wrap shared object. But now I got
another idea and the question remains, could there be a use for wrapped
libraries?
Can you imagine program barrel.c using some routines from foo_wrap.c
directly? Or how about embedded Ruby programs? Could they possess some need
to 'ld -lfoo_wrap'?
Then, Guy Decoux
m> First, let's change it to search with require 'name_of_lib' for the file
m> libname_of_lib.so too. This might break some old stuff if the
m> LD_LIBRARY_PATH is not traversed totally for foo.so before for
m> libfoo.so.
ts> It can, perhaps, exist a security problem with such scheme. I dont know.
Yes, it could be some kind of problem. I would say require has that
inherently (by not hardcoding the value) and the fact that you can say
require 'the_evil_library_name_generator'
require the_evil_library
does make me smile but with perceptive eyes. I think this feature is good
and need some care to be not misused.
And the last one for Matz:
>First of all, you have to distinguish OS's shared libraries and Ruby's
>dynamically loadable extension. They have both file extension (.so)
>and in same binary format, but similarity ends there.
Yep, maybe I didn't make it clear but I think I have the idea :). Even so, I
would rephrase that the shared libraries and Ruby's dynamically loadable
extensions are a little bit more similar to each other; they are *mainly*
used from different kind of program - the first by ordinary, general
programs and the latter by programs somehow related to Ruby framework, most
notably interpreter (the other option being Ruby embedded programs).
>You have shared library libfoo.so and libbar.so, and wrapper routines
>in foo.c and foo.bar. So why don't you choose foo.so and bar.so for
>extension name? Ruby does not use `ld' inside. You don't need to
>prefix extension names by `lib'.
I see the original idea to name extensions to name_for_extension.so. Since
they still are normal libraries (just used normally for Ruby) I think they
should be named
1) like the standard, that is libname_for_the_extension.so, or to
2) make notable difference
The first one is probably harder to tackle with, considering the wide range
of platforms. The second point might already be done. libfoo.so's wrapper is
foo.so, thus being clear. We might get some clarity by making bigger
difference like naming the foo.so to Foo.rso (denoting Ruby shared Object)
or something.
However, I still think the main point is to allow specific initialization
routine instead of naming of the lib. I wasted some of my precious free time
by creating the following patch :). Feel free to discuss about it, and I
personally don't mind it to get into development version, as it's (most
probably) not breaking any existing code.
This allows to write
require 'Foo' 'weird_initialization_function'
loading Foo.so from path and calling it's
Init_weird_initialization_function.
First, I would like to ask what is ALLOCA_N (and alloca family) and how it
differs from the other macros?
Secondly, I would like to note that this is patch for require 'lib'
'init_name' not for finding libraries with appended 'lib' as it's not yet
"accepted" feature.
Then, I see this patch incorporated few waiting-to-be-handled-bugfixes. I
skimmed through the code few hours trying to find these kind of problems
elsewhere in the code too, but with no luck. For these I'm not sure even now
if these are real problems or fixes. I present these first for easier
discussion.
--- ruby\dln.c Mon May 01 11:41:13 2000
+++ ruby.require\ruby\dln.c Mon May 01 12:47:56 2000
@@ -98,7 +99,9 @@
if (*p == '/') slash = p;
#endif
- sprintf(buf, FUNCNAME_PATTERN, slash + 1);
+ if( snprintf(buf, maxlen, FUNCNAME_PATTERN, slash + 1) == -1 ){
+ /* handle error: buffer size insufficient */
+ }
for (p = buf; *p; p++) { /* Delete suffix if it exists */
if (*p == '.') {
*p = '\0'; break;
@@ -367,6 +383,9 @@
while (read(fd, p, 1) == 1) {
if (*p == '\n' || *p == '\t' || *p == ' ') break;
p++;
+ if (p-buf >= MAXPATHLEN){
+ /* some clever buffer overflow error handling */
+ }
}
*p = '\0';
And now the real patch for require.
Are you sure you want these in diff -u format?
--- ruby\dln.c Mon May 01 11:41:13 2000
+++ ruby.require\ruby\dln.c Mon May 01 12:47:56 2000
@@ -1,14 +1,14 @@
-/**********************************************************************
+/************************************************
dln.c -
$Author: matz $
- $Date: 2000/05/01 09:41:13 $
+ $Date: 2000/03/07 08:37:27 $
created at: Tue Jan 18 17:05:06 JST 1994
Copyright (C) 1993-2000 Yukihiro Matsumoto
-**********************************************************************/
+************************************************/
#include "config.h"
#include "defines.h"
@@ -84,8 +84,9 @@
#endif
static void
-init_funcname(buf, file)
+init_funcname(buf, maxlen, file)
char *buf;
+ int maxlen;
char *file;
{
char *p, *slash;
@@ -98,7 +99,9 @@
if (*p == '/') slash = p;
#endif
- sprintf(buf, FUNCNAME_PATTERN, slash + 1);
+ if( snprintf(buf, maxlen, FUNCNAME_PATTERN, slash + 1) == -1 ){
+ /* handle error: buffer size insufficient */
+ }
for (p = buf; *p; p++) { /* Delete suffix if it exists */
if (*p == '.') {
*p = '\0'; break;
@@ -106,6 +109,19 @@
}
}
+static void
+init_funcname2(buf, maxlen, file, initfunc)
+ char *buf;
+ int maxlen;
+ char *file;
+ char *initfunc;
+{
+ if(strcmp(initfunc, "") == 0)
+ init_funcname(buf, maxlen, file);
+ else
+ init_funcname(buf, maxlen, initfunc);
+}
+
#ifdef USE_DLN_A_OUT
#ifndef LIBC_NAME
@@ -367,6 +383,9 @@
while (read(fd, p, 1) == 1) {
if (*p == '\n' || *p == '\t' || *p == ' ') break;
p++;
+ if (p-buf >= MAXPATHLEN){
+ /* some clever buffer overflow error handling */
+ }
}
*p = '\0';
@@ -591,10 +610,11 @@
#endif
static int
-load_1(fd, disp, need_init)
+load_1(fd, disp, fname, init_func)
int fd;
long disp;
- const char *need_init;
+ const char *fname;
+ const char *init_func;
{
static char *libc = LIBC_NAME;
struct exec hdr;
@@ -605,7 +625,6 @@
struct nlist *sym;
struct nlist *end;
int init_p = 0;
- char buf[256];
if (load_header(fd, &hdr, disp) == -1) return -1;
if (INVALID_OBJECT(hdr)) {
@@ -815,16 +834,19 @@
}
}
+ need_init = fname;
if (need_init) {
int len;
char **libs_to_be_linked = 0;
+ char* initfuncname = NULL;
if (undef_tbl->num_entries > 0) {
if (load_lib(libc) == -1) goto err_exit;
}
- init_funcname(buf, need_init);
- len = strlen(buf);
+ initfuncname = ALLOCA_N(char, MAXPATHLEN);
+ init_funcname(initfuncname, MAXPATHLEN, fname, init_func);
+ len = strlen(initfuncname);
for (sym = syms; sym<end; sym++) {
char *name = sym->n_un.n_name;
@@ -832,7 +854,7 @@
if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
libs_to_be_linked = (char**)sym->n_value;
}
- else if (strcmp(name+1, buf) == 0) {
+ else if (strcmp(name+1, initfuncname) == 0) {
init_p = 1;
((int (*)())sym->n_value)();
}
@@ -844,6 +866,7 @@
libs_to_be_linked++;
}
}
+ free(initfuncname);
}
free(reloc);
free(syms);
@@ -961,7 +984,7 @@
target_offset = -1;
st_foreach(undef_tbl, search_undef, lib_tbl);
if (target_offset == -1) break;
- if (load_1(fd, target_offset, 0) == -1) {
+ if (load_1(fd, target_offset, 0, 0) == -1) {
st_free_table(lib_tbl);
free(data);
goto badlib;
@@ -1007,7 +1030,7 @@
if (sym < end) {
found++;
free(syms);
- if (load_1(fd, offset, 0) == -1) {
+ if (load_1(fd, offset, 0, 0) == -1) {
goto badlib;
}
}
@@ -1028,11 +1051,13 @@
}
static int
-load(file)
+load(file, initfunc)
const char *file;
+ const char *initfunc;
{
int fd;
int result;
+ char *initfunc = ALLOC_N(char, MAXPATHLEN);
if (dln_init_p == 0) {
if (dln_init(dln_argv0) == -1) return -1;
@@ -1047,7 +1072,8 @@
dln_errno = errno;
return -1;
}
- result = load_1(fd, 0, file);
+
+ result = load_1(fd, 0, file, initfunc);
close(fd);
return result;
@@ -1202,17 +1228,18 @@
#endif
void
-dln_load(file)
+dln_load(file, initname)
const char *file;
+ const char *initname;
{
#ifdef _WIN32
HINSTANCE handle;
char winfile[255];
void (*init_fct)();
- char buf[MAXPATHLEN];
+ char initfuncname[MAXPATHLEN];
/* Load the file as an object one */
- init_funcname(buf, file);
+ init_funcname2(initfuncname, MAXPATHLEN, file, initname);
#ifdef __CYGWIN32__
cygwin32_conv_to_win32_path(file, winfile);
@@ -1234,8 +1261,8 @@
init_fct(_impure_ptr);
#endif
- if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
- printf("GetProcAddress %s\n", buf);
+ if ((init_fct = (void(*)())GetProcAddress(handle, initfuncname)) ==
NULL) {
+ printf("GetProcAddress %s\n", initfuncname);
goto failed;
}
/* Call the init code */
@@ -1243,15 +1270,15 @@
return;
#else
#ifdef USE_DLN_A_OUT
- if (load(file) == -1) {
+ if (load(file, initfuncname) == -1) {
goto failed;
}
return;
#else
- char buf[MAXPATHLEN];
+ char initfuncname[MAXPATHLEN];
/* Load the file as an object one */
- init_funcname(buf, file);
+ init_funcname2(initfuncname, MAXPATHLEN, file, initname);
#ifdef USE_DLN_DLOPEN
#define DLN_DEFINED
@@ -1271,7 +1298,7 @@
goto failed;
}
- if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) {
+ if ((init_fct = (void(*)())dlsym(handle, initfuncname)) == NULL) {
goto failed;
}
/* Call the init code */
@@ -1293,9 +1320,9 @@
extern int errno;
rb_loaderror("%s - %s", strerror(errno), file);
}
- shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
+ shl_findsym(&lib, initfuncname, TYPE_PROCEDURE, (void*)&init_fct);
if (init_fct == NULL) {
- shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
+ shl_findsym(&lib, initfuncname, TYPE_UNDEFINED,
(void*)&init_fct);
if (init_fct == NULL) {
errno = ENOSYM;
rb_loaderror("%s - %s", strerror(ENOSYM), file);
@@ -1349,7 +1376,7 @@
}
/* lookup the initial function */
- if(rld_lookup(NULL, buf, &init_address) == 0) {
+ if(rld_lookup(NULL, initfuncname, &init_address) == 0) {
rb_loaderror("Failed to lookup Init function %.200s", file);
}
@@ -1365,7 +1392,7 @@
int dyld_result;
NSObjectFileImage obj_file; /* handle, but not use it */
/* "file" is module file name .
- "buf" is initial function name with "_" . */
+ "initfuncname" is initial function name with "_" . */
void (*init_fct)();
@@ -1380,12 +1407,12 @@
/* lookup the initial function */
/*NSIsSymbolNameDefined require function name without "_" */
- if(NSIsSymbolNameDefined(buf + 1)) {
+ if(NSIsSymbolNameDefined(initfuncname + 1)) {
rb_loaderror("Failed to lookup Init function %.200s",file);
}
/* NSLookupAndBindSymbol require function name with "_" !! */
- init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
+ init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(initfuncname));
(*init_fct)();
return;
@@ -1412,12 +1439,12 @@
B_SYMBOL_TYPE_CODE. Why ? */
/* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
/* "__Fv" dont need! The Be Book Bug ? */
- err_stat = get_image_symbol(img_id, buf,
+ err_stat = get_image_symbol(img_id, initfuncname,
B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
if (err_stat != B_NO_ERROR) {
char real_name[1024];
- strcpy(real_name, buf);
+ strcpy(real_name, initfuncname);
strcat(real_name, "__Fv");
err_stat = get_image_symbol(img_id, real_name,
B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
@@ -1430,7 +1457,7 @@
else if (B_NO_ERROR != err_stat) {
char errmsg[] = "Internal of BeOS version. %.200s (symbol_name =
%s)";
unload_add_on(img_id);
- rb_loaderror(errmsg, strerror(err_stat), buf);
+ rb_loaderror(errmsg, strerror(err_stat), initfuncname);
}
/* call module initialize function. */
@@ -1454,7 +1481,7 @@
void (*init_fct)();
char fullpath[MAXPATHLEN];
- strcpy(fullpath, file);
+ strncpy(fullpath, MAXPATHLEN, file); /* handle error: needed? */
/* resolve any aliases to find the real file */
c2pstr(fullpath);
@@ -1475,8 +1502,8 @@
}
/* Locate the address of the correct init function */
- c2pstr(buf);
- err = FindSymbol(connID, buf, &symAddr, &class);
+ c2pstr(initfuncname);
+ err = FindSymbol(connID, initfuncname, &symAddr, &class);
if (err) {
rb_loaderror("Unresolved symbols - %s" , file);
}
--- ruby\dln.h Mon May 01 11:41:13 2000
+++ ruby.require\ruby\dln.h Sun Apr 30 23:43:10 2000
@@ -1,15 +1,12 @@
-/**********************************************************************
+/************************************************
dln.h -
$Author: matz $
- $Date: 2000/05/01 09:41:13 $
+ $Date: 1999/08/13 05:45:03 $
created at: Wed Jan 19 16:53:09 JST 1994
- Copyright (C) 1993-2000 Yukihiro Matsumoto
-
-**********************************************************************/
-
+************************************************/
#ifndef DLN_H
#define DLN_H
@@ -29,5 +26,5 @@
extern char *dln_argv0;
#endif
-void dln_load _((const char*));
+void dln_load _((const char*,const char*));
#endif
--- ruby\eval.c Mon May 01 11:41:14 2000
+++ ruby.require\ruby\eval.c Mon May 01 11:06:10 2000
@@ -1,16 +1,14 @@
-/**********************************************************************
+/************************************************
eval.c -
$Author: matz $
- $Date: 2000/05/01 09:41:14 $
+ $Date: 2000/04/17 15:39:37 $
created at: Thu Jun 10 14:22:17 JST 1993
Copyright (C) 1993-2000 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agancy, Japan
-**********************************************************************/
+************************************************/
#include "ruby.h"
#include "node.h"
@@ -1839,11 +1837,10 @@
#define return_value(v) prot_tag->retval = (v)
static VALUE
-rb_eval(self, n)
+rb_eval(self, node)
VALUE self;
- NODE *n;
+ NODE * volatile node;
{
- NODE * volatile node = n;
int state;
volatile VALUE result = Qnil;
@@ -2748,10 +2745,6 @@
rb_warning("discarding old %s",
rb_id2name(node->nd_mid));
}
rb_clear_cache_by_id(node->nd_mid);
- if (node->nd_noex) { /* toplevel */
- rb_warning("overriding global function `%s'",
- rb_id2name(node->nd_mid));
- }
}
if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
@@ -2761,7 +2754,7 @@
noex = NOEX_PROTECTED;
}
else {
- noex = node->nd_noex;
+ noex = NOEX_PUBLIC;
}
if (body && origin == ruby_class && body->nd_noex & NOEX_UNDEF)
{
noex |= NOEX_UNDEF;
@@ -2789,16 +2782,16 @@
VALUE klass;
NODE *body = 0;
- if (rb_safe_level() >= 4 && !OBJ_TAINTED(recv)) {
- rb_raise(rb_eSecurityError, "Insecure; can't define
singleton method");
- }
- if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
+ if (rb_special_const_p(recv)) {
rb_raise(rb_eTypeError,
- "can't define singleton method \"%s\" for %s",
+ "can't define method \"%s\" for %s",
rb_id2name(node->nd_mid),
rb_class2name(CLASS_OF(recv)));
}
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(recv)) {
+ rb_raise(rb_eSecurityError, "can't define singleton
method");
+ }
if (OBJ_FROZEN(recv)) rb_error_frozen("object");
klass = rb_singleton_class(recv);
if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) {
@@ -3002,11 +2995,10 @@
}
static VALUE
-module_setup(module, n)
+module_setup(module, node)
VALUE module;
- NODE *n;
+ NODE * volatile node;
{
- NODE * volatile node = n;
int state;
struct FRAME frame;
VALUE result; /* OK */
@@ -3436,30 +3428,37 @@
list = node->nd_head;
- if (TYPE(val) != T_ARRAY) {
- if (NIL_P(val))
- val = rb_ary_new2(0);
- else
- val = rb_ary_new3(1, val);
- }
- len = RARRAY(val)->len;
- for (i=0; list && i<len; i++) {
- assign(self, list->nd_head, RARRAY(val)->ptr[i], check);
- list = list->nd_next;
- }
- if (check && list) goto arg_error;
- if (node->nd_args) {
- if (node->nd_args == (NODE*)-1) {
- /* ignore rest args */
+ if (val) {
+ if (TYPE(val) != T_ARRAY) {
+ if (NIL_P(val))
+ val = rb_ary_new2(0);
+ else
+ val = rb_ary_new3(1, val);
}
- else if (!list && i<len) {
- assign(self, node->nd_args, rb_ary_new4(len-i,
RARRAY(val)->ptr+i), check);
+ len = RARRAY(val)->len;
+ for (i=0; list && i<len; i++) {
+ assign(self, list->nd_head, RARRAY(val)->ptr[i], check);
+ list = list->nd_next;
}
- else {
- assign(self, node->nd_args, rb_ary_new2(0), check);
+ if (check && list) goto arg_error;
+ if (node->nd_args) {
+ if (node->nd_args == (NODE*)-1) {
+ /* ignore rest args */
+ }
+ else if (!list && i<len) {
+ assign(self, node->nd_args, rb_ary_new4(len-i,
RARRAY(val)->ptr+i), check);
+ }
+ else {
+ assign(self, node->nd_args, rb_ary_new2(0), check);
+ }
}
+ else if (check && i<len) goto arg_error;
+ }
+ else if (node->nd_args && node->nd_args != (NODE*)-1) {
+ assign(self, node->nd_args, Qnil, check);
}
+ if (check && list) goto arg_error;
while (list) {
i++;
assign(self, list->nd_head, Qnil, check);
@@ -4915,13 +4914,24 @@
}
VALUE
-rb_f_require(obj, fname)
- VALUE obj, fname;
+rb_f_require(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
{
- char *ext, *file, *feature, *buf; /* OK */
+ VALUE fname, initname;
+ char *ext, *file, *feature, *buf, *initfunc; /* OK */
volatile VALUE load;
int state;
volatile int safe = ruby_safe_level;
+ FILE *fp = NULL;
+
+ rb_scan_args(argc, argv, "11", &fname, &initname);
+ if (argc < 2 ) /* defaults initname, if not called with some value */
+ initname = rb_str_new2("");
+
+ Check_Type( fname, T_STRING );
+ Check_Type( initname, T_STRING );
Check_SafeStr(fname);
if (rb_provided(RSTRING(fname)->ptr))
@@ -4980,7 +4990,8 @@
if ((state = EXEC_TAG()) == 0) {
load = rb_str_new2(file);
file = RSTRING(load)->ptr;
- dln_load(file);
+ initfunc = RSTRING(initname)->ptr;
+ dln_load(file, initfunc);
}
POP_TAG();
rb_thread_loading_done(feature);
@@ -5009,7 +5020,10 @@
rb_require(fname)
const char *fname;
{
- return rb_f_require(Qnil, rb_str_new2(fname));
+ VALUE *argv;
+ argv = ALLOCA_N(VALUE, 1);
+ argv[0] = rb_str_new2(fname);
+ return rb_f_require(1, argv, Qnil);
}
static void
@@ -5501,7 +5515,7 @@
rb_define_readonly_variable("$\"", &rb_features);
rb_define_global_function("load", rb_f_load, -1);
- rb_define_global_function("require", rb_f_require, 1);
+ rb_define_global_function("require", rb_f_require, -1);
rb_define_global_function("autoload", rb_f_autoload, 2);
rb_global_variable(&ruby_wrapper);
}
@@ -6200,7 +6214,7 @@
THREAD_RUNNABLE,
THREAD_STOPPED,
THREAD_TO_KILL,
- THREAD_KILLED
+ THREAD_KILLED,
};
#define WAIT_FD (1<<0)
@@ -6262,9 +6276,7 @@
#define THREAD_RAISED 0x200
-static thread_t main_thread;
static thread_t curr_thread = 0;
-
static int num_waiting_on_fd = 0;
static int num_waiting_on_timer = 0;
static int num_waiting_on_join = 0;
@@ -6284,6 +6296,8 @@
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
}
+static thread_t main_thread;
+
#define STACK(addr) (th->stk_pos<(VALUE*)(addr) &&
(VALUE*)(addr)<th->stk_pos+th->stk_len)
#define ADJ(addr)
(void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr
))
@@ -6359,9 +6373,11 @@
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
if (th->locals) st_free_table(th->locals);
- if (th->status != THREAD_KILLED && th->prev) {
- th->prev->next = th->next;
- th->next->prev = th->prev;
+ if (th->status != THREAD_KILLED) {
+ if (th->prev)
+ th->prev->next = th->next;
+ if (th->next)
+ th->next->prev = th->prev;
}
if (th != main_thread) free(th);
}
@@ -7989,6 +8005,7 @@
return_value(value);
rb_trap_restore_mask();
JUMP_TAG(TAG_THROW);
+ /* not reached */
}
void
Index: intern.h
===================================================================
RCS file: /home/cvs/ruby/intern.h,v
retrieving revision 1.15
diff -r1.15 intern.h
119c119
< VALUE rb_f_require _((VALUE, VALUE));
---
> VALUE rb_f_require _((int, VALUE*, VALUE));
Index: variable.c
===================================================================
RCS file: /home/cvs/ruby/variable.c,v
retrieving revision 1.13
diff -r1.13 variable.c
1036a1037
> VALUE *argv;
1042c1043,1045
< rb_f_require(Qnil, module);
---
> argv = ALLOCA_N(VALUE, 1);
> argv[0] = module;
> rb_f_require(1, argv, Qnil);