diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | configure.in | 32 | ||||
-rw-r--r-- | defines.h | 4 | ||||
-rw-r--r-- | eval.c | 157 | ||||
-rw-r--r-- | ext/extmk.rb | 11 |
5 files changed, 128 insertions, 82 deletions
@@ -1,3 +1,9 @@ +Mon Feb 19 18:27:42 2007 Akinori MUSHA <knu@iDaemons.org> + + * configure.in, defines.h, eval.c (rb_feature_p, rb_provided, + load_wait, search_required, rb_require_safe), ext/extmk.rb: Fix + a bug where a statically linked extension cannot be autoloaded. + Thu Feb 15 20:31:07 2007 Akinori MUSHA <knu@iDaemons.org> * lib/uri/ftp.rb: Revert the previous change pending discussion. diff --git a/configure.in b/configure.in index 4c59fa488e..77437d6ffa 100644 --- a/configure.in +++ b/configure.in @@ -1144,30 +1144,24 @@ if test "$dln_a_out_works" = yes; then STATIC=-Bstatic fi DLEXT=so - AC_DEFINE(DLEXT, ".so") CCDLFLAGS= else case "$target_os" in - hpux*) DLEXT=sl - AC_DEFINE(DLEXT, ".sl");; - nextstep*) DLEXT=bundle - AC_DEFINE(DLEXT, ".bundle");; - openstep*) DLEXT=bundle - AC_DEFINE(DLEXT, ".bundle");; - rhapsody*) DLEXT=bundle - AC_DEFINE(DLEXT, ".bundle");; - darwin*) DLEXT=bundle - AC_DEFINE(DLEXT, ".bundle");; - os2-emx*) DLEXT=dll - AC_DEFINE(DLEXT, ".dll");; - cygwin*|mingw*) DLEXT=so - AC_DEFINE(DLEXT, ".so") - DLEXT2=dll - AC_DEFINE(DLEXT2, ".dll");; - *) DLEXT=so - AC_DEFINE(DLEXT, ".so");; + hpux*) DLEXT=sl;; + nextstep*|openstep*|rhapsody*|darwin*) + DLEXT=bundle;; + os2-emx*) DLEXT=dll;; + cygwin*|mingw*) + DLEXT=so DLEXT2=dll;; + *) DLEXT=so;; esac fi +len=2 # .rb +n=`expr "$DLEXT" : '.*'`; test "$n" -gt "$len" && len=$n +n=`expr "$DLEXT2" : '.*'`; test "$n" -gt "$len" && len=$n +AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`) +test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT") +test ".$DLEXT2" = "." || AC_DEFINE_UNQUOTED(DLEXT2, ".$DLEXT2") AC_SUBST(STRIP)dnl if test "$with_dln_a_out" = yes; then @@ -248,6 +248,10 @@ void rb_ia64_flushrs(void); #define ENV_IGNORECASE #endif +#ifndef DLEXT_MAXLEN +#define DLEXT_MAXLEN 4 +#endif + #ifndef RUBY_PLATFORM #define RUBY_PLATFORM "unknown-unknown" #endif @@ -6928,13 +6928,22 @@ static st_table *loading_tbl; #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0) #endif -static char * + +static const char *const loadable_ext[] = { + ".rb", DLEXT, +#ifdef DLEXT2 + DLEXT2, +#endif + 0 +}; + +static int rb_feature_p(feature, ext, rb) const char *feature, *ext; int rb; { VALUE v; - char *f, *e; + const char *f, *e; long i, len, elen; if (ext) { @@ -6945,50 +6954,59 @@ rb_feature_p(feature, ext, rb) len = strlen(feature); elen = 0; } - for (i = 0; i < RARRAY(rb_features)->len; ++i) { - v = RARRAY(rb_features)->ptr[i]; + for (i = 0; i < RARRAY_LEN(rb_features); ++i) { + v = RARRAY_PTR(rb_features)[i]; f = StringValuePtr(v); - if (strncmp(f, feature, len) != 0) continue; + if (RSTRING_LEN(v) < len || strncmp(f, feature, len) != 0) + continue; if (!*(e = f + len)) { if (ext) continue; - return e; + return 'u'; } if (*e != '.') continue; if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) { - return e; + return 's'; } if ((rb || !ext) && (strcmp(e, ".rb") == 0)) { - return e; + return 'r'; + } + } + if (loading_tbl) { + if (st_lookup(loading_tbl, (st_data_t)feature, 0)) { + if (ext) return 'u'; + return strcmp(ext, ".rb") ? 's' : 'r'; + } + else { + char *buf; + + if (ext) return 0; + buf = ALLOCA_N(char, len + DLEXT_MAXLEN + 1); + strcpy(buf, feature); + for (i = 0; (e = loadable_ext[i]) != 0; i++) { + strncpy(buf + len, e, DLEXT_MAXLEN + 1); + if (st_lookup(loading_tbl, (st_data_t)buf, 0)) { + return i ? 's' : 'r'; + } + } } } return 0; } -static const char *const loadable_ext[] = { - ".rb", DLEXT, -#ifdef DLEXT2 - DLEXT2, -#endif - 0 -}; +static int search_required(VALUE, VALUE *, VALUE *); int rb_provided(feature) const char *feature; { - int i; - char *buf; + VALUE fname, path; if (rb_feature_p(feature, 0, Qfalse)) return Qtrue; - if (!loading_tbl) return Qfalse; - if (st_lookup(loading_tbl, (st_data_t)feature, 0)) return Qtrue; - buf = ALLOCA_N(char, strlen(feature)+8); - strcpy(buf, feature); - for (i=0; ; i++) { - if (!loadable_ext[i]) break; - strcpy(buf+strlen(feature), loadable_ext[i]); - if (st_lookup(loading_tbl, (st_data_t)buf, 0)) return Qtrue; + if (search_required(rb_str_new2(feature), &fname, &path) != 0) { + feature = RSTRING_PTR(fname); + if (rb_feature_p(feature, strrchr(feature, '.'), Qfalse)) + return Qtrue; } return Qfalse; } @@ -7007,19 +7025,41 @@ rb_provide(feature) rb_provide_feature(rb_str_new2(feature)); } -static int -load_wait(ftptr) - char *ftptr; +static char * +load_lock(ftptr) + const char *ftptr; { st_data_t th; - if (!loading_tbl) return Qfalse; - if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return Qfalse; + if (!loading_tbl || + !st_lookup(loading_tbl, (st_data_t)ftptr, &th)) + { + /* loading ruby library should be serialized. */ + if (!loading_tbl) { + loading_tbl = st_init_strtable(); + } + /* partial state */ + ftptr = ruby_strdup(ftptr); + st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); + return (char *)ftptr; + } do { - if ((rb_thread_t)th == curr_thread) return Qtrue; + if ((rb_thread_t)th == curr_thread) return 0; CHECK_INTS; } while (st_lookup(loading_tbl, (st_data_t)ftptr, &th)); - return Qtrue; + return 0; +} + +static void +load_unlock(const char *ftptr) +{ + if (ftptr) { + st_data_t key = (st_data_t)ftptr; + + if (st_delete(loading_tbl, &key, 0)) { + free((char *)key); + } + } } /* @@ -7061,16 +7101,16 @@ search_required(fname, featurep, path) *featurep = fname; *path = 0; - ext = strrchr(ftptr = RSTRING(fname)->ptr, '.'); + ext = strrchr(ftptr = RSTRING_PTR(fname), '.'); if (ext && !strchr(ext, '/')) { if (strcmp(".rb", ext) == 0) { if (rb_feature_p(ftptr, ext, Qtrue)) return 'r'; - if (*path = rb_find_file(fname)) return 'r'; + if ((*path = rb_find_file(fname)) != 0) return 'r'; return 0; } else if (IS_SOEXT(ext)) { if (rb_feature_p(ftptr, ext, Qfalse)) return 's'; - tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); + tmp = rb_str_new(RSTRING_PTR(fname), ext-RSTRING_PTR(fname)); *featurep = tmp; #ifdef DLEXT2 OBJ_FREEZE(tmp); @@ -7089,20 +7129,18 @@ search_required(fname, featurep, path) } else if (IS_DLEXT(ext)) { if (rb_feature_p(ftptr, ext, Qfalse)) return 's'; - if (*path = rb_find_file(fname)) return 's'; + if ((*path = rb_find_file(fname)) != 0) return 's'; } } tmp = fname; - switch (type = rb_find_file_ext(&tmp, loadable_ext)) { + type = rb_find_file_ext(&tmp, loadable_ext); + *featurep = tmp; + switch (type) { case 0: - if ((ext = rb_feature_p(ftptr, 0, Qfalse))) { - type = strcmp(".rb", ext); - break; - } - return 0; + ftptr = RSTRING_PTR(tmp); + return rb_feature_p(ftptr, 0, Qfalse); default: - *featurep = tmp; ext = strrchr(ftptr = RSTRING(tmp)->ptr, '.'); if (rb_feature_p(ftptr, ext, !--type)) break; *path = rb_find_file(tmp); @@ -7150,18 +7188,11 @@ rb_require_safe(fname, safe) ruby_safe_level = safe; found = search_required(fname, &feature, &path); if (found) { - if (!path || load_wait(RSTRING(feature)->ptr)) { + if (!path || !(ftptr = load_lock(RSTRING_PTR(feature)))) { result = Qfalse; } else { ruby_safe_level = 0; - /* loading ruby library should be serialized. */ - if (!loading_tbl) { - loading_tbl = st_init_strtable(); - } - /* partial state */ - ftptr = ruby_strdup(RSTRING_PTR(feature)); - st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); switch (found) { case 'r': rb_load(path, 0); @@ -7188,11 +7219,7 @@ rb_require_safe(fname, safe) ruby_frame->last_func = saved.func; SCOPE_SET(saved.vmode); ruby_safe_level = saved.safe; - if (ftptr) { - if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */ - free(ftptr); - } - } + load_unlock(ftptr); if (state) JUMP_TAG(state); if (NIL_P(result)) { load_failed(fname); @@ -7211,6 +7238,24 @@ rb_require(fname) return rb_require_safe(fn, ruby_safe_level); } +void +ruby_init_ext(name, init) + const char *name; + void (*init) _((void)); +{ + ruby_current_node = 0; + ruby_sourcefile = rb_source_filename(name); + ruby_sourceline = 0; + ruby_frame->last_func = 0; + ruby_frame->orig_func = 0; + SCOPE_SET(SCOPE_PUBLIC); + if (load_lock(name)) { + (*init)(); + rb_provide(name); + load_unlock(name); + } +} + static void secure_visibility(self) VALUE self; diff --git a/ext/extmk.rb b/ext/extmk.rb index ff1b184a1f..ac396a0d80 100644 --- a/ext/extmk.rb +++ b/ext/extmk.rb @@ -451,14 +451,11 @@ unless $extlist.empty? src = %{\ #include "ruby.h" -#define init(func, name) { \ - void func _((void)); \ - ruby_sourcefile = src = rb_source_filename(name); \ - func(); \ - rb_provide(src); \ -} +#define init(func, name) {void func _((void)); ruby_init_ext(name, func);} + +void ruby_init_ext _((const char *name, void (*init)(void))); -void Init_ext _((void))\n{\n char *src;#$extinit} +void Init_ext _((void))\n{\n#$extinit} } if !modified?(extinit.c, MTIMES) || IO.read(extinit.c) != src open(extinit.c, "w") {|f| f.print src} |