[macruby-changes] [459] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 20 23:13:14 PDT 2008
Revision: 459
http://trac.macosforge.org/projects/ruby/changeset/459
Author: lsansonetti at apple.com
Date: 2008-08-20 23:13:14 -0700 (Wed, 20 Aug 2008)
Log Message:
-----------
merging lrz_unstable branch
Modified Paths:
--------------
MacRuby/trunk/Rakefile
MacRuby/trunk/array.c
MacRuby/trunk/bignum.c
MacRuby/trunk/bs.c
MacRuby/trunk/class.c
MacRuby/trunk/compile.c
MacRuby/trunk/debug.h
MacRuby/trunk/encoding.c
MacRuby/trunk/eval.c
MacRuby/trunk/ext/extmk.rb
MacRuby/trunk/ext/syck/rubyext.c
MacRuby/trunk/gc.c
MacRuby/trunk/hash.c
MacRuby/trunk/id.c
MacRuby/trunk/id.h
MacRuby/trunk/include/ruby/defines.h
MacRuby/trunk/include/ruby/intern.h
MacRuby/trunk/include/ruby/node.h
MacRuby/trunk/include/ruby/ruby.h
MacRuby/trunk/insnhelper.h
MacRuby/trunk/insns.def
MacRuby/trunk/instruby.rb
MacRuby/trunk/io.c
MacRuby/trunk/lib/delegate.rb
MacRuby/trunk/lib/fileutils.rb
MacRuby/trunk/marshal.c
MacRuby/trunk/numeric.c
MacRuby/trunk/objc.m
MacRuby/trunk/object.c
MacRuby/trunk/parse.y
MacRuby/trunk/proc.c
MacRuby/trunk/process.c
MacRuby/trunk/re.c
MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb
MacRuby/trunk/signal.c
MacRuby/trunk/st.c
MacRuby/trunk/string.c
MacRuby/trunk/struct.c
MacRuby/trunk/thread.c
MacRuby/trunk/variable.c
MacRuby/trunk/version.c
MacRuby/trunk/version.h
MacRuby/trunk/vm.c
MacRuby/trunk/vm_core.h
MacRuby/trunk/vm_eval.c
MacRuby/trunk/vm_insnhelper.c
MacRuby/trunk/vm_method.c
Modified: MacRuby/trunk/Rakefile
===================================================================
--- MacRuby/trunk/Rakefile 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/Rakefile 2008-08-21 06:13:14 UTC (rev 459)
@@ -21,6 +21,7 @@
NO_WARN_BUILD = !do_option('allow_build_warnings', false)
BUILD_AS_EMBEDDABLE = do_option('build_as_embeddable', false)
ENABLE_STATIC_LIBRARY = do_option('enable_static_library', 'no') { 'yes' }
+ENABLE_DEBUG_LOGGING = do_option('enable_debug_logging', true)
# TODO: we should find a way to document these options in rake's --help
@@ -208,31 +209,28 @@
desc "Create config.h"
task :config_h do
config_h = 'include/ruby/config.h'
- if !File.exist?(config_h) \
- or File.mtime(config_h) < File.mtime(config_h + '.in') \
- or File.mtime(config_h) < File.mtime(__FILE__)
- new_config_h = File.read(config_h + '.in') << "\n"
- flag = ['/System/Library/Frameworks', '/Library/Frameworks'].any? do |p|
- File.exist?(File.join(p, 'BridgeSupport.framework'))
- end
- new_config_h << "#define HAVE_BRIDGESUPPORT_FRAMEWORK #{flag ? 1 : 0}\n"
- flag = File.exist?('/usr/include/auto_zone.h')
- new_config_h << "#define HAVE_AUTO_ZONE_H #{flag ? 1 : 0}\n"
- new_config_h << "#define RUBY_PLATFORM \"#{NEW_RUBY_PLATFORM}\"\n"
- new_config_h << "#define RUBY_LIB \"#{RUBY_LIB}\"\n"
- new_config_h << "#define RUBY_ARCHLIB \"#{RUBY_ARCHLIB}\"\n"
- new_config_h << "#define RUBY_SITE_LIB \"#{RUBY_SITE_LIB}\"\n"
- new_config_h << "#define RUBY_SITE_LIB2 \"#{RUBY_SITE_LIB2}\"\n"
- new_config_h << "#define RUBY_SITE_ARCHLIB \"#{RUBY_SITE_ARCHLIB}\"\n"
- new_config_h << "#define RUBY_VENDOR_LIB \"#{RUBY_VENDOR_LIB}\"\n"
- new_config_h << "#define RUBY_VENDOR_LIB2 \"#{RUBY_VENDOR_LIB2}\"\n"
- new_config_h << "#define RUBY_VENDOR_ARCHLIB \"#{RUBY_VENDOR_ARCHLIB}\"\n"
- if !File.exist?(config_h) or File.read(config_h) != new_config_h
- File.open(config_h, 'w') { |io| io.print new_config_h }
- ext_dir = ".ext/include/#{NEW_RUBY_PLATFORM}/ruby"
- mkdir_p(ext_dir)
- cp(config_h, ext_dir)
- end
+ new_config_h = File.read(config_h + '.in') << "\n"
+ flag = ['/System/Library/Frameworks', '/Library/Frameworks'].any? do |p|
+ File.exist?(File.join(p, 'BridgeSupport.framework'))
+ end
+ new_config_h << "#define HAVE_BRIDGESUPPORT_FRAMEWORK #{flag ? 1 : 0}\n"
+ flag = File.exist?('/usr/include/auto_zone.h')
+ new_config_h << "#define HAVE_AUTO_ZONE_H #{flag ? 1 : 0}\n"
+ new_config_h << "#define ENABLE_DEBUG_LOGGING 1\n" if ENABLE_DEBUG_LOGGING
+ new_config_h << "#define RUBY_PLATFORM \"#{NEW_RUBY_PLATFORM}\"\n"
+ new_config_h << "#define RUBY_LIB \"#{RUBY_LIB}\"\n"
+ new_config_h << "#define RUBY_ARCHLIB \"#{RUBY_ARCHLIB}\"\n"
+ new_config_h << "#define RUBY_SITE_LIB \"#{RUBY_SITE_LIB}\"\n"
+ new_config_h << "#define RUBY_SITE_LIB2 \"#{RUBY_SITE_LIB2}\"\n"
+ new_config_h << "#define RUBY_SITE_ARCHLIB \"#{RUBY_SITE_ARCHLIB}\"\n"
+ new_config_h << "#define RUBY_VENDOR_LIB \"#{RUBY_VENDOR_LIB}\"\n"
+ new_config_h << "#define RUBY_VENDOR_LIB2 \"#{RUBY_VENDOR_LIB2}\"\n"
+ new_config_h << "#define RUBY_VENDOR_ARCHLIB \"#{RUBY_VENDOR_ARCHLIB}\"\n"
+ if !File.exist?(config_h) or File.read(config_h) != new_config_h
+ File.open(config_h, 'w') { |io| io.print new_config_h }
+ ext_dir = ".ext/include/#{NEW_RUBY_PLATFORM}/ruby"
+ mkdir_p(ext_dir)
+ cp(config_h, ext_dir)
end
end
@@ -261,7 +259,7 @@
cp('lex.c.blt', 'lex.c')
end
inc_to_gen = %w{opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc vmtc.inc vm.inc}.select { |inc| !File.exist?(inc) or File.mtime("template/#{inc}.tmpl") > File.mtime(inc) }
- unless inc_to_gen.empty?
+ if !inc_to_gen.empty? or File.mtime('insns.def') > File.mtime('vm.inc')
sh("/usr/bin/ruby -Ks tool/insns2vm.rb #{inc_to_gen.join(' ')}")
end
if !File.exist?('node_name.inc') or File.mtime('include/ruby/node.h') > File.mtime('node_name.inc')
Modified: MacRuby/trunk/array.c
===================================================================
--- MacRuby/trunk/array.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/array.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,25 +1,23 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's array.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- array.c -
-
- $Author: matz $
- created at: Fri Aug 6 09:46:12 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/util.h"
#include "ruby/st.h"
+#include "id.h"
VALUE rb_cArray;
-#if WITH_OBJC
VALUE rb_cCFArray;
-VALUE rb_cArrayRuby;
-#endif
+VALUE rb_cNSArray;
+VALUE rb_cNSMutableArray;
static ID id_cmp;
@@ -33,15 +31,6 @@
}
}
-static inline void
-memfill(register VALUE *mem, register long size, register VALUE val)
-{
- while (size--) {
- *mem++ = val;
- }
-}
-
-#if WITH_OBJC
/* TODO optimize this */
struct rb_objc_ary_struct {
void *cptr;
@@ -69,24 +58,7 @@
}
return s;
}
-#else
-#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
-#define ARY_SET_LEN(ary, n) do { \
- RARRAY(ary)->len = (n);\
-} while (0)
-
-#define ARY_CAPA(ary) RARRAY(ary)->aux.capa
-#define RESIZE_CAPA(ary,capacity) do {\
- REALLOC_N(RARRAY(ary)->ptr, VALUE, (capacity));\
- RARRAY(ary)->aux.capa = (capacity);\
-} while (0)
-#endif
-
-VALUE rb_ary_frozen_p(VALUE ary);
-
-#if WITH_OBJC
-
static inline void
rb_ary_modify_check(VALUE ary)
{
@@ -104,32 +76,6 @@
}
#define rb_ary_modify rb_ary_modify_check
-#else
-
-static inline void
-rb_ary_modify_check(VALUE ary)
-{
- if (OBJ_FROZEN(ary)) rb_error_frozen("array");
- if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify array");
-}
-
-static void
-rb_ary_modify(VALUE ary)
-{
- VALUE *ptr;
-
- rb_ary_modify_check(ary);
- if (ARY_SHARED_P(ary)) {
- ptr = ALLOC_N(VALUE, RARRAY_LEN(ary));
- FL_UNSET(ary, ELTS_SHARED);
- RARRAY(ary)->aux.capa = RARRAY_LEN(ary);
- MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
- RARRAY(ary)->ptr = ptr;
- }
-}
-#endif
-
VALUE
rb_ary_freeze(VALUE ary)
{
@@ -151,62 +97,21 @@
return Qfalse;
}
-#if WITH_OBJC
-int rb_any_cmp(VALUE a, VALUE b);
+void rb_ary_insert(VALUE ary, long idx, VALUE val);
-static Boolean
-rb_cfarray_equal_cb(const void *v1, const void *v2)
-{
- return !rb_any_cmp((VALUE)v1, (VALUE)v2);
-}
-
-static const void *
-rb_cfarray_retain_cb(CFAllocatorRef allocator, const void *v)
-{
- rb_objc_retain(v);
- return v;
-}
-
-static void
-rb_cfarray_release_cb(CFAllocatorRef allocator, const void *v)
-{
- rb_objc_release(v);
-}
-
-static void
-rb_ary_insert(VALUE ary, long idx, VALUE val);
-#endif
-
static VALUE
ary_alloc(VALUE klass)
{
-#if WITH_OBJC
- VALUE ary;
- CFArrayCallBacks cb;
+ CFMutableArrayRef ary;
- memset(&cb, 0, sizeof(CFArrayCallBacks));
- cb.retain = rb_cfarray_retain_cb;
- cb.release = rb_cfarray_release_cb;
- cb.equal = rb_cfarray_equal_cb;
+ ary = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ if (klass != 0 && klass != rb_cNSArray && klass != rb_cNSMutableArray)
+ *(Class *)ary = (Class)klass;
- ary = (VALUE)CFArrayCreateMutable(NULL, 0, &cb);
- if (klass != 0 && klass != rb_cArray && klass != rb_cArrayRuby)
- *(Class *)ary = RCLASS_OCID(klass);
-
- CFMakeCollectable((CFTypeRef)ary);
+ CFMakeCollectable(ary);
rb_gc_malloc_increase(sizeof(void *));
-
- return ary;
-#else
- NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, klass, T_ARRAY);
- ary->len = 0;
- ary->ptr = 0;
- ary->aux.capa = 0;
-
return (VALUE)ary;
-#endif
}
static VALUE
@@ -221,11 +126,6 @@
rb_raise(rb_eArgError, "array size too big");
}
ary = ary_alloc(klass);
-#if !WITH_OBJC
- if (len == 0) len++;
- GC_WB(&RARRAY(ary)->ptr, ALLOC_N(VALUE, len));
- RARRAY(ary)->aux.capa = len;
-#endif
return ary;
}
@@ -233,11 +133,7 @@
VALUE
rb_ary_new2(long len)
{
-#if WITH_OBJC
return ary_new(0, len);
-#else
- return ary_new(rb_cArray, len);
-#endif
}
@@ -264,9 +160,6 @@
}
va_end(ar);
-#if !WITH_OBJC
- RARRAY(ary)->len = n;
-#endif
return ary;
}
@@ -277,51 +170,16 @@
ary = rb_ary_new2(n);
if (n > 0 && elts) {
-#if WITH_OBJC
- CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)elts, n);
-#else
- MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
- RARRAY(ary)->len = n;
-#endif
+ long i;
+ void **vals = (void **)alloca(n * sizeof(void *));
+ for (i = 0; i < n; i++)
+ vals[i] = RB2OC(elts[i]);
+ CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), (const void **)vals, n);
}
return ary;
}
-void
-rb_ary_free(VALUE ary)
-{
-#if WITH_OBJC
- rb_notimplement();
-#else
- if (!ARY_SHARED_P(ary)) {
- xfree(RARRAY(ary)->ptr);
- }
-#endif
-}
-
-#if !WITH_OBJC
-static VALUE
-ary_make_shared(VALUE ary)
-{
- if (ARY_SHARED_P(ary)) {
- return RARRAY(ary)->aux.shared;
- }
- else {
- NEWOBJ(shared, struct RArray);
- OBJSETUP(shared, 0, T_ARRAY);
-
- shared->len = RARRAY(ary)->len;
- shared->ptr = RARRAY(ary)->ptr;
- shared->aux.capa = RARRAY(ary)->aux.capa;
- RARRAY(ary)->aux.shared = (VALUE)shared;
- FL_SET(ary, ELTS_SHARED);
- OBJ_FREEZE(shared);
- return (VALUE)shared;
- }
-}
-#endif
-
VALUE
rb_assoc_new(VALUE car, VALUE cdr)
{
@@ -410,14 +268,9 @@
long len;
VALUE size, val;
- rb_ary_modify(ary);
+ ary = (VALUE)objc_msgSend((id)ary, selInit);
+
if (argc == 0) {
-#if !WITH_OBJC
- if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
- free(RARRAY(ary)->ptr);
- }
- RARRAY(ary)->len = 0;
-#endif
if (rb_block_given_p()) {
rb_warning("given block not used");
}
@@ -440,9 +293,6 @@
rb_raise(rb_eArgError, "array size too big");
}
rb_ary_modify(ary);
-#if !WITH_OBJC
- RESIZE_CAPA(ary, len);
-#endif
if (rb_block_given_p()) {
long i;
@@ -451,20 +301,17 @@
}
for (i=0; i<len; i++) {
rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
-#if !WITH_OBJC
- RARRAY(ary)->len = i + 1;
-#endif
}
}
else {
-#if WITH_OBJC
long i;
+ const void **values = alloca(sizeof(void *) * len);
+ void *ocval = RB2OC(val);
+
for (i=0; i<len; i++)
- rb_ary_insert(ary, i, val);
-#else
- memfill(RARRAY_PTR(ary), len, val);
- RARRAY(ary)->len = len;
-#endif
+ values[i] = ocval;
+
+ CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, len);
}
return ary;
}
@@ -481,26 +328,21 @@
static VALUE
rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
{
+ int i;
+
VALUE ary = ary_alloc(klass);
if (argc < 0) {
rb_raise(rb_eArgError, "negative array size");
}
-#if WITH_OBJC
- CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0),
- (const void **)argv, argc);
-#else
- RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
- RARRAY(ary)->aux.capa = argc;
- MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
- RARRAY(ary)->len = argc;
-#endif
+ for (i = 0; i < argc; i++) {
+ CFArrayAppendValue((CFMutableArrayRef)ary, RB2OC(argv[i]));
+ }
return ary;
}
-#if WITH_OBJC
-static void
+void
rb_ary_insert(VALUE ary, long idx, VALUE val)
{
if (idx < 0) {
@@ -514,9 +356,8 @@
rb_ary_modify(ary);
CFArrayInsertValueAtIndex((CFMutableArrayRef)ary, idx,
- (const void *)val);
+ (const void *)RB2OC(val));
}
-#endif
void
rb_ary_store(VALUE ary, long idx, VALUE val)
@@ -532,71 +373,22 @@
rb_ary_modify(ary);
-#if WITH_OBJC
if (idx > len) {
- const void **objs;
long i;
- if (idx > sizeof(CFIndex))
- if ((idx - len) * (long)sizeof(VALUE) <= idx - len)
+ if ((idx - len) * (long)sizeof(VALUE) <= idx - len) {
rb_raise(rb_eArgError, "index too big");
- objs = (const void **)alloca(sizeof(void *) * (idx - len));
- if (objs == NULL)
- rb_raise(rb_eArgError, "index too big");
- for (i = 0; i < (idx - len); i++)
- objs[i] = (const void *)Qnil;
- CFArrayReplaceValues((CFMutableArrayRef)ary,
- CFRangeMake(len, 0),
- objs,
- idx - len);
- CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)val);
- }
- else {
- CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx, (const void *)val);
- }
-#else
- if (idx >= ARY_CAPA(ary)) {
- long new_capa = ARY_CAPA(ary) / 2;
-
- if (new_capa < ARY_DEFAULT_SIZE) {
- new_capa = ARY_DEFAULT_SIZE;
}
- if (new_capa + idx < new_capa) {
- rb_raise(rb_eArgError, "index too big");
+ for (i = 0; i < (idx - len); i++) {
+ CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
}
- new_capa += idx;
- if (new_capa * (long)sizeof(VALUE) <= new_capa) {
- rb_raise(rb_eArgError, "index too big");
- }
- RESIZE_CAPA(ary, new_capa);
+ CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(val));
}
- if (idx > RARRAY_LEN(ary)) {
- rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
- idx-RARRAY_LEN(ary) + 1);
+ else {
+ CFArraySetValueAtIndex((CFMutableArrayRef)ary, idx, (const void *)RB2OC(val));
}
-
- if (idx >= RARRAY_LEN(ary)) {
- RARRAY(ary)->len = idx + 1;
- }
- GC_WB(&RARRAY_PTR(ary)[idx], val);
-#endif
}
-#if !WITH_OBJC
static VALUE
-ary_shared_array(VALUE klass, VALUE ary)
-{
- VALUE val = ary_alloc(klass);
-
- ary_make_shared(ary);
- RARRAY(val)->ptr = RARRAY(ary)->ptr;
- RARRAY(val)->len = RARRAY(ary)->len;
- RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
- FL_SET(val, ELTS_SHARED);
- return val;
-}
-#endif
-
-static VALUE
ary_shared_first(int argc, VALUE *argv, VALUE ary, int last, bool remove)
{
VALUE nv, result;
@@ -616,16 +408,11 @@
if (last) {
offset = ary_len - n;
}
-#if WITH_OBJC
result = rb_ary_new();
CFArrayAppendArray((CFMutableArrayRef)result, (CFArrayRef)ary, CFRangeMake(offset, n));
- if (remove)
+ if (remove) {
CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(offset, n), NULL, 0);
-#else
- result = ary_shared_array(rb_cArray, ary);
- RARRAY(result)->ptr += offset;
- RARRAY(result)->len = n;
-#endif
+ }
return result;
}
@@ -646,12 +433,8 @@
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
-#if WITH_OBJC
rb_ary_modify(ary);
- CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)item);
-#else
- rb_ary_store(ary, RARRAY_LEN(ary), item);
-#endif
+ CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)RB2OC(item));
return ary;
}
@@ -682,7 +465,6 @@
{
long n;
rb_ary_modify_check(ary);
-#if WITH_OBJC
n = RARRAY_LEN(ary);
if (n == 0) {
return Qnil;
@@ -692,18 +474,6 @@
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, n - 1);
return val;
}
-#else
- if (RARRAY_LEN(ary) == 0) return Qnil;
- if (!ARY_SHARED_P(ary) &&
- RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
- {
- RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2);
- }
- n = RARRAY_LEN(ary)-1;
- RARRAY(ary)->len = n;
- return RARRAY_PTR(ary)[n];
-#endif
}
/*
@@ -734,9 +504,6 @@
rb_ary_modify_check(ary);
result = ary_shared_first(argc, argv, ary, Qtrue, true);
-#if !WITH_OBJC
- RARRAY(ary)->len -= RARRAY_LEN(result);
-#endif
return result;
}
@@ -747,24 +514,8 @@
rb_ary_modify_check(ary);
if (RARRAY_LEN(ary) == 0) return Qnil;
-#if WITH_OBJC
top = RARRAY_AT(ary, 0);
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, 0);
-#else
- top = RARRAY_PTR(ary)[0];
- if (!ARY_SHARED_P(ary)) {
- if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
- MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
- RARRAY(ary)->len--;
- return top;
- }
- RARRAY_PTR(ary)[0] = Qnil;
- ary_make_shared(ary);
- }
- RARRAY(ary)->ptr++; /* shift ptr */
- RARRAY(ary)->len--;
-
-#endif
return top;
}
@@ -800,17 +551,6 @@
rb_ary_modify_check(ary);
result = ary_shared_first(argc, argv, ary, Qfalse, true);
-#if !WITH_OBJC
- n = RARRAY_LEN(result);
- if (ARY_SHARED_P(ary)) {
- RARRAY(ary)->ptr += n;
- RARRAY(ary)->len -= n;
- }
- else {
- MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
- RARRAY(ary)->len -= n;
- }
-#endif
return result;
}
@@ -830,26 +570,15 @@
static VALUE
rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
{
- if (argc == 0) return ary;
- rb_ary_modify(ary);
-#if WITH_OBJC
- {
- long i;
- for (i = argc - 1; i >= 0; i--)
- CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
- 0, (const void *)argv[i]);
+ int i;
+ if (argc == 0) {
+ return ary;
}
-#else
- if (RARRAY(ary)->aux.capa <= (len = RARRAY(ary)->len) + argc) {
- RESIZE_CAPA(ary, len + argc + ARY_DEFAULT_SIZE);
- }
+ rb_ary_modify(ary);
+ for (i = argc - 1; i >= 0; i--)
+ CFArrayInsertValueAtIndex((CFMutableArrayRef)ary,
+ 0, (const void *)RB2OC(argv[i]));
- /* sliding items */
- MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
- MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
- RARRAY(ary)->len += argc;
-#endif
-
return ary;
}
@@ -860,7 +589,6 @@
}
/* faster version - use this if you don't need to treat negative offset */
-#if WITH_OBJC
VALUE
rb_ary_elt(VALUE ary, long offset)
{
@@ -869,42 +597,29 @@
return Qnil;
if (offset < 0 || n <= offset)
return Qnil;
- return (VALUE)CFArrayGetValueAtIndex((CFArrayRef)ary, offset);
+ return OC2RB(CFArrayGetValueAtIndex((CFArrayRef)ary, offset));
}
-#else
-static inline VALUE
-rb_ary_elt(VALUE ary, long offset)
-{
- if (RARRAY_LEN(ary) == 0) return Qnil;
- if (offset < 0 || RARRAY_LEN(ary) <= offset) {
- return Qnil;
- }
- return RARRAY_PTR(ary)[offset];
-}
-#endif
const VALUE *
rb_ary_ptr(VALUE ary)
{
-#if WITH_OBJC
/* FIXME we could inline __CFArrayGetBucketsPtr for non-store arrays,
* for performance reasons.
*/
- const VALUE *values;
- long len;
+ VALUE *values;
+ long i, len;
len = RARRAY_LEN(ary);
if (len == 0)
return NULL;
- values = (const VALUE *)xmalloc(sizeof(VALUE) * len);
+ values = (VALUE *)xmalloc(sizeof(VALUE) * len);
CFArrayGetValues((CFArrayRef)ary, CFRangeMake(0, len),
(const void **)values);
+ for (i = 0; i < len; i++)
+ values[i] = OC2RB(values[i]);
GC_WB(&rb_objc_ary_get_struct2(ary)->cptr, values);
return values;
-#else
- return RARRAY_PTR(ary);
-#endif
}
VALUE
@@ -919,7 +634,6 @@
VALUE
rb_ary_subseq(VALUE ary, long beg, long len)
{
-#if WITH_OBJC
long n;
VALUE newary;
VALUE klass;
@@ -944,29 +658,6 @@
values, len);
}
return newary;
-#else
- VALUE klass, ary2, shared;
- VALUE *ptr;
-
- if (beg > RARRAY_LEN(ary)) return Qnil;
- if (beg < 0 || len < 0) return Qnil;
-
- if (RARRAY_LEN(ary) < len || RARRAY_LEN(ary) < beg + len) {
- len = RARRAY_LEN(ary) - beg;
- }
- klass = rb_obj_class(ary);
- if (len == 0) return ary_new(klass, 0);
-
- shared = ary_make_shared(ary);
- ptr = RARRAY_PTR(ary);
- ary2 = ary_alloc(klass);
- RARRAY(ary2)->ptr = ptr + beg;
- RARRAY(ary2)->len = len;
- RARRAY(ary2)->aux.shared = shared;
- FL_SET(ary2, ELTS_SHARED);
-
- return ary2;
-#endif
}
/*
@@ -1187,18 +878,11 @@
}
}
else {
-#if WITH_OBJC
CFIndex idx;
idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
- (const void *)val);
+ (const void *)RB2OC(val));
if (idx != -1)
return LONG2NUM(idx);
-#else
- for (i=0; i<n; i++) {
- if (rb_equal(RARRAY_AT(ary, i), val))
- return LONG2NUM(i);
- }
-#endif
}
return Qnil;
}
@@ -1238,20 +922,10 @@
}
else {
rb_scan_args(argc, argv, "01", &val);
-#if WITH_OBJC
i = CFArrayGetLastIndexOfValue((CFArrayRef)ary, CFRangeMake(0, n),
- (const void *)val);
+ (const void *)RB2OC(val));
if (i != -1)
return LONG2NUM(i);
-#else
- while (i--) {
- if (rb_equal(RARRAY_AT(ary, i), val))
- return LONG2NUM(i);
- if (i > n) {
- i = n;
- }
- }
-#endif
}
return Qnil;
}
@@ -1294,11 +968,10 @@
rlen = RARRAY_LEN(rpl);
}
rb_ary_modify(ary);
-#if WITH_OBJC
if (beg >= n) {
long i;
for (i = n; i < beg - n; i++) {
- CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)Qnil);
+ CFArrayAppendValue((CFMutableArrayRef)ary, (const void *)kCFNull);
}
if (rlen > 0)
CFArrayAppendArray((CFMutableArrayRef)ary, (CFArrayRef)rpl,
@@ -1318,40 +991,6 @@
values,
rlen);
}
-#else
- if (beg >= RARRAY_LEN(ary)) {
- len = beg + rlen;
- if (len >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, len);
- }
- rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
- if (rlen > 0) {
- MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
- }
- RARRAY(ary)->len = len;
- }
- else {
- long alen;
-
- if (beg + len > RARRAY_LEN(ary)) {
- len = RARRAY_LEN(ary) - beg;
- }
-
- alen = RARRAY_LEN(ary) + rlen - len;
- if (alen >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, alen);
- }
-
- if (len != rlen) {
- MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
- VALUE, RARRAY_LEN(ary) - (beg + len));
- RARRAY(ary)->len = alen;
- }
- if (rlen > 0) {
- MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
- }
- }
-#endif
}
/*
@@ -1560,38 +1199,28 @@
return Qfalse;
}
-#if WITH_OBJC
-static inline VALUE
-rb_ary_dup2(VALUE ary)
-{
- VALUE klass, dup;
- long n;
-
- klass = rb_obj_class(ary);
- dup = ary_new(klass, 0);
- n = RARRAY_LEN(ary);
- if (n > 0)
- CFArrayAppendArray((CFMutableArrayRef)dup, (CFArrayRef)ary,
- CFRangeMake(0, n));
- return dup;
-}
-#endif
-
VALUE
rb_ary_dup(VALUE ary)
{
-#if WITH_OBJC
- VALUE dup = rb_ary_dup2(ary);
-#else
- VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
+ VALUE dup;
- MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
- RARRAY(dup)->len = RARRAY_LEN(ary);
+ dup = (VALUE)CFArrayCreateMutableCopy(NULL, 0, (CFArrayRef)ary);
+ if (OBJ_TAINTED(ary))
+ OBJ_TAINT(dup);
-#endif
+ CFMakeCollectable((CFTypeRef)dup);
return dup;
}
+static VALUE
+rb_ary_clone(VALUE ary)
+{
+ VALUE clone = rb_ary_dup(ary);
+ if (OBJ_FROZEN(ary))
+ OBJ_FREEZE(clone);
+ return clone;
+}
+
extern VALUE rb_output_fs;
static VALUE
@@ -1613,19 +1242,7 @@
if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0);
if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue;
-#if WITH_OBJC
result = rb_str_buf_new(0);
-#else
- for (i=0; i<RARRAY_LEN(ary); i++) {
- tmp = rb_check_string_type(RARRAY_AT(ary, i));
- len += NIL_P(tmp) ? 10 : RSTRING_BYTELEN(tmp);
- }
- if (!NIL_P(sep)) {
- StringValue(sep);
- len += RSTRING_BYTELEN(sep) * (RARRAY_LEN(ary) - 1);
- }
- result = rb_str_buf_new(len);
-#endif
for (i=0, count=RARRAY_LEN(ary); i<count; i++) {
tmp = RARRAY_AT(ary, i);
@@ -1728,11 +1345,7 @@
static VALUE
rb_ary_to_a(VALUE ary)
{
-#if WITH_OBJC
if (!rb_objc_ary_is_pure(ary)) {
-#else
- if (rb_obj_class(ary) != rb_cArray) {
-#endif
VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
rb_ary_replace(dup, ary);
return dup;
@@ -1756,33 +1369,25 @@
VALUE
rb_ary_reverse(VALUE ary)
{
-#if WITH_OBJC
long n;
rb_ary_modify(ary);
n = RARRAY_LEN(ary);
if (n > 0) {
+ void **values;
+ CFRange range;
long i;
- for (i = 0; i < (n / 2); i++)
- CFArrayExchangeValuesAtIndices((CFMutableArrayRef)ary,
- i, n - i - 1);
- }
-#else
- VALUE *p1, *p2;
- VALUE tmp;
- rb_ary_modify(ary);
- if (RARRAY_LEN(ary) > 1) {
- p1 = RARRAY_PTR(ary);
- p2 = p1 + RARRAY_LEN(ary) - 1; /* points last item */
-
- while (p1 < p2) {
- tmp = *p1;
- *p1++ = *p2;
- *p2-- = tmp;
+ values = alloca(sizeof(void *) * n);
+ range = CFRangeMake(0, n);
+ CFArrayGetValues((CFArrayRef)ary, range, (const void **)values);
+ for (i = 0; i < (n / 2); i++) {
+ void *v = values[i];
+ values[i] = values[n - i - 1];
+ values[n - i - 1] = v;
}
+ CFArrayReplaceValues((CFMutableArrayRef)ary, range, (const void **)values, n);
}
-#endif
return ary;
}
@@ -1822,11 +1427,7 @@
static int
sort_1(const void *ap, const void *bp, void *dummy)
{
-#if WITH_OBJC
VALUE a = (VALUE)ap, b = (VALUE)bp;
-#else
- VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
-#endif
VALUE retval = rb_yield_values(2, a, b);
int n;
@@ -1838,18 +1439,10 @@
sort_2(const void *ap, const void *bp, void *dummy)
{
VALUE retval;
-#if WITH_OBJC
VALUE a = (VALUE)ap, b = (VALUE)bp;
-#else
- VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
-#endif
int n;
- if (FIXNUM_P(a) && FIXNUM_P(b)) {
- if ((long)a > (long)b) return 1;
- if ((long)a < (long)b) return -1;
- return 0;
- }
+ /* FIXME optimize!!! */
if (TYPE(a) == T_STRING) {
if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
}
@@ -1876,7 +1469,6 @@
* a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]
*/
-#if WITH_OBJC
static void
rb_ary_sort_bang1(VALUE ary, bool is_dup)
{
@@ -1899,34 +1491,12 @@
}
}
}
-#endif
VALUE
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
-#if WITH_OBJC
rb_ary_sort_bang1(ary, false);
-#else
- if (RARRAY_LEN(ary) > 1) {
- VALUE tmp = ary_make_shared(ary);
-
- RBASIC(tmp)->klass = 0;
- ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE),
- rb_block_given_p()?sort_1:sort_2, &RBASIC(tmp)->klass);
- if (RARRAY(ary)->ptr != RARRAY(tmp)->ptr) {
- xfree(RARRAY(ary)->ptr);
- RARRAY(ary)->ptr = RARRAY(tmp)->ptr;
- RARRAY(ary)->len = RARRAY(tmp)->len;
- RARRAY(ary)->aux.capa = RARRAY(tmp)->aux.capa;
- };
- FL_UNSET(ary, ELTS_SHARED);
- RARRAY(tmp)->ptr = 0;
- RARRAY(tmp)->len = 0;
- RARRAY(tmp)->aux.capa = 0;
- RBASIC(tmp)->klass = RBASIC(ary)->klass;
- }
-#endif
return ary;
}
@@ -2112,56 +1682,29 @@
VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
-#if WITH_OBJC
- long n, i;
+ long k, n, i;
CFRange r;
+ const void *ocitem;
rb_ary_modify(ary);
- r = CFRangeMake(0, RARRAY_LEN(ary));
- n = 0;
- while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r,
- (const void *)item)) != -1) {
+ ocitem = (const void *)RB2OC(item);
+ n = RARRAY_LEN(ary);
+ r = CFRangeMake(0, n);
+ k = 0;
+ while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary, r, ocitem)) != -1) {
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
- n++;
+ r.location = i;
+ r.length = --n - i;
+ k++;
}
- if (n == 0) {
+ if (k == 0) {
if (rb_block_given_p()) {
return rb_yield(item);
}
return Qnil;
}
return item;
-#else
- long i1, i2;
-
- for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
- VALUE e = RARRAY_PTR(ary)[i1];
-
- if (rb_equal(e, item)) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, e);
- }
- i2++;
- }
- if (RARRAY_LEN(ary) == i2) {
- if (rb_block_given_p()) {
- return rb_yield(item);
- }
- return Qnil;
- }
-
- rb_ary_modify(ary);
- if (RARRAY_LEN(ary) > i2) {
- RARRAY(ary)->len = i2;
- if (i2 * 2 < ARY_CAPA(ary) &&
- ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
- RESIZE_CAPA(ary, i2*2);
- }
- }
-
- return item;
-#endif
}
VALUE
@@ -2178,13 +1721,7 @@
rb_ary_modify(ary);
del = RARRAY_AT(ary, pos);
-#if WITH_OBJC
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, pos);
-#else
- MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
- RARRAY_LEN(ary)-pos-1);
- RARRAY(ary)->len--;
-#endif
return del;
}
@@ -2248,12 +1785,7 @@
if (alen < len || alen < pos + len) {
len = alen - pos;
}
-#if WITH_OBJC
arg2 = rb_ary_subseq(ary, pos, len);
-#else
- arg2 = rb_ary_new4(len, RARRAY_PTR(ary)+pos);
- RBASIC(arg2)->klass = rb_obj_class(ary);
-#endif
rb_ary_splice(ary, pos, len, Qundef); /* Qnil/rb_ary_new2(0) */
return arg2;
}
@@ -2295,30 +1827,16 @@
orign = n = RARRAY_LEN(ary);
for (i1 = i2 = 0; i1 < n; i1++) {
VALUE v = RARRAY_AT(ary, i1);
-#if WITH_OBJC
if (!RTEST(rb_yield(v))) {
continue;
}
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i1);
n--;
i1--;
-#else
- if (RTEST(rb_yield(v))) continue;
- if (i1 != i2) {
- rb_ary_store(ary, i2, v);
- }
- i2++;
-#endif
}
-#if WITH_OBJC
if (n == orign)
return Qnil;
-#else
- if (n == i2) return Qnil;
- if (i2 < RARRAY_LEN(ary))
- RARRAY(ary)->len = i2;
-#endif
return ary;
}
@@ -2492,22 +2010,10 @@
orig = to_ary(orig);
rb_ary_modify_check(copy);
if (copy == orig) return copy;
-#if WITH_OBJC
CFArrayRemoveAllValues((CFMutableArrayRef)copy);
CFArrayAppendArray((CFMutableArrayRef)copy,
(CFArrayRef)orig,
CFRangeMake(0, RARRAY_LEN(orig)));
-#else
- shared = ary_make_shared(orig);
- if (!ARY_SHARED_P(copy)) {
- ptr = RARRAY(copy)->ptr;
- xfree(ptr);
- }
- RARRAY(copy)->ptr = RARRAY(orig)->ptr;
- RARRAY(copy)->len = RARRAY(orig)->len;
- RARRAY(copy)->aux.shared = shared;
- FL_SET(copy, ELTS_SHARED);
-#endif
return copy;
}
@@ -2526,14 +2032,7 @@
rb_ary_clear(VALUE ary)
{
rb_ary_modify(ary);
-#if WITH_OBJC
CFArrayRemoveAllValues((CFMutableArrayRef)ary);
-#else
- RARRAY(ary)->len = 0;
- if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
- }
-#endif
return ary;
}
@@ -2603,15 +2102,6 @@
if (end < 0) {
rb_raise(rb_eArgError, "argument too big");
}
-#if !WITH_OBJC
- if (n < end) {
- if (end >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, end);
- }
- rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
- RARRAY(ary)->len = end;
- }
-#endif
if (block_p) {
VALUE v;
@@ -2619,25 +2109,14 @@
for (i=beg; i<end; i++) {
v = rb_yield(LONG2NUM(i));
-#if !WITH_OBJC
- if (i>=RARRAY_LEN(ary)) break;
-#endif
rb_ary_store(ary, i, v);
}
}
else {
-#if WITH_OBJC
long i;
for (i=beg; i<end; i++) {
rb_ary_store(ary, i, item);
}
-#else
- p = RARRAY_PTR(ary) + beg;
- pend = p + len;
- while (p < pend) {
- *p++ = item;
- }
-#endif
}
return ary;
}
@@ -2657,21 +2136,12 @@
{
VALUE z;
-#if WITH_OBJC
y = to_ary(y);
z = rb_ary_new2(0);
CFArrayAppendArray((CFMutableArrayRef)z,
(CFArrayRef)x, CFRangeMake(0, RARRAY_LEN(x)));
CFArrayAppendArray((CFMutableArrayRef)z,
(CFArrayRef)y, CFRangeMake(0, RARRAY_LEN(y)));
-#else
- y = to_ary(y);
- len = RARRAY_LEN(x) + RARRAY_LEN(y);
- z = rb_ary_new2(len);
- MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
- MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
- RARRAY(z)->len = len;
-#endif
return z;
}
@@ -2731,25 +2201,13 @@
if (LONG_MAX/len < n) {
rb_raise(rb_eArgError, "argument too big");
}
-#if WITH_OBJC
ary2 = ary_new(rb_obj_class(ary), 0);
for (i = 0; i < len; i++) {
CFArrayAppendArray((CFMutableArrayRef)ary2,
(CFArrayRef)ary,
CFRangeMake(0, n));
}
-#else
- len *= RARRAY_LEN(ary);
- ary2 = ary_new(rb_obj_class(ary), len);
- RARRAY(ary2)->len = len;
-
- for (i=0; i<len; i+=RARRAY_LEN(ary)) {
- MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
- }
- OBJ_INFECT(ary2, ary);
-#endif
-
return ary2;
}
@@ -2818,19 +2276,6 @@
return Qnil;
}
-static VALUE
-recursive_equal(VALUE ary1, VALUE ary2, int recur)
-{
- long i;
-
- if (recur) return Qfalse;
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
-}
-
/*
* call-seq:
* array == other_array -> bool
@@ -2855,8 +2300,7 @@
}
return rb_equal(ary2, ary1);
}
- if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
- return rb_exec_recursive(recursive_equal, ary1, ary2);
+ return CFEqual((CFTypeRef)ary1, (CFTypeRef)ary2) ? Qtrue : Qfalse;
}
static VALUE
@@ -2889,40 +2333,8 @@
return rb_exec_recursive(recursive_eql, ary1, ary2);
}
-static VALUE
-recursive_hash(VALUE ary, VALUE dummy, int recur)
-{
- long i, h;
- VALUE n;
-
- if (recur) {
- return LONG2FIX(0);
- }
- h = RARRAY_LEN(ary);
- for (i=0; i<RARRAY_LEN(ary); i++) {
- h = (h << 1) | (h<0 ? 1 : 0);
- n = rb_hash(RARRAY_AT(ary, i));
- h ^= NUM2LONG(n);
- }
- return LONG2FIX(h);
-}
-
/*
* call-seq:
- * array.hash -> fixnum
- *
- * Compute a hash-code for this array. Two arrays with the same content
- * will have the same hash code (and will compare using <code>eql?</code>).
- */
-
-static VALUE
-rb_ary_hash(VALUE ary)
-{
- return rb_exec_recursive(recursive_hash, ary, 0);
-}
-
-/*
- * call-seq:
* array.include?(obj) -> true or false
*
* Returns <code>true</code> if the given object is present in
@@ -2937,19 +2349,8 @@
VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
-#if WITH_OBJC
return CFArrayContainsValue((CFArrayRef)ary,
- CFRangeMake(0, RARRAY_LEN(ary)), (const void *)item) ? Qtrue : Qfalse;
-#else
- long i;
-
- for (i=0; i<RARRAY_LEN(ary); i++) {
- if (rb_equal(RARRAY_PTR(ary)[i], item)) {
- return Qtrue;
- }
- }
- return Qfalse;
-#endif
+ CFRangeMake(0, RARRAY_LEN(ary)), (const void *)RB2OC(item)) ? Qtrue : Qfalse;
}
@@ -3048,12 +2449,9 @@
ary3 = rb_ary_new();
for (i=0; i<RARRAY_LEN(ary1); i++) {
-#if WITH_OBJC
- if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)RARRAY_AT(ary1, i), NULL)) continue;
-#else
- if (st_lookup(RHASH_TBL(hash), RARRAY_PTR(ary1)[i], 0)) continue;
-#endif
+ const void *v = CFArrayGetValueAtIndex((CFArrayRef)ary1, i);
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)v, NULL))
+ continue;
rb_ary_push(ary3, rb_ary_elt(ary1, i));
}
return ary3;
@@ -3086,13 +2484,10 @@
for (i=0; i<RARRAY_LEN(ary1); i++) {
v = vv = rb_ary_elt(ary1, i);
-#if WITH_OBJC
- if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+ id ocvv = RB2OC(vv);
+ if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)vv);
-#else
- if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+ (const void *)ocvv);
rb_ary_push(ary3, v);
}
}
@@ -3124,25 +2519,19 @@
for (i=0; i<RARRAY_LEN(ary1); i++) {
v = vv = rb_ary_elt(ary1, i);
-#if WITH_OBJC
- if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+ id ocvv = RB2OC(vv);
+ if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)vv);
-#else
- if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+ (const void *)ocvv);
rb_ary_push(ary3, v);
}
}
for (i=0; i<RARRAY_LEN(ary2); i++) {
v = vv = rb_ary_elt(ary2, i);
-#if WITH_OBJC
- if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
+ id ocvv = RB2OC(vv);
+ if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)ocvv)) {
CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)vv);
-#else
- if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
+ (const void *)ocvv);
rb_ary_push(ary3, v);
}
}
@@ -3166,7 +2555,6 @@
static VALUE
rb_ary_uniq_bang(VALUE ary)
{
-#if WITH_OBJC
long i, n;
bool changed;
@@ -3174,13 +2562,15 @@
n = RARRAY_LEN(ary);
for (i = 0, changed = false; i < n; i++) {
VALUE e;
+ id oce;
long idx;
CFRange r;
e = RARRAY_AT(ary, i);
+ oce = RB2OC(e);
r = CFRangeMake(i + 1, n - i - 1);
while ((idx = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
- r, (const void *)e)) != -1) {
+ r, (const void *)oce)) != -1) {
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, idx);
r.location = idx;
r.length = --n - idx;
@@ -3189,30 +2579,7 @@
}
if (!changed)
return Qnil;
-#else
- VALUE hash, v, vv;
- long i, j;
- hash = ary_make_hash(ary, 0);
-
- if (RARRAY_LEN(ary) == RHASH_SIZE(hash)) {
- return Qnil;
- }
- for (i=j=0; i<RARRAY_LEN(ary); i++) {
- v = vv = rb_ary_elt(ary, i);
-#if WITH_OBJC
- if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)vv)) {
- CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)vv);
-#else
- if (st_delete(RHASH_TBL(hash), (st_data_t*)&vv, 0)) {
-#endif
- rb_ary_store(ary, j++, v);
- }
- }
- RARRAY(ary)->len = j;
-#endif
-
return ary;
}
@@ -3248,7 +2615,6 @@
static VALUE
rb_ary_compact_bang(VALUE ary)
{
-#if WITH_OBJC
long i, n, k;
CFRange r;
@@ -3259,34 +2625,15 @@
k = 0;
r = CFRangeMake(0, n);
while ((i = CFArrayGetFirstIndexOfValue((CFArrayRef)ary,
- r, (const void *)Qnil)) != -1) {
+ r, (const void *)kCFNull)) != -1) {
CFArrayRemoveValueAtIndex((CFMutableArrayRef)ary, i);
r.location = i;
- r.length = n - i;
+ r.length = --n - i;
k++;
}
if (k == 0)
return Qnil;
-#else
- VALUE *p, *t, *end;
- long n;
- rb_ary_modify(ary);
- p = t = RARRAY_PTR(ary);
- end = p + RARRAY_LEN(ary);
-
- while (t < end) {
- if (NIL_P(*t)) t++;
- else *p++ = *t++;
- }
- if (RARRAY_LEN(ary) == (p - RARRAY_PTR(ary))) {
- return Qnil;
- }
- n = p - RARRAY_PTR(ary);
- RESIZE_CAPA(ary, n);
- RARRAY(ary)->len = n;
-#endif
-
return ary;
}
@@ -3336,35 +2683,20 @@
if (!rb_block_given_p())
return LONG2NUM(count);
-#if WITH_OBJC
for (i = 0; i < count; i++) {
if (RTEST(rb_yield(RARRAY_AT(ary, i))))
n++;
}
-#else
- for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
- if (RTEST(rb_yield(*p))) n++;
- }
-#endif
}
else {
VALUE obj;
- long i, count = RARRAY_LEN(ary);
+ long count = RARRAY_LEN(ary);
rb_scan_args(argc, argv, "1", &obj);
if (rb_block_given_p()) {
rb_warn("given block not used");
}
-#if WITH_OBJC
- for (i = 0; i < count; i++) {
- if (rb_equal(RARRAY_AT(ary, i), obj))
- n++;
- }
-#else
- for (p = RARRAY_PTR(ary), pend = p + RARRAY_LEN(ary); p < pend; p++) {
- if (rb_equal(*p, obj)) n++;
- }
-#endif
+ n = CFArrayGetCountOfValue((CFArrayRef)ary, CFRangeMake(0, count), RB2OC(obj));
}
return LONG2NUM(n);
@@ -3388,11 +2720,6 @@
while (i < RARRAY_LEN(ary)) {
elt = RARRAY_AT(ary, i++);
tmp = rb_check_array_type(elt);
-#if !WITH_OBJC
- if (RBASIC(result)->klass) {
- rb_raise(rb_eRuntimeError, "flatten reentered");
- }
-#endif
if (NIL_P(tmp) || (level >= 0 && RARRAY_LEN(stack) / 2 >= level)) {
rb_ary_push(result, elt);
}
@@ -3422,9 +2749,6 @@
st_free_table(memo);
-#if !WITH_OBJC
- RBASIC(result)->klass = rb_class_of(ary);
-#endif
return result;
}
@@ -3513,13 +2837,7 @@
rb_ary_modify(ary);
while (i) {
long j = rb_genrand_real()*i;
-#if WITH_OBJC
CFArrayExchangeValuesAtIndices((CFMutableArrayRef)ary, --i, j);
-#else
- VALUE tmp = RARRAY_AT(ary, --i);
- RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
- RARRAY_PTR(ary)[j] = tmp;
-#endif
}
return ary;
}
@@ -3637,16 +2955,8 @@
/* Build a ruby array of the corresponding values */
/* And yield it to the associated block */
VALUE result = rb_ary_new2(r);
-#if WITH_OBJC
for (j = 0; j < r; j++)
rb_ary_store(result, j, RARRAY_AT(values, p[j]));
-#else
- VALUE *result_array = RARRAY_PTR(result);
- const VALUE *values_array = RARRAY_PTR(values);
-
- for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
- RARRAY(result)->len = r;
-#endif
rb_yield(result);
}
}
@@ -3706,19 +3016,11 @@
long *p = (long*)RSTRING_BYTEPTR(t0);
volatile VALUE t1 = tmpbuf(n,sizeof(int));
int *used = (int*)RSTRING_BYTEPTR(t1);
-#if WITH_OBJC
VALUE ary0 = rb_ary_dup(ary);
-#else
- VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
-#endif
for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
-#if !WITH_OBJC
- RB_GC_GUARD(t0);
- RB_GC_GUARD(t1);
-#endif
}
return ary;
}
@@ -3793,9 +3095,6 @@
volatile VALUE cc = rb_ary_new2(n);
long lev = 0;
-#if !WITH_OBJC
- RBASIC(cc)->klass = 0;
-#endif
MEMZERO(stack, long, n);
stack[0] = -1;
for (i = 0; i < nlen; i++) {
@@ -3804,11 +3103,7 @@
stack[lev+1] = stack[lev]+1;
rb_ary_store(cc, lev, RARRAY_AT(ary, stack[lev+1]));
}
-#if WITH_OBJC
rb_yield(rb_ary_dup(cc));
-#else
- rb_yield(cc);
-#endif
do {
stack[lev--]++;
} while (lev && (stack[lev+1]+n == len+lev+1));
@@ -3990,13 +3285,9 @@
return rb_ary_drop(ary, LONG2FIX(i));
}
-#if WITH_OBJC
-
-#define NSCFARRAY() RCLASS_OCID(rb_cCFArray)
-
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFARRAY();
+ *(Class *)x = (Class)rb_cCFArray;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -4004,7 +3295,7 @@
bool
rb_objc_ary_is_pure(VALUE ary)
{
- return *(Class *)ary == NSCFARRAY();
+ return *(Class *)ary == (Class)rb_cCFArray;
}
static CFIndex
@@ -4114,12 +3405,12 @@
class_addMethod(klass, sel_registerName("_cfindexOfObject:inRange:"),
method_getImplementation(m), method_getTypeEncoding(m));
}
+
+ rb_define_alloc_func((VALUE)klass, ary_alloc);
#undef INSTALL_METHOD
}
-#endif
-
/* Arrays are ordered, integer-indexed collections of any object.
* Array indexing starts at 0, as in C or Java. A negative index is
* assumed to be relative to the end of the array---that is, an index of -1
@@ -4130,19 +3421,14 @@
void
Init_Array(void)
{
-#if WITH_OBJC
- rb_cCFArray = rb_objc_import_class((Class)objc_getClass("NSCFArray"));;
- rb_cArray = rb_objc_import_class((Class)objc_getClass("NSArray"));
- rb_cArrayRuby =
- rb_objc_import_class((Class)objc_getClass("NSMutableArray"));
- FL_UNSET(rb_cArrayRuby, RCLASS_OBJC_IMPORTED);
- rb_const_set(rb_cObject, rb_intern("Array"), rb_cArrayRuby);
-#else
- rb_cArray = rb_define_class("Array", rb_cObject);
-#endif
+ rb_cCFArray = (VALUE)objc_getClass("NSCFArray");
+ rb_cArray = rb_cNSArray = (VALUE)objc_getClass("NSArray");
+ rb_cNSMutableArray = (VALUE)objc_getClass("NSMutableArray");
+ rb_set_class_path(rb_cNSMutableArray, rb_cObject, "NSMutableArray");
+ rb_const_set(rb_cObject, rb_intern("Array"), rb_cNSMutableArray);
+
rb_include_module(rb_cArray, rb_mEnumerable);
- rb_define_alloc_func(rb_cArray, ary_alloc);
rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
@@ -4156,7 +3442,6 @@
rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
- rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
@@ -4224,10 +3509,12 @@
rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
rb_define_method(rb_cArray, "_count", rb_ary_count, -1);
-#if WITH_OBJC
- /* to maintain backwards compatibility with our /etc/irbrc file */
+
+ /* to maintain backwards compatibility with our /etc/irbrc file
+ * TODO: fix /etc/irbrc to use #count, and remove this method.
+ */
rb_define_method(rb_cArray, "nitems", rb_ary_count, -1);
-#endif
+
rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, 0);
rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, 0);
rb_define_method(rb_cArray, "choice", rb_ary_choice, 0);
@@ -4241,5 +3528,9 @@
rb_define_method(rb_cArray, "drop", rb_ary_drop, 1);
rb_define_method(rb_cArray, "drop_while", rb_ary_drop_while, 0);
+ /* to return mutable copies */
+ rb_define_method(rb_cArray, "dup", rb_ary_dup, 0);
+ rb_define_method(rb_cArray, "clone", rb_ary_clone, 0);
+
id_cmp = rb_intern("<=>");
}
Modified: MacRuby/trunk/bignum.c
===================================================================
--- MacRuby/trunk/bignum.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/bignum.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -82,7 +82,7 @@
ds = ALLOC_N(BDIGIT, len);
MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
- RBIGNUM(big)->as.heap.digits = ds;
+ GC_WB(&RBIGNUM(big)->as.heap.digits, ds);
RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
}
}
@@ -98,10 +98,11 @@
}
else {
if (RBIGNUM_LEN(big) == 0) {
- RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
+ GC_WB(&RBIGNUM(big)->as.heap.digits, ALLOC_N(BDIGIT, len));
}
else {
REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
+ GC_WB(&RBIGNUM(big)->as.heap.digits, RBIGNUM(big)->as.heap.digits);
}
}
}
@@ -2660,6 +2661,59 @@
return Qtrue;
}
+#if WITH_OBJC
+static const char *
+imp_rb_bignum_objCType(void *rcv, SEL sel)
+{
+ return "q";
+}
+
+static void
+imp_rb_bignum_getValue(void *rcv, SEL sel, void *buffer)
+{
+ long long v = NUM2LL(rcv);
+ *(long long *)buffer = v;
+}
+
+static long long
+imp_rb_bignum_longLongValue(void *rcv, SEL sel)
+{
+ return NUM2LL(rcv);
+}
+
+static bool
+imp_rb_bignum_isEqual(void *rcv, SEL sel, void *other)
+{
+ if (other == NULL)
+ return false;
+ if (*(Class *)other != (Class)rb_cBignum)
+ return false;
+ return rb_big_eq((VALUE)rcv, (VALUE)other) == Qtrue;
+}
+
+static inline void
+rb_objc_install_method(Class klass, SEL sel, IMP imp)
+{
+ Method method = class_getInstanceMethod(klass, sel);
+ assert(method != NULL);
+ assert(class_addMethod(klass, sel, imp, method_getTypeEncoding(method)));
+}
+
+static void
+rb_install_nsnumber_primitives(void)
+{
+ Class klass = (Class)rb_cBignum;
+ rb_objc_install_method(klass, sel_registerName("objCType"),
+ (IMP)imp_rb_bignum_objCType);
+ rb_objc_install_method(klass, sel_registerName("getValue:"),
+ (IMP)imp_rb_bignum_getValue);
+ rb_objc_install_method(klass, sel_registerName("longLongValue"),
+ (IMP)imp_rb_bignum_longLongValue);
+ rb_objc_install_method(klass, sel_registerName("isEqual:"),
+ (IMP)imp_rb_bignum_isEqual);
+}
+#endif
+
/*
* Bignum objects hold integers outside the range of
* Fixnum. Bignum objects are created
@@ -2716,4 +2770,8 @@
rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
power_cache_init();
+
+#if WITH_OBJC
+ rb_install_nsnumber_primitives();
+#endif
}
Modified: MacRuby/trunk/bs.c
===================================================================
--- MacRuby/trunk/bs.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/bs.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -205,7 +205,7 @@
return ret;
}
-#define MAX_ENCODE_LEN 1024
+#define MAX_ENCODE_LEN 2048
#ifndef MIN
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -252,7 +252,7 @@
p_src = pos + 1;
pos = strchr(p_src, '"');
if (pos == NULL) {
- // XXX NSLog("Can't find the end of field delimiter starting at %d", p_src - src);
+ fprintf(stderr, "Can't find the end of field delimiter starting at %d\n", p_src - src);
goto bails;
}
if (field != NULL) {
@@ -307,19 +307,19 @@
}
if (ok == false) {
- //XXX DLOG("MDLOSX", "Can't find the field encoding starting at %d", p_src - src);
+ fprintf(stderr, "Can't find the field encoding starting at %d\n", p_src - src);
goto bails;
}
if (opposite == '}' || opposite == ')') {
char buf[MAX_ENCODE_LEN];
char buf2[MAX_ENCODE_LEN];
-
+
strncpy(buf, p_src, MIN(sizeof buf, i));
buf[MIN(sizeof buf, i)] = '\0';
if (!undecorate_struct_type(buf, buf2, sizeof buf2, NULL, 0, NULL)) {
- // XXX DLOG("MDLOSX", "Can't un-decode the field encoding '%s'", buf);
+ fprintf(stderr, "Can't un-decode the field encoding '%s'\n", buf);
goto bails;
}
@@ -597,10 +597,10 @@
CHECK_ATTRIBUTE(struct_name, "name");
if (!undecorate_struct_type(struct_decorated_type, type,
- MAX_ENCODE_LEN, fields, 128,
+ sizeof type, fields, 128,
&field_count)) {
BAIL("Can't handle structure '%s' with type '%s'",
- name, struct_decorated_type);
+ struct_name, struct_decorated_type);
}
free(struct_decorated_type);
@@ -1063,7 +1063,6 @@
// FIXME this is inefficient
memcpy(&methods[*methods_count], method,
sizeof(bs_element_method_t));
- free(method);
(*methods_count)++;
@@ -1071,7 +1070,8 @@
klass->class_methods = methods;
else
klass->instance_methods = methods;
-
+
+ free(method);
method = NULL;
break;
}
Modified: MacRuby/trunk/class.c
===================================================================
--- MacRuby/trunk/class.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/class.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,18 +1,20 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's class.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- class.c -
-
- $Author: akr $
- created at: Tue Aug 10 15:05:44 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/signal.h"
#include "ruby/node.h"
#include "ruby/st.h"
+#include "debug.h"
+#include "id.h"
#include <ctype.h>
extern st_table *rb_class_tbl;
@@ -20,87 +22,6 @@
#define VISI(x) ((x)&NOEX_MASK)
#define VISI_CHECK(x,f) (VISI(x) == (f))
-static VALUE
-class_init(VALUE obj)
-{
- GC_WB(&RCLASS(obj)->ptr, ALLOC(rb_classext_t));
- RCLASS_IV_TBL(obj) = 0;
- RCLASS_M_TBL(obj) = 0;
- RCLASS_SUPER(obj) = 0;
- RCLASS_IV_INDEX_TBL(obj) = 0;
- return obj;
-}
-
-#if WITH_OBJC
-
-extern st_table *rb_objc_class_tbl;
-
-VALUE
-rb_objc_import_class(Class ocklass)
-{
- VALUE rbklass;
- ID nameid;
- VALUE super;
-
- assert(ocklass != NULL);
- assert(class_isMetaClass(ocklass) == 0);
- assert(rb_objc_class_tbl != NULL);
-
- if (st_lookup(rb_objc_class_tbl, (st_data_t)ocklass, (st_data_t *)&rbklass))
- return rbklass;
-
-//printf("import %s (%p)\n", class_getName(ocklass), ocklass);
-
- {
- NEWOBJ(obj, struct RClass);
- OBJSETUP(obj, rb_cClass, T_CLASS);
- rbklass = (VALUE)obj;
- }
-
- RBASIC(rbklass)->isa = ocklass->isa;
- RCLASS(rbklass)->ocklass = ocklass;
-
- class_init(rbklass);
-
- RCLASS_M_TBL(rbklass) = st_init_numtable();
-
- nameid = rb_intern(class_getName(ocklass));
-
- if (rb_cObject != 0 && RCLASS_IV_TBL(rb_cObject) != NULL)
- st_delete(RCLASS_IV_TBL(rb_cObject), (st_data_t*)&nameid, NULL);
- rb_const_set((rb_cObject != 0 ? rb_cObject : rbklass), nameid, rbklass);
-
- /* FIXME do we need to maintain rb_class_tbl anymore? */
- st_insert(rb_class_tbl, (st_data_t)nameid, (st_data_t)rbklass);
- st_insert(rb_objc_class_tbl, (st_data_t)ocklass, (st_data_t)rbklass);
-
- ocklass = class_getSuperclass(ocklass);
-
- /* Hack: make sure that all classes that inherit from NSObject have their
- * Ruby class counterpart inherit from Object first.
- * This is because constants declared in Object are meant to be visible
- * in all scopes, and we need to be able to access them in Ruby-written
- * subclasses of Objective-C classes.
- */
- if (rb_cBasicObject != 0
- && rb_cObject != 0
- && ocklass == RCLASS_OCID(rb_cBasicObject)) {
- super = rb_cObject;
- }
- else {
- super = ocklass == NULL ? 0 : rb_objc_import_class(ocklass);
- }
-
- RCLASS_SUPER(rbklass) = super;
- OBJ_INFECT(rbklass, super);
- FL_SET(rbklass, RCLASS_OBJC_IMPORTED);
-
- if (super != 0)
- rb_make_metaclass(rbklass, RBASIC(super)->klass);
-
- return rbklass;
-}
-
void rb_objc_install_array_primitives(Class);
void rb_objc_install_hash_primitives(Class);
void rb_objc_install_string_primitives(Class);
@@ -110,16 +31,19 @@
{
if (rb_cArray != 0 && rb_cHash != 0 && rb_cString != 0) {
do {
- if (ocsuper == RCLASS_OCID(rb_cArray)) {
+ if (ocsuper == (Class)rb_cArray) {
rb_objc_install_array_primitives(ocklass);
+ RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_ARRAY_SUBCLASS);
return true;
}
- if (ocsuper == RCLASS_OCID(rb_cHash)) {
+ if (ocsuper == (Class)rb_cHash) {
rb_objc_install_hash_primitives(ocklass);
+ RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_HASH_SUBCLASS);
return true;
}
- if (ocsuper == RCLASS_OCID(rb_cString)) {
+ if (ocsuper == (Class)rb_cString) {
rb_objc_install_string_primitives(ocklass);
+ RCLASS_SET_VERSION_FLAG(ocklass, RCLASS_IS_STRING_SUBCLASS);
return true;
}
ocsuper = class_getSuperclass(ocsuper);
@@ -130,24 +54,42 @@
}
static VALUE
-rb_objc_alloc_class(const char *name, VALUE *psuper, VALUE flags, VALUE klass)
+rb_class_allocate_instance(VALUE klass)
{
- VALUE super, obj;
- Class ocklass, ocsuper;
- char ocname[128];
+ NEWOBJ(obj, struct RObject);
+ OBJSETUP(obj, klass, T_OBJECT);
+ return (VALUE)obj;
+}
- super = psuper == NULL ? 0 : *psuper;
+static VALUE
+rb_objc_init(VALUE rcv)
+{
+ rb_funcall(rcv, idInitialize, 0);
+ return rcv;
+}
+void
+rb_define_object_special_methods(VALUE klass)
+{
+ rb_define_alloc_func(klass, rb_class_allocate_instance);
+ rb_define_singleton_method(klass, "new", rb_class_new_instance, -1);
+ rb_define_method(klass, "dup", rb_obj_dup, 0);
+ rb_define_method(klass, "init", rb_objc_init, 0);
+ rb_define_method(klass, "initialize_copy", rb_obj_init_copy, 1);
+}
+
+static VALUE
+rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
+{
+ Class ocklass;
+ char ocname[128];
+ int version_flag;
+
if (name == NULL) {
static long anon_count = 1;
snprintf(ocname, sizeof ocname, "RBAnonymous%ld", ++anon_count);
}
else {
- if (super == rb_cBasicObject && strcmp(name, "Object") != 0) {
- rb_warn("Do not subclass NSObject directly, please subclass " \
- "Object instead.");
- super = *psuper = rb_cObject;
- }
if (objc_getClass(name) != NULL) {
long count = 1;
snprintf(ocname, sizeof ocname, "RB%s", name);
@@ -161,28 +103,31 @@
}
}
- ocsuper = super == 0 ? NULL : RCLASS_OCID(super);
- ocklass = objc_allocateClassPair(ocsuper, ocname, 0);
+ if (super == 0)
+ super = rb_cObject;
+
+ ocklass = objc_allocateClassPair((Class)super, ocname, sizeof(id));
assert(ocklass != NULL);
- {
- NEWOBJ(obj2, struct RClass);
- OBJSETUP(obj2, klass, flags);
- obj = (VALUE)obj2;
+ version_flag = RCLASS_IS_RUBY_CLASS;
+ if (flags == T_MODULE) {
+ version_flag |= RCLASS_IS_MODULE;
}
+ if (super == rb_cObject) {
+ version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+ }
+ else if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS) {
+ version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+ }
- RBASIC(obj)->isa = ocklass->isa;
- RCLASS(obj)->ocklass = ocklass;
+ class_setVersion(ocklass, version_flag);
- rb_objc_retain((const void *)obj); /* classes should never be released */
+ DLOG("DEFC", "%s < %s (version=%d)", ocname, class_getName(class_getSuperclass((Class)ocklass)), version_flag);
- if (name == NULL)
- FL_SET(obj, RCLASS_ANONYMOUS);
-
if (klass != 0)
- rb_objc_install_primitives(ocklass, ocsuper);
+ rb_objc_install_primitives(ocklass, (Class)super);
- return obj;
+ return (VALUE)ocklass;
}
VALUE
@@ -190,90 +135,23 @@
{
VALUE klass;
- klass = rb_objc_alloc_class(name, &super, T_CLASS, rb_cClass);
-
- class_init(klass);
-
- objc_registerClassPair(RCLASS_OCID(klass));
+ klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
+ objc_registerClassPair((Class)klass);
- if (name != NULL)
- st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
- st_insert(rb_objc_class_tbl, (st_data_t)RCLASS_OCID(klass),
- (st_data_t)klass);
-
- RCLASS_M_TBL(klass) = st_init_numtable();
- RCLASS_SUPER(klass) = super;
-
- OBJ_INFECT(klass, super);
-
- return klass;
-}
-
-VALUE
-rb_objc_rename_class(VALUE klass, const char *name)
-{
-#if 0
- Class ocorig;
- Class ocnew;
- char *ocname;
- unsigned i, count;
-
- count = strlen(name);
- ocname = (char *)alloca(count + 3);
- ocname[0] = 'R';
- ocname[1] = 'B';
- for (i = 0; i < count; i++) {
- char c = name[i];
- if (c == ':')
- c = '_';
- ocname[i + 2] = c;
+ if (super == rb_cNSObject) {
+ rb_define_object_special_methods(klass);
}
- ocname[count + 2] = '\0';
- ocorig = RCLASS_OCID(klass);
+ if (name != NULL && rb_class_tbl != NULL)
+ st_insert(rb_class_tbl, (st_data_t)rb_intern(name), (st_data_t)klass);
- //printf("renamed class %p %s to %s\n", klass, class_getName(ocorig), ocname);
-
- ocnew = objc_duplicateClass(ocorig, ocname, 0);
-
- RBASIC(klass)->isa = ocnew->isa;
- RCLASS(klass)->ocklass = ocnew;
-
- //printf("old %p new %p\n", ocorig, ocnew);
-
- //objc_disposeClassPair(ocorig);
-
return klass;
-#endif
- return klass;
}
-#endif /* WITH_OBJC */
-
-static VALUE
-class_alloc(VALUE flags, VALUE klass)
-{
-#if WITH_OBJC
- VALUE obj = rb_objc_alloc_class(NULL, NULL, flags, klass);
-#else
- NEWOBJ(obj, struct RClass);
- OBJSETUP(obj, klass, flags);
-#endif
- return class_init((VALUE)obj);
-}
-
VALUE
rb_class_boot(VALUE super)
{
-#if WITH_OBJC
VALUE klass = rb_objc_create_class(NULL, super);
-#else
- VALUE klass = class_alloc(T_CLASS, rb_cClass);
-
- RCLASS_SUPER(klass) = super;
- RCLASS_M_TBL(klass) = st_init_numtable();
-#endif
- OBJ_INFECT(klass, super);
return (VALUE)klass;
}
@@ -284,7 +162,7 @@
rb_raise(rb_eTypeError, "superclass must be a Class (%s given)",
rb_obj_classname(super));
}
- if (RBASIC(super)->flags & FL_SINGLETON) {
+ if (RCLASS_SINGLETON(super)) {
rb_raise(rb_eTypeError, "can't make subclass of singleton class");
}
}
@@ -300,57 +178,34 @@
return rb_class_boot(super);
}
-struct clone_method_data {
- st_table *tbl;
- VALUE klass;
-};
-
-static int
-clone_method(ID mid, NODE *body, struct clone_method_data *data)
-{
- if (body == 0) {
- st_insert(data->tbl, mid, 0);
- }
- else {
- st_insert(data->tbl, mid,
- (st_data_t)
- NEW_FBODY(
- NEW_METHOD(body->nd_body->nd_body,
- data->klass, /* TODO */
- body->nd_body->nd_noex),
- 0));
- }
- return ST_CONTINUE;
-}
-
/* :nodoc: */
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
rb_obj_init_copy(clone, orig);
- if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC(clone)->klass = rb_singleton_class_clone(orig);
- }
- RCLASS_SUPER(clone) = RCLASS_SUPER(orig);
-#if WITH_OBJC
{
- Class ocsuper;
- extern VALUE rb_cStringRuby;
- extern VALUE rb_cArrayRuby;
- extern VALUE rb_cHashRuby;
- if (orig == rb_cStringRuby
- || orig == rb_cArrayRuby
- || orig == rb_cHashRuby) {
- ocsuper = RCLASS_OCID(orig);
+ VALUE super;
+ int version_flag;
+
+ if (orig == rb_cNSMutableString
+ || orig == rb_cNSMutableArray
+ || orig == rb_cNSMutableHash) {
+ super = orig;
rb_warn("cloning class `%s' is not supported, creating a " \
"subclass instead", rb_class2name(orig));
}
else {
- ocsuper = class_getSuperclass(RCLASS_OCID(orig));
+ super = RCLASS_SUPER(orig);
}
- class_setSuperclass(RCLASS(clone)->ocklass, ocsuper);
+ RCLASS_SUPER(clone) = super;
+
+ version_flag = RCLASS_IS_RUBY_CLASS;
+ if ((RCLASS_VERSION(super) & RCLASS_IS_OBJECT_SUBCLASS) == RCLASS_IS_OBJECT_SUBCLASS)
+ version_flag |= RCLASS_IS_OBJECT_SUBCLASS;
+
+ class_setVersion((Class)clone, version_flag);
}
-#endif
+#if 0 // TODO
if (RCLASS_IV_TBL(orig)) {
ID id;
@@ -368,6 +223,7 @@
st_foreach(RCLASS_M_TBL(orig), clone_method,
(st_data_t)&data);
}
+#endif
return clone;
}
@@ -376,16 +232,11 @@
VALUE
rb_class_init_copy(VALUE clone, VALUE orig)
{
- if (RCLASS_SUPER(clone) != 0) {
- rb_raise(rb_eTypeError, "already initialized class");
- }
- if (FL_TEST(orig, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(orig)) {
rb_raise(rb_eTypeError, "can't copy singleton class");
}
clone = rb_mod_init_copy(clone, orig);
-#if WITH_OBJC
- rb_objc_install_primitives(RCLASS_OCID(clone), RCLASS_OCID(orig));
-#endif
+ rb_objc_install_primitives((Class)clone, (Class)orig);
return clone;
}
@@ -393,100 +244,82 @@
rb_singleton_class_clone(VALUE obj)
{
VALUE klass = RBASIC(obj)->klass;
-
- if (!FL_TEST(klass, FL_SINGLETON))
+ if (!RCLASS_SINGLETON(klass)) {
return klass;
+ }
else {
- struct clone_method_data data;
/* copy singleton(unnamed) class */
- VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+ VALUE clone = rb_objc_create_class(NULL, RCLASS_SUPER(klass));
- if (BUILTIN_TYPE(obj) == T_CLASS) {
- RBASIC(clone)->klass = (VALUE)clone;
+ CFMutableDictionaryRef ivar_dict = rb_class_ivar_dict(klass);
+ if (ivar_dict != NULL) {
+ CFMutableDictionaryRef cloned_ivar_dict;
+
+ cloned_ivar_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ivar_dict);
+ rb_class_ivar_set_dict(clone, cloned_ivar_dict);
+ CFMakeCollectable(cloned_ivar_dict);
}
- else {
- RBASIC(clone)->klass = rb_singleton_class_clone(klass);
- }
- RCLASS_SUPER(clone) = RCLASS_SUPER(klass);
- if (RCLASS_IV_TBL(klass)) {
- GC_WB(&RCLASS_IV_TBL(clone), st_copy(RCLASS_IV_TBL(klass)));
+ Method *methods;
+ unsigned i, methods_count;
+ methods = class_copyMethodList((Class)klass, &methods_count);
+ if (methods != NULL) {
+ for (i = 0; i < methods_count; i++) {
+ Method method = methods[i], method2;
+ method2 = class_getInstanceMethod((Class)clone, method_getName(method));
+ if (method2 != class_getInstanceMethod((Class)RCLASS_SUPER(clone), method_getName(method))) {
+ method_setImplementation(method2, method_getImplementation(method));
+ }
+ else {
+ assert(class_addMethod((Class)clone,
+ method_getName(method),
+ method_getImplementation(method),
+ method_getTypeEncoding(method)));
+ }
+ }
+ free(methods);
}
- GC_WB(&RCLASS_M_TBL(clone), st_init_numtable());
- data.tbl = RCLASS_M_TBL(clone);
- data.klass = (VALUE)clone;
- st_foreach(RCLASS_M_TBL(klass), clone_method,
- (st_data_t)&data);
+
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
- FL_SET(clone, FL_SINGLETON);
-#if WITH_OBJC
- objc_registerClassPair(RCLASS_OCID(clone));
-#endif
- return (VALUE)clone;
+ if (RCLASS_SUPER(clone) == rb_cNSObject) {
+ RCLASS_VERSION(clone) ^= RCLASS_IS_OBJECT_SUBCLASS;
+ }
+ RCLASS_SET_VERSION_FLAG(clone, RCLASS_IS_SINGLETON);
+
+ return clone;
}
}
void
rb_singleton_class_attached(VALUE klass, VALUE obj)
{
- if (FL_TEST(klass, FL_SINGLETON)) {
- if (!RCLASS_IV_TBL(klass)) {
- GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
- }
- st_insert(RCLASS_IV_TBL(klass), rb_intern("__attached__"), obj);
+ if (RCLASS_SINGLETON(klass)) {
+ static ID attachedId = 0;
+ if (attachedId == 0)
+ attachedId = rb_intern("__attached__");
+ rb_ivar_set(klass, attachedId, obj);
}
}
VALUE
rb_make_metaclass(VALUE obj, VALUE super)
{
- bool pure;
-
-#if WITH_OBJC
- pure = rb_objc_is_non_native(obj);
-#else
- pure = false;
-#endif
-
- if (!pure && BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
- return RBASIC(obj)->klass = rb_cClass;
+ if (TYPE(obj) == T_CLASS && RCLASS_SINGLETON(obj)) {
+ RBASIC(obj)->klass = rb_cClass;
+ return rb_cClass;
}
else {
- VALUE metasuper;
VALUE klass;
-#if WITH_OBJC
- if (!pure && BUILTIN_TYPE(obj) == T_CLASS) {
- NEWOBJ(obj2, struct RClass);
- OBJSETUP(obj2, rb_cClass, T_CLASS);
- klass = (VALUE)obj2;
- rb_objc_retain((const void *)klass);
- class_init(klass);
- OBJ_INFECT(klass, super);
- RCLASS_SUPER(klass) = super;
- RCLASS_M_TBL(klass) = st_init_numtable();
- RCLASS(klass)->ocklass = RBASIC(super)->isa;
- RBASIC(obj)->klass = klass;
- }
- else {
- klass = rb_class_boot(super);
- *(Class *)obj = RCLASS_OCID(klass);
- if (!pure)
- RBASIC(obj)->klass = klass;
- }
-#else
klass = rb_class_boot(super);
RBASIC(obj)->klass = klass;
-#endif
- FL_SET(klass, FL_SINGLETON);
+ if (super == rb_cNSObject) {
+ RCLASS_VERSION(klass) ^= RCLASS_IS_OBJECT_SUBCLASS;
+ }
+ RCLASS_SET_VERSION_FLAG(klass, RCLASS_IS_SINGLETON);
rb_singleton_class_attached(klass, obj);
- metasuper = RBASIC(rb_class_real(super))->klass;
- /* metaclass of a superclass may be NULL at boot time */
- if (metasuper) {
- RBASIC(klass)->klass = metasuper;
- }
return klass;
}
}
@@ -497,12 +330,7 @@
VALUE klass;
if (!super) super = rb_cObject;
-#if WITH_OBJC
klass = rb_objc_create_class(rb_id2name(id), super);
-#else
- klass = rb_class_new(super);
-#endif
- rb_make_metaclass(klass, RBASIC(super)->klass);
return klass;
}
@@ -575,11 +403,7 @@
VALUE
rb_module_new(void)
{
- VALUE mdl = class_alloc(T_MODULE, rb_cModule);
-
- RCLASS_M_TBL(mdl) = st_init_numtable();
-
- return (VALUE)mdl;
+ return rb_define_module_id(0);
}
VALUE
@@ -587,15 +411,15 @@
{
VALUE mdl;
-#if WITH_OBJC
- mdl = rb_objc_create_class(rb_id2name(id), 0);
- RBASIC(mdl)->flags = T_MODULE;
- RBASIC(mdl)->klass = rb_cModule; /* necessary? */
-#else
- mdl = rb_module_new();
- rb_name_class(mdl, id);
-#endif
+ mdl = rb_objc_alloc_class(id == 0 ? NULL : rb_id2name(id), rb_cObject, T_MODULE, rb_cModule);
+ objc_registerClassPair((Class)mdl);
+ if (rb_mKernel != 0) {
+ /* because Module#initialize can accept a block */
+ extern VALUE rb_mod_initialize(VALUE);
+ rb_define_method(*(VALUE *)mdl, "initialize", rb_mod_initialize, 0);
+ }
+
return mdl;
}
@@ -640,83 +464,57 @@
return module;
}
-static VALUE
-include_class_new(VALUE module, VALUE super)
-{
- VALUE klass = class_alloc(T_ICLASS, rb_cClass);
-
- if (BUILTIN_TYPE(module) == T_ICLASS) {
- module = RBASIC(module)->klass;
- }
- if (!RCLASS_IV_TBL(module)) {
- GC_WB(&RCLASS_IV_TBL(module), st_init_numtable());
- }
- RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
- RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
- RCLASS_SUPER(klass) = super;
- if (TYPE(module) == T_ICLASS) {
- RBASIC(klass)->klass = RBASIC(module)->klass;
- }
- else {
- RBASIC(klass)->klass = module;
- }
-#if WITH_OBJC
- class_setSuperclass(RCLASS(klass)->ocklass,
- RCLASS(RBASIC(klass)->klass)->ocklass);
-#endif
- OBJ_INFECT(klass, module);
- OBJ_INFECT(klass, super);
-
- return (VALUE)klass;
-}
-
void
rb_include_module(VALUE klass, VALUE module)
{
- VALUE p, c;
- int changed = 0;
+ Method *methods;
+ unsigned int i, methods_count;
+ VALUE ary;
rb_frozen_class_p(klass);
- if (!OBJ_TAINTED(klass)) {
+
+ if (!OBJ_TAINTED(klass))
rb_secure(4);
+
+ Check_Type(module, T_MODULE);
+
+ ary = rb_attr_get(klass, idIncludedModules);
+ if (ary == Qnil) {
+ ary = rb_ary_new();
+ rb_ivar_set(klass, idIncludedModules, ary);
}
-
- if (TYPE(module) != T_MODULE) {
- Check_Type(module, T_MODULE);
+ if (rb_ary_includes(ary, module))
+ return;
+ rb_ary_insert(ary, 0, module);
+
+ ary = rb_attr_get(module, idIncludedInClasses);
+ if (ary == Qnil) {
+ ary = rb_ary_new();
+ rb_ivar_set(module, idIncludedInClasses, ary);
}
+ rb_ary_push(ary, klass);
- OBJ_INFECT(klass, module);
- c = klass;
- while (module) {
- int superclass_seen = Qfalse;
+ DLOG("INCM", "%s <- %s", class_getName((Class)klass), class_getName((Class)module));
- if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
- rb_raise(rb_eArgError, "cyclic include detected");
- /* ignore if the module included already in superclasses */
- for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
- switch (BUILTIN_TYPE(p)) {
- case T_ICLASS:
- if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
- if (!superclass_seen) {
- c = p; /* move insertion point */
- }
- goto skip;
- }
- break;
- case T_CLASS:
- superclass_seen = Qtrue;
- break;
+ methods = class_copyMethodList((Class)module, &methods_count);
+ if (methods != NULL) {
+ for (i = 0; i < methods_count; i++) {
+ Method method = methods[i], method2;
+ DLOG("DEFI", "-[%s %s]", class_getName((Class)klass), (char *)method_getName(method));
+
+ method2 = class_getInstanceMethod((Class)klass, method_getName(method));
+ if (method2 != NULL && method2 != class_getInstanceMethod((Class)RCLASS_SUPER(klass), method_getName(method))) {
+ method_setImplementation(method2, method_getImplementation(method));
}
+ else {
+ assert(class_addMethod((Class)klass,
+ method_getName(method),
+ method_getImplementation(method),
+ method_getTypeEncoding(method)));
+ }
}
-#if WITH_OBJC
- rb_objc_sync_ruby_methods(module, klass);
-#endif
- c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
- changed = 1;
- skip:
- module = RCLASS_SUPER(module);
+ free(methods);
}
- if (changed) rb_clear_cache();
}
/*
@@ -736,16 +534,29 @@
* Outer.included_modules #=> [Mixin]
*/
+static void
+rb_mod_included_modules_nosuper(VALUE mod, VALUE ary)
+{
+ VALUE inc_mods = rb_ivar_get(mod, idIncludedModules);
+ if (inc_mods != Qnil) {
+ int i, count = RARRAY_LEN(inc_mods);
+ for (i = 0; i < count; i++) {
+ VALUE imod = RARRAY_AT(inc_mods, i);
+ rb_ary_push(ary, imod);
+ rb_ary_concat(ary, rb_mod_included_modules(imod));
+ }
+ }
+}
+
VALUE
rb_mod_included_modules(VALUE mod)
{
- VALUE ary = rb_ary_new();
- VALUE p;
+ VALUE p, ary = rb_ary_new();
- for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
+ for (p = mod; p; p = RCLASS_SUPER(p)) {
+ rb_mod_included_modules_nosuper(p, ary);
+ if (RCLASS_MODULE(p))
+ break;
}
return ary;
}
@@ -772,15 +583,7 @@
VALUE
rb_mod_include_p(VALUE mod, VALUE mod2)
{
- VALUE p;
-
- Check_Type(mod2, T_MODULE);
- for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- if (RBASIC(p)->klass == mod2) return Qtrue;
- }
- }
- return Qfalse;
+ return rb_ary_includes(rb_mod_included_modules(mod), mod2);
}
/*
@@ -799,20 +602,18 @@
* Math.ancestors #=> [Math]
*/
+static void rb_mod_included_modules_nosuper(VALUE, VALUE);
+
VALUE
rb_mod_ancestors(VALUE mod)
{
VALUE p, ary = rb_ary_new();
-
+
for (p = mod; p; p = RCLASS_SUPER(p)) {
- if (FL_TEST(p, FL_SINGLETON))
- continue;
- if (BUILTIN_TYPE(p) == T_ICLASS) {
- rb_ary_push(ary, RBASIC(p)->klass);
- }
- else {
- rb_ary_push(ary, p);
- }
+ rb_ary_push(ary, p);
+ rb_mod_included_modules_nosuper(p, ary);
+ if (RCLASS_MODULE(p))
+ break;
}
return ary;
}
@@ -862,59 +663,117 @@
return ins_methods_push(name, type, ary, NOEX_PUBLIC);
}
-static int
-method_entry(ID key, NODE *body, st_table *list)
+static void
+rb_objc_push_methods(VALUE ary, VALUE mod, VALUE objc_methods)
{
- long type;
+ Method *methods;
+ unsigned int i, count;
- if (key == ID_ALLOCATOR) {
- return ST_CONTINUE;
+ methods = class_copyMethodList((Class)mod, &count);
+ if (methods != NULL) {
+ for (i = 0; i < count; i++) {
+ Method method;
+ SEL sel;
+ char *sel_name, *p;
+ VALUE sym;
+ ID mid;
+ char buf[100];
+ BOOL is_ruby_method;
+ size_t len;
+
+ method = methods[i];
+
+ sel = method_getName(method);
+ if (sel == sel_ignored)
+ continue;
+
+ sel_name = (char *)sel;
+ is_ruby_method = rb_objc_method_node3(method_getImplementation(method)) != NULL;
+
+ if (!is_ruby_method && objc_methods == Qfalse)
+ continue;
+
+ len = strlen(sel_name);
+
+ if (is_ruby_method && len > 8 && sel_name[0] == '_' && sel_name[1] == '_' && sel_name[2] == 'r' && sel_name[3] == 'b' && sel_name[4] == '_' && sel_name[len - 1] == '_' && sel_name[len - 2] == '_') {
+ /* retransform ignored selectors, __rb_%s__ -> %s */
+ assert(sizeof buf > len - 7);
+ strncpy(buf, &sel_name[5], len - 7);
+ buf[len - 7] = '\0';
+ sel_name = buf;
+ }
+ else {
+ if (is_ruby_method && len >= 3 && sel_name[len - 1] == ':' && isalpha(sel_name[len - 3])) {
+ assert(len + 3 < sizeof(buf));
+ if (sel_name[len - 2] == '=') {
+ /* skip foo=: (ruby) -> setFoo: (objc) shortcuts */
+ snprintf(buf, sizeof buf, "set%s", sel_name);
+ buf[4] = toupper(buf[4]);
+ buf[len + 1] = ':';
+ buf[len + 2] = '\0';
+
+ method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
+ if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+ continue;
+ }
+ else if (sel_name[len - 2] == '?') {
+ /* skip foo?: (ruby) -> isFoo: (objc) shortcuts */
+ snprintf(buf, sizeof buf, "is%s", sel_name);
+ buf[3] = toupper(buf[3]);
+ buf[len] = ':';
+ buf[len + 1] = '\0';
+
+ method = class_getInstanceMethod((Class)mod, sel_registerName(buf));
+ if (method != NULL && rb_objc_method_node3(method_getImplementation(method)) == NULL)
+ continue;
+ }
+ }
+ p = strchr(sel_name, ':');
+ if (p != NULL && strchr(p + 1, ':') == NULL) {
+ /* remove trailing ':' for methods with arity 1 */
+ assert(len < sizeof(buf));
+ strncpy(buf, sel_name, len);
+ buf[len - 1] = '\0';
+ sel_name = buf;
+ }
+ }
+ mid = rb_intern(sel_name);
+ sym = ID2SYM(mid);
+
+ if (rb_ary_includes(ary, sym) == Qfalse)
+ rb_ary_push(ary, sym);
+ }
+ free(methods);
}
-
- if (!st_lookup(list, key, 0)) {
- if (body ==0 || !body->nd_body->nd_body) {
- type = -1; /* none */
- }
- else {
- type = VISI(body->nd_body->nd_noex);
- }
- st_add_direct(list, key, type);
- }
- return ST_CONTINUE;
}
static VALUE
class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, long, VALUE))
{
VALUE ary;
- int recur;
- st_table *list;
- VALUE mod_orig = mod;
+ VALUE recur, objc_methods;
+ ary = rb_ary_new();
+
if (argc == 0) {
recur = Qtrue;
+ objc_methods = Qfalse;
}
else {
- VALUE r;
- rb_scan_args(argc, argv, "01", &r);
- recur = RTEST(r);
+ rb_scan_args(argc, argv, "02", &recur, &objc_methods);
+ if (NIL_P(recur))
+ recur = Qtrue;
+ if (NIL_P(objc_methods))
+ objc_methods = Qfalse;
}
- list = st_init_numtable();
- for (; mod; mod = RCLASS_SUPER(mod)) {
- st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
- if (BUILTIN_TYPE(mod) == T_ICLASS) continue;
- if (FL_TEST(mod, FL_SINGLETON)) continue;
- if (!recur) break;
- }
- ary = rb_ary_new();
- st_foreach(list, func, ary);
- st_free_table(list);
+ while (mod != 0) {
+ rb_objc_push_methods(ary, mod, objc_methods);
+ if (recur == Qfalse)
+ break;
+ mod = (VALUE)class_getSuperclass((Class)mod);
+ }
-#if WITH_OBJC
- rb_objc_methods(ary, RCLASS(mod_orig)->ocklass);
-#endif
-
return ary;
}
@@ -1039,30 +898,25 @@
VALUE
rb_obj_singleton_methods(int argc, VALUE *argv, VALUE obj)
{
- VALUE recur, ary, klass;
- st_table *list;
+ VALUE recur, objc_methods, klass, ary;
if (argc == 0) {
recur = Qtrue;
+ objc_methods = Qfalse;
}
else {
- rb_scan_args(argc, argv, "01", &recur);
+ rb_scan_args(argc, argv, "02", &recur, &objc_methods);
}
+
klass = CLASS_OF(obj);
- list = st_init_numtable();
- if (klass && FL_TEST(klass, FL_SINGLETON)) {
- st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
+ ary = rb_ary_new();
+
+ do {
+ if (RCLASS_SINGLETON(klass))
+ rb_objc_push_methods(ary, klass, objc_methods);
klass = RCLASS_SUPER(klass);
}
- if (RTEST(recur)) {
- while (klass && (FL_TEST(klass, FL_SINGLETON) || TYPE(klass) == T_ICLASS)) {
- st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
- klass = RCLASS_SUPER(klass);
- }
- }
- ary = rb_ary_new();
- st_foreach(list, ins_methods_i, ary);
- st_free_table(list);
+ while (recur == Qtrue && klass != 0);
return ary;
}
@@ -1119,36 +973,30 @@
}
DEFER_INTS;
-#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
- Class ocklass;
-
- ocklass = *(Class *)obj;
- klass = rb_objc_import_class(ocklass);
- if (class_isMetaClass(ocklass))
- return klass;
-
- if (!FL_TEST(klass, FL_SINGLETON))
- klass = rb_make_metaclass(obj, klass);
- return klass;
- }
-#endif
- if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
+ if (RCLASS_SINGLETON(RBASIC(obj)->klass) &&
rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
klass = RBASIC(obj)->klass;
}
else {
- klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+ switch (TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ klass = *(VALUE *)obj;
+ break;
+ default:
+ klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
+ break;
+ }
}
-#if !WITH_OBJC
+#if 0
if (OBJ_TAINTED(obj)) {
OBJ_TAINT(klass);
}
else {
- FL_UNSET(klass, FL_TAINT);
+ OBJ_UNTAINT(klass);
}
- if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
#endif
+ if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
ALLOW_INTS;
return klass;
@@ -1227,7 +1075,7 @@
p++;
}
- if(*p == '*') {
+ if (*p == '*') {
rest_arg:
var = va_arg(vargs, VALUE*);
if (argc > i) {
Modified: MacRuby/trunk/compile.c
===================================================================
--- MacRuby/trunk/compile.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/compile.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -338,9 +338,9 @@
alloc_size *= 2;
goto retry;
}
- storage->next = (void *)ALLOC_N(char, alloc_size +
+ GC_WB(&storage->next, (void *)ALLOC_N(char, alloc_size +
sizeof(struct
- iseq_compile_data_storage));
+ iseq_compile_data_storage)));
storage = iseq->compile_data->storage_current = storage->next;
storage->next = 0;
storage->pos = 0;
@@ -674,7 +674,7 @@
operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * argc);
for (i = 0; i < argc; i++) {
VALUE v = va_arg(argv, VALUE);
- operands[i] = v;
+ GC_WB(&operands[i], v);
}
va_end(argv);
}
@@ -687,12 +687,43 @@
{
INSN *iobj = 0;
VALUE *operands =
- (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5);
+ (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 7);
+ struct rb_method_cache *mcache;
+
operands[0] = id;
operands[1] = argc;
operands[2] = block;
operands[3] = flag;
- operands[4] = 0;
+
+ mcache = (struct rb_method_cache *)xmalloc(sizeof(struct rb_method_cache));
+ mcache->flags = RB_MCACHE_RCALL_FLAG;
+ mcache->as.rcall.klass = 0;
+ mcache->as.rcall.node = NULL;
+ if (FIX2INT(argc) > 0) {
+ char *id_str;
+ size_t id_str_len;
+ char buf[100];
+
+ id_str = (char *)rb_sym2name(id);
+ id_str_len = strlen(id_str);
+
+ if (id_str[id_str_len - 1] != ':') {
+ snprintf(buf, sizeof buf, "%s:", id_str);
+ id_str = buf;
+ }
+
+ mcache->as.rcall.sel = sel_registerName(id_str);
+ }
+ else {
+ mcache->as.rcall.sel = sel_registerName(rb_sym2name(id));
+ if (mcache->as.rcall.sel == sel_ignored
+ || mcache->as.rcall.sel == sel_zone) {
+ char buf[100];
+ snprintf(buf, sizeof buf, "__rb_%s__", rb_sym2name(id));
+ mcache->as.rcall.sel = sel_registerName(buf);
+ }
+ }
+ GC_WB(&operands[4], (VALUE)mcache);
iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands);
return iobj;
}
@@ -898,7 +929,7 @@
i += 1;
iseq->arg_opts = i;
- iseq->arg_opt_table = ALLOC_N(VALUE, i);
+ GC_WB(&iseq->arg_opt_table, ALLOC_N(VALUE, i));
#if WITH_OBJC
CFArrayGetValues((CFArrayRef)labels, CFRangeMake(0, i),
(const void **)iseq->arg_opt_table);
@@ -906,6 +937,9 @@
MEMCPY(iseq->arg_opt_table, RARRAY_PTR(labels), VALUE, i);
#endif
for (j = 0; j < i; j++) {
+#if WITH_OBJC
+ iseq->arg_opt_table[j] = OC2RB(iseq->arg_opt_table[j]);
+#endif
iseq->arg_opt_table[j] &= ~1;
}
}
@@ -1609,6 +1643,11 @@
insn_set_specialized_instruction(iobj, BIN(opt_aref));
}
}
+ else if (argc == 2) {
+ if (mid == idASET) {
+ insn_set_specialized_instruction(iobj, BIN(opt_aset));
+ }
+ }
}
if (argc > 0) {
Modified: MacRuby/trunk/debug.h
===================================================================
--- MacRuby/trunk/debug.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/debug.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -29,4 +29,17 @@
void ruby_debug_breakpoint(void);
void ruby_debug_gc_check_func(void);
+#if ENABLE_DEBUG_LOGGING
+# include "vm_core.h"
+extern bool ruby_dlog_enabled;
+# define DLOG(mod, fmt, args...) \
+ if (UNLIKELY(ruby_dlog_enabled)) { \
+ printf("%10s ", mod); \
+ printf(fmt, ##args); \
+ printf("\n"); \
+ }
+#else
+# define DLOG(mod, fmt, args...)
+#endif
+
#endif /* RUBY_DEBUG_H */
Modified: MacRuby/trunk/encoding.c
===================================================================
--- MacRuby/trunk/encoding.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/encoding.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,14 +1,14 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's encoding.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- encoding.c -
-
- $Author: nobu $
- created at: Thu May 24 17:23:27 JST 2007
-
- Copyright (C) 2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/encoding.h"
#include "regenc.h"
@@ -20,8 +20,6 @@
static ID id_encoding, id_base_encoding;
VALUE rb_cEncoding;
-#if WITH_OBJC
-
static CFMutableDictionaryRef __encodings = NULL;
static VALUE
@@ -115,307 +113,6 @@
return rb_enc_to_enc_ptr(v);
}
-#else
-
-struct rb_encoding_entry {
- const char *name;
- rb_encoding *enc;
-};
-
-static struct {
- struct rb_encoding_entry *list;
- int count;
- int size;
- st_table *names;
-} enc_table;
-
-void rb_enc_init(void);
-
-#define ENCODING_COUNT ENCINDEX_BUILTIN_MAX
-
-#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
-
-#define ENC_UNINITIALIZED (&rb_cEncoding)
-#define enc_initialized_p(enc) ((enc)->auxiliary_data != &rb_cEncoding)
-#define ENC_FROM_ENCODING(enc) ((VALUE)(enc)->auxiliary_data)
-
-#define ENC_DUMMY_FLAG FL_USER2
-#define ENC_DUMMY_P(enc) (RBASIC(enc)->flags & ENC_DUMMY_FLAG)
-#define ENC_SET_DUMMY(enc) (RBASIC(enc)->flags |= ENC_DUMMY_FLAG)
-
-static int load_encoding(const char *name);
-static VALUE enc_base_encoding(VALUE self);
-
-static void
-enc_mark(void *ptr)
-{
-}
-
-static VALUE
-enc_new(rb_encoding *encoding)
-{
- VALUE enc = Data_Wrap_Struct(rb_cEncoding, enc_mark, 0, encoding);
- encoding->auxiliary_data = (void *)enc;
- return enc;
-}
-
-VALUE
-rb_enc_from_encoding(rb_encoding *encoding)
-{
- if (!encoding) return Qnil;
- if (enc_initialized_p(encoding))
- return ENC_FROM_ENCODING(encoding);
- return enc_new(encoding);
-}
-
-static int
-enc_check_encoding(VALUE obj)
-{
- int index;
- rb_encoding *enc;
-
- if (SPECIAL_CONST_P(obj) || BUILTIN_TYPE(obj) != T_DATA ||
- RDATA(obj)->dmark != enc_mark) {
- return -1;
- }
- enc = (rb_encoding*)RDATA(obj)->data;
- index = rb_enc_to_index(enc);
- if (rb_enc_from_index(index) != enc)
- return -1;
- if (enc_autoload_p(enc)) {
- index = rb_enc_find_index(enc->name);
- }
- return index;
-}
-
-int
-rb_to_encoding_index(VALUE enc)
-{
- int idx;
-
- idx = enc_check_encoding(enc);
- if (idx >= 0) {
- return idx;
- }
- else if (NIL_P(enc = rb_check_string_type(enc))) {
- return -1;
- }
- else {
- return rb_enc_find_index(StringValueCStr(enc));
- }
-}
-
-rb_encoding *
-rb_to_encoding(VALUE enc)
-{
- int idx;
-
- idx = enc_check_encoding(enc);
- if (idx >= 0) return RDATA(enc)->data;
- if ((idx = rb_enc_find_index(StringValueCStr(enc))) < 0) {
- rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
- }
- return rb_enc_from_index(idx);
-}
-
-void
-rb_gc_mark_encodings(void)
-{
- int i;
- for (i = 0; i < enc_table.count; ++i) {
- rb_encoding *enc = enc_table.list[i].enc;
- if (enc && enc_initialized_p(enc)) {
- rb_gc_mark(ENC_FROM_ENCODING(enc));
- }
- }
-}
-
-static int
-enc_table_expand(int newsize)
-{
- struct rb_encoding_entry *ent;
- int count = newsize;
-
- if (enc_table.size >= newsize) return newsize;
- newsize = (newsize + 7) / 8 * 8;
- ent = realloc(enc_table.list, sizeof(*enc_table.list) * newsize);
- if (!ent) return -1;
- memset(ent + enc_table.size, 0, sizeof(*ent)*(newsize - enc_table.size));
- enc_table.list = ent;
- enc_table.size = newsize;
- return count;
-}
-
-static int
-enc_register_at(int index, const char *name, rb_encoding *encoding)
-{
- struct rb_encoding_entry *ent = &enc_table.list[index];
- void *obj = ENC_UNINITIALIZED;
-
- if (!ent->name) {
- ent->name = name = strdup(name);
- }
- else if (STRCASECMP(name, ent->name)) {
- return -1;
- }
- if (!ent->enc) {
- ent->enc = malloc(sizeof(rb_encoding));
- }
- else {
- obj = ent->enc->auxiliary_data;
- }
- if (encoding) {
- *ent->enc = *encoding;
- }
- else {
- memset(ent->enc, 0, sizeof(*ent->enc));
- }
- encoding = ent->enc;
- encoding->name = name;
- encoding->ruby_encoding_index = index;
- st_insert(enc_table.names, (st_data_t)name, (st_data_t)index);
- if (obj != ENC_UNINITIALIZED) {
- encoding->auxiliary_data = obj;
- }
- else if (rb_cEncoding) {
- /* initialize encoding data */
- enc_new(encoding);
- }
- else {
- encoding->auxiliary_data = ENC_UNINITIALIZED;
- }
- return index;
-}
-
-static int
-enc_register(const char *name, rb_encoding *encoding)
-{
- int index = enc_table.count;
-
- if ((index = enc_table_expand(index + 1)) < 0) return -1;
- enc_table.count = index;
- return enc_register_at(index - 1, name, encoding);
-}
-
-static void set_encoding_const(const char *, rb_encoding *);
-int rb_enc_registered(const char *name);
-
-int
-rb_enc_register(const char *name, rb_encoding *encoding)
-{
- int index = rb_enc_registered(name);
-
- if (index >= 0) {
- rb_encoding *oldenc = rb_enc_from_index(index);
- if (STRCASECMP(name, rb_enc_name(oldenc))) {
- index = enc_register(name, encoding);
- }
- else if (!enc_autoload_p(oldenc) ||
- (enc_initialized_p(oldenc) &&
- !ENC_DUMMY_P(ENC_FROM_ENCODING(oldenc)))) {
- enc_register_at(index, name, encoding);
- }
- else {
- rb_raise(rb_eArgError, "encoding %s is already registered", name);
- }
- }
- else {
- index = enc_register(name, encoding);
- set_encoding_const(name, rb_enc_from_index(index));
- }
- return index;
-}
-
-void
-rb_encdb_declare(const char *name)
-{
- int idx = rb_enc_registered(name);
- if (idx < 0) {
- idx = enc_register(name, 0);
- }
- set_encoding_const(name, rb_enc_from_index(idx));
-}
-
-static void
-enc_check_duplication(const char *name)
-{
- if (rb_enc_registered(name) >= 0) {
- rb_raise(rb_eArgError, "encoding %s is already registered", name);
- }
-}
-
-static VALUE
-set_base_encoding(int index, rb_encoding *base)
-{
- VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
- rb_ivar_set(enc, id_base_encoding, rb_enc_from_encoding(base));
- if (rb_enc_dummy_p(base)) ENC_SET_DUMMY(enc);
- return enc;
-}
-
-int
-rb_enc_replicate(const char *name, rb_encoding *encoding)
-{
- int idx;
-
- enc_check_duplication(name);
- idx = enc_register(name, encoding);
- set_base_encoding(idx, encoding);
- set_encoding_const(name, rb_enc_from_index(idx));
- return idx;
-}
-
-static int
-enc_replicate(int idx, const char *name, rb_encoding *origenc)
-{
- if (idx < 0) {
- idx = enc_register(name, origenc);
- }
- else {
- idx = enc_register_at(idx, name, origenc);
- }
- if (idx >= 0) {
- set_base_encoding(idx, origenc);
- set_encoding_const(name, rb_enc_from_index(idx));
- }
- return idx;
-}
-
-int
-rb_encdb_replicate(const char *name, const char *orig)
-{
- int origidx = rb_enc_registered(orig);
- int idx = rb_enc_registered(name);
-
- if (origidx < 0) {
- origidx = enc_register(orig, 0);
- }
- return enc_replicate(idx, name, rb_enc_from_index(origidx));
-}
-
-int
-rb_define_dummy_encoding(const char *name)
-{
- int index = rb_enc_replicate(name, rb_ascii8bit_encoding());
- VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
- ENC_SET_DUMMY(enc);
- return index;
-}
-
-int
-rb_encdb_dummy(const char *name)
-{
- int index = enc_replicate(rb_enc_registered(name), name,
- rb_ascii8bit_encoding());
- VALUE enc = rb_enc_from_encoding(enc_table.list[index].enc);
-
- ENC_SET_DUMMY(enc);
- return index;
-}
-#endif // WITH_OBJC
-
/*
* call-seq:
* enc.dummy? => true or false
@@ -435,208 +132,6 @@
return rb_enc_dummy_p(rb_to_encoding(enc)) ? Qtrue : Qfalse;
}
-#if !WITH_OBJC
-static int
-enc_alias(const char *alias, int idx)
-{
- alias = strdup(alias);
- st_insert(enc_table.names, (st_data_t)alias, (st_data_t)idx);
- set_encoding_const(alias, rb_enc_from_index(idx));
- return idx;
-}
-
-int
-rb_enc_alias(const char *alias, const char *orig)
-{
- int idx;
-
- enc_check_duplication(alias);
- if (!enc_table.list) {
- rb_enc_init();
- }
- if ((idx = rb_enc_find_index(orig)) < 0) {
- return -1;
- }
- return enc_alias(alias, idx);
-}
-
-int
-rb_encdb_alias(const char *alias, const char *orig)
-{
- int idx = rb_enc_registered(orig);
-
- if (idx < 0) {
- idx = enc_register(orig, 0);
- }
- return enc_alias(alias, idx);
-}
-
-enum {
- ENCINDEX_ASCII,
- ENCINDEX_UTF_8,
- ENCINDEX_US_ASCII,
- ENCINDEX_BUILTIN_MAX
-};
-
-extern rb_encoding OnigEncodingUTF_8;
-extern rb_encoding OnigEncodingUS_ASCII;
-
-void
-rb_enc_init(void)
-{
- enc_table_expand(ENCODING_COUNT + 1);
- if (!enc_table.names) {
- enc_table.names = st_init_strcasetable();
- GC_ROOT(&enc_table.names);
- }
-#define ENC_REGISTER(enc) enc_register_at(ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc)
- ENC_REGISTER(ASCII);
- ENC_REGISTER(UTF_8);
- ENC_REGISTER(US_ASCII);
-#undef ENC_REGISTER
- enc_table.count = ENCINDEX_BUILTIN_MAX;
-}
-
-rb_encoding *
-rb_enc_from_index(int index)
-{
- if (!enc_table.list) {
- rb_enc_init();
- }
- if (index < 0 || enc_table.count <= index) {
- return 0;
- }
- return enc_table.list[index].enc;
-}
-
-int
-rb_enc_registered(const char *name)
-{
- st_data_t idx = 0;
-
- if (!name) return -1;
- if (!enc_table.list) return -1;
- if (st_lookup(enc_table.names, (st_data_t)name, &idx)) {
- return (int)idx;
- }
- return -1;
-}
-
-static VALUE
-require_enc(VALUE enclib)
-{
- return rb_require_safe(enclib, rb_safe_level());
-}
-
-static int
-load_encoding(const char *name)
-{
- VALUE enclib = rb_sprintf("enc/%s", name);
- VALUE verbose = ruby_verbose;
- VALUE debug = ruby_debug;
- VALUE loaded;
- char *s = RSTRING_BYTEPTR(enclib) + 4, *e = RSTRING_END(enclib);
- int idx;
-
- while (s < e) {
- if (!ISALNUM(*s)) *s = '_';
- else if (ISUPPER(*s)) *s = TOLOWER(*s);
- ++s;
- }
- OBJ_FREEZE(enclib);
- ruby_verbose = Qfalse;
- ruby_debug = Qfalse;
- loaded = rb_protect(require_enc, enclib, 0);
- ruby_verbose = verbose;
- ruby_debug = debug;
- rb_set_errinfo(Qnil);
- if (NIL_P(loaded)) return -1;
- if ((idx = rb_enc_registered(name)) < 0) return -1;
- if (enc_autoload_p(enc_table.list[idx].enc)) return -1;
- return idx;
-}
-
-int
-rb_enc_find_index(const char *name)
-{
- int i = rb_enc_registered(name), b;
- rb_encoding *enc;
- VALUE base;
-
- if (i < 0) {
- i = load_encoding(name);
- }
- else if (enc_autoload_p(enc = rb_enc_from_index(i))) {
- if (enc_initialized_p(enc) &&
- (base = enc_base_encoding(ENC_FROM_ENCODING(enc)), !NIL_P(base))) {
- if ((b = enc_check_encoding(base)) < 0) {
- goto failed;
- }
- enc_register_at(i, rb_enc_name(enc), rb_enc_from_index(b));
- }
- else {
- i = load_encoding(rb_enc_name(enc));
- if (i < 0) {
- failed:
- rb_warn("failed to load encoding (%s); use ASCII-8BIT instead",
- name);
- return 0;
- }
- }
- }
- return i;
-}
-
-rb_encoding *
-rb_enc_find(const char *name)
-{
- int idx = rb_enc_find_index(name);
- if (idx < 0) idx = 0;
- return rb_enc_from_index(idx);
-}
-
-static inline int
-enc_capable(VALUE obj)
-{
- if (SPECIAL_CONST_P(obj)) return Qfalse;
- switch (/*BUILTIN_*/TYPE(obj)) {
- case T_STRING:
- case T_REGEXP:
- case T_FILE:
- return Qtrue;
- case T_DATA:
- if (RDATA(obj)->dmark == enc_mark) return Qtrue;
- default:
- return Qfalse;
- }
-}
-
-static void
-enc_check_capable(VALUE x)
-{
- if (!enc_capable(x)) {
- const char *etype;
-
- if (NIL_P(x)) {
- etype = "nil";
- }
- else if (FIXNUM_P(x)) {
- etype = "Fixnum";
- }
- else if (SYMBOL_P(x)) {
- etype = "Symbol";
- }
- else if (rb_special_const_p(x)) {
- etype = RSTRING_BYTEPTR(rb_obj_as_string(x));
- }
- else {
- etype = rb_obj_classname(x);
- }
- rb_raise(rb_eTypeError, "wrong argument type %s (not encode capable)", etype);
- }
-}
-#endif
-
ID
rb_id_encoding(void)
{
@@ -646,150 +141,16 @@
return id_encoding;
}
-#if !WITH_OBJC
-int
-rb_enc_internal_get_index(VALUE obj)
-{
- int i;
-
- i = ENCODING_GET_INLINED(obj);
- if (i == ENCODING_INLINE_MAX) {
- VALUE iv;
-
- iv = rb_ivar_get(obj, rb_id_encoding());
- i = NUM2INT(iv);
- }
- return i;
-}
-
-void
-rb_enc_internal_set_index(VALUE obj, int idx)
-{
- if (idx < ENCODING_INLINE_MAX) {
- ENCODING_SET_INLINED(obj, idx);
- return;
- }
- ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX);
- rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx));
- return;
-}
-
-void
-rb_enc_associate_index(VALUE obj, int idx)
-{
- enc_check_capable(obj);
- if (rb_enc_internal_get_index(obj) == idx)
- return;
- if (!ENC_CODERANGE_ASCIIONLY(obj) ||
- !rb_enc_asciicompat(rb_enc_from_index(idx))) {
- ENC_CODERANGE_CLEAR(obj);
- }
- rb_enc_internal_set_index(obj, idx);
-}
-
-void
-rb_enc_associate(VALUE obj, rb_encoding *enc)
-{
- rb_enc_associate_index(obj, rb_enc_to_index(enc));
-}
-
-int
-rb_enc_get_index(VALUE obj)
-{
- if (!enc_capable(obj)) return -1;
- return rb_enc_internal_get_index(obj);
-}
-
rb_encoding*
-rb_enc_get(VALUE obj)
-{
- return rb_enc_from_index(rb_enc_get_index(obj));
-}
-
-rb_encoding*
-rb_enc_check(VALUE str1, VALUE str2)
-{
- rb_encoding *enc = rb_enc_compatible(str1, str2);
- if (!enc)
- rb_raise(rb_eArgError, "character encodings differ: %s and %s",
- rb_enc_name(rb_enc_get(str1)),
- rb_enc_name(rb_enc_get(str2)));
- return enc;
-}
-#endif
-
-rb_encoding*
rb_enc_compatible(VALUE str1, VALUE str2)
{
-#if WITH_OBJC
/* TODO */
rb_encoding *enc = rb_enc_get(str1);
if (enc == rb_enc_get(str2))
return enc;
return NULL;
-#else
- int idx1, idx2;
- rb_encoding *enc1, *enc2;
-
- idx1 = rb_enc_get_index(str1);
- idx2 = rb_enc_get_index(str2);
-
- if (idx1 < 0 || idx2 < 0)
- return 0;
-
- if (idx1 == idx2) {
- return rb_enc_from_index(idx1);
- }
- enc1 = rb_enc_from_index(idx1);
- enc2 = rb_enc_from_index(idx2);
-
- if (TYPE(str2) == T_STRING && RSTRING_BYTELEN(str2) == 0)
- return enc1;
- if (TYPE(str1) == T_STRING && RSTRING_BYTELEN(str1) == 0)
- return enc2;
- if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
- return 0;
- }
-
- if (BUILTIN_TYPE(str1) != T_STRING) {
- VALUE tmp = str1;
- int idx0 = idx1;
- str1 = str2;
- str2 = tmp;
- idx1 = idx2;
- idx2 = idx0;
- }
- if (BUILTIN_TYPE(str1) == T_STRING) {
- int cr1, cr2;
-
- cr1 = rb_enc_str_coderange(str1);
- if (BUILTIN_TYPE(str2) == T_STRING) {
- cr2 = rb_enc_str_coderange(str2);
- if (cr1 != cr2) {
- /* may need to handle ENC_CODERANGE_BROKEN */
- if (cr1 == ENC_CODERANGE_7BIT) return enc2;
- if (cr2 == ENC_CODERANGE_7BIT) return enc1;
- }
- if (cr2 == ENC_CODERANGE_7BIT) {
- if (idx1 == 0) return enc2;
- return enc1;
- }
- }
- if (cr1 == ENC_CODERANGE_7BIT)
- return enc2;
- }
- return 0;
-#endif
}
-#if !WITH_OBJC
-void
-rb_enc_copy(VALUE obj1, VALUE obj2)
-{
- rb_enc_associate_index(obj1, rb_enc_get_index(obj2));
-}
-#endif
-
/*
* call-seq:
* obj.encoding => encoding
@@ -807,90 +168,6 @@
return rb_enc_from_encoding(enc);
}
-#if !WITH_OBJC
-int
-rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
-{
- int n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
- if (MBCLEN_CHARFOUND_P(n) && MBCLEN_CHARFOUND_LEN(n) <= e-p)
- return MBCLEN_CHARFOUND_LEN(n);
- else {
- int min = rb_enc_mbminlen(enc);
- return min <= e-p ? min : e-p;
- }
-}
-
-int
-rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
-{
- int n;
- if (e <= p)
- return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(1);
- n = ONIGENC_PRECISE_MBC_ENC_LEN(enc, (UChar*)p, (UChar*)e);
- if (e-p < n)
- return ONIGENC_CONSTRUCT_MBCLEN_NEEDMORE(n-(e-p));
- return n;
-}
-
-int
-rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
-{
- int c, l;
- if (e <= p)
- return -1;
- if (rb_enc_asciicompat(enc)) {
- c = (unsigned char)*p;
- if (!ISASCII(c))
- return -1;
- if (len) *len = 1;
- return c;
- }
- l = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(l))
- return -1;
- c = rb_enc_mbc_to_codepoint(p, e, enc);
- if (!rb_enc_isascii(c, enc))
- return -1;
- if (len) *len = l;
- return c;
-}
-
-int
-rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
-{
- int r;
- if (e <= p)
- rb_raise(rb_eArgError, "empty string");
- r = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_CHARFOUND_P(r))
- return rb_enc_mbc_to_codepoint(p, e, enc);
- else
- rb_raise(rb_eArgError, "invalid mbstring sequence");
-}
-
-int
-rb_enc_codelen(int c, rb_encoding *enc)
-{
- int n = ONIGENC_CODE_TO_MBCLEN(enc,c);
- if (n == 0) {
- rb_raise(rb_eArgError, "invalid codepoint 0x%x", c);
- }
- return n;
-}
-
-int
-rb_enc_toupper(int c, rb_encoding *enc)
-{
- return (ONIGENC_IS_ASCII_CODE(c)?ONIGENC_ASCII_CODE_TO_UPPER_CASE(c):(c));
-}
-
-int
-rb_enc_tolower(int c, rb_encoding *enc)
-{
- return (ONIGENC_IS_ASCII_CODE(c)?ONIGENC_ASCII_CODE_TO_LOWER_CASE(c):(c));
-}
-#endif
-
/*
* call-seq:
* enc.inspect => string
@@ -903,7 +180,6 @@
static VALUE
enc_inspect(VALUE self)
{
-#if WITH_OBJC
char buffer[512];
VALUE enc_name;
long n;
@@ -914,13 +190,6 @@
RSTRING_PTR(enc_name));
return rb_str_new(buffer, n);
-#else
- VALUE str = rb_sprintf("#<%s:%s%s>", rb_obj_classname(self),
- rb_enc_name((rb_encoding*)DATA_PTR(self)),
- (ENC_DUMMY_P(self) ? " (dummy)" : ""));
- ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
- return str;
-#endif
}
/*
@@ -934,11 +203,7 @@
static VALUE
enc_name(VALUE self)
{
-#if WITH_OBJC
return (VALUE)CFStringConvertEncodingToIANACharSetName(rb_enc_to_enc(self));
-#else
- return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
-#endif
}
static VALUE
@@ -968,7 +233,6 @@
static VALUE
enc_list(VALUE klass)
{
-#if WITH_OBJC
VALUE ary;
const CFStringEncoding *e;
@@ -978,16 +242,6 @@
rb_ary_push(ary, enc_make(e));
e++;
}
-#else
- VALUE ary = rb_ary_new2(enc_table.count);
- int i;
- for (i = 0; i < enc_table.count; ++i) {
- rb_encoding *enc = enc_table.list[i].enc;
- if (enc) {
- rb_ary_push(ary, rb_enc_from_encoding(enc));
- }
- }
-#endif
return ary;
}
@@ -1028,24 +282,10 @@
static VALUE
enc_find(VALUE klass, VALUE enc)
{
-#if WITH_OBJC
VALUE e = enc_find2(enc);
if (e == Qnil)
rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
return e;
-#else
- int idx;
-
- StringValue(enc);
- if (!rb_enc_asciicompat(rb_enc_get(enc))) {
- rb_raise(rb_eArgError, "invalid name encoding (non ASCII)");
- }
- idx = rb_enc_find_index(StringValueCStr(enc));
- if (idx < 0) {
- rb_raise(rb_eArgError, "unknown encoding name - %s", RSTRING_BYTEPTR(enc));
- }
- return rb_enc_from_encoding(rb_enc_from_index(idx));
-#endif
}
/*
@@ -1091,72 +331,6 @@
return enc_find(klass, str);
}
-#if !WITH_OBJC
-rb_encoding *
-rb_ascii8bit_encoding(void)
-{
- if (!enc_table.list) {
- rb_enc_init();
- }
- return enc_table.list[0].enc;
-}
-
-rb_encoding *
-rb_utf8_encoding(void)
-{
- if (!enc_table.list) {
- rb_enc_init();
- }
- return enc_table.list[ENCINDEX_UTF_8].enc;
-}
-
-rb_encoding *
-rb_usascii_encoding(void)
-{
- if (!enc_table.list) {
- rb_enc_init();
- }
- return enc_table.list[ENCINDEX_US_ASCII].enc;
-}
-
-int
-rb_usascii_encindex(void)
-{
- return ENCINDEX_US_ASCII;
-}
-
-rb_encoding *
-rb_locale_encoding(void)
-{
- VALUE charmap = rb_locale_charmap(rb_cEncoding);
- int idx;
-
- if (NIL_P(charmap))
- idx = rb_enc_find_index("US-ASCII");
- else
- idx = rb_enc_find_index(StringValueCStr(charmap));
- if (idx < 0)
- return rb_ascii8bit_encoding();
-
- return rb_enc_from_index(idx);
-}
-
-static int default_external_index;
-
-rb_encoding *
-rb_default_external_encoding(void)
-{
- return rb_enc_from_index(default_external_index);
-}
-
-VALUE
-rb_enc_default_external(void)
-{
- return rb_enc_from_encoding(rb_default_external_encoding());
-}
-#endif
-
-#if WITH_OBJC
static rb_encoding *default_external;
rb_encoding *
@@ -1170,7 +344,6 @@
{
return enc_make(default_external);
}
-#endif
/*
* call-seq:
@@ -1189,11 +362,7 @@
void
rb_enc_set_default_external(VALUE encoding)
{
-#if WITH_OBJC
default_external = rb_enc_to_enc_ptr(encoding);
-#else
- default_external_index = rb_enc_to_index(rb_to_encoding(encoding));
-#endif
}
/*
@@ -1218,80 +387,10 @@
VALUE
rb_locale_charmap(VALUE klass)
{
-#if WITH_OBJC
CFStringEncoding enc = CFStringGetSystemEncoding();
return (VALUE)CFStringConvertEncodingToIANACharSetName(enc);
-#elif defined NO_LOCALE_CHARMAP
- return rb_usascii_str_new2("ASCII-8BIT");
-#elif defined HAVE_LANGINFO_H
- char *codeset;
- codeset = nl_langinfo(CODESET);
- return rb_usascii_str_new2(codeset);
-#elif defined _WIN32
- return rb_sprintf("CP%d", GetACP());
-#else
- return Qnil;
-#endif
}
-#if !WITH_OBJC
-static void
-set_encoding_const(const char *name, rb_encoding *enc)
-{
- VALUE encoding = rb_enc_from_encoding(enc);
- char *s = (char *)name;
- int haslower = 0, hasupper = 0, valid = 0;
-
- if (ISDIGIT(*s)) return;
- if (ISUPPER(*s)) {
- hasupper = 1;
- while (*++s && (ISALNUM(*s) || *s == '_')) {
- if (ISLOWER(*s)) haslower = 1;
- }
- }
- if (!*s) {
- valid = 1;
- rb_define_const(rb_cEncoding, name, encoding);
- }
- if (!valid || haslower) {
- int len = strlen(name) + 1;
- if (!haslower || !hasupper) {
- do {
- if (ISLOWER(*s)) haslower = 1;
- if (ISUPPER(*s)) hasupper = 1;
- } while (*++s && (!haslower || !hasupper));
- }
- MEMCPY(s = ALLOCA_N(char, len), name, char, len);
- name = s;
- if (!valid) {
- if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
- for (; *s; ++s) {
- if (!ISALNUM(*s)) *s = '_';
- }
- if (hasupper) {
- rb_define_const(rb_cEncoding, name, encoding);
- }
- }
- if (haslower) {
- for (s = (char *)name; *s; ++s) {
- if (ISLOWER(*s)) *s = ONIGENC_ASCII_CODE_TO_UPPER_CASE((int)*s);
- }
- rb_define_const(rb_cEncoding, name, encoding);
- }
- }
-}
-
-static int
-rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg)
-{
- VALUE ary = (VALUE)arg;
- VALUE str = rb_usascii_str_new2((char *)name);
- OBJ_FREEZE(str);
- rb_ary_push(ary, str);
- return ST_CONTINUE;
-}
-#endif
-
/*
* call-seq:
* Encoding.name_list => ["enc1", "enc2", ...]
@@ -1311,7 +410,6 @@
static VALUE
rb_enc_name_list(VALUE klass)
{
-#if WITH_OBJC
VALUE ary, list;
long i, count;
@@ -1319,39 +417,9 @@
list = enc_list(klass);
for (i = 0, count = RARRAY_LEN(list); i < count; i++)
rb_ary_push(ary, enc_name(RARRAY_AT(list, i)));
-#else
- VALUE ary = rb_ary_new2(enc_table.names->num_entries);
- st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
-#endif
return ary;
}
-#if !WITH_OBJC
-static int
-rb_enc_aliases_enc_i(st_data_t name, st_data_t orig, st_data_t arg)
-{
- VALUE *p = (VALUE *)arg;
- VALUE aliases = p[0], ary = p[1];
- int idx = (int)orig;
- VALUE key, str = rb_ary_entry(ary, idx);
-
- if (NIL_P(str)) {
- rb_encoding *enc = rb_enc_from_index(idx);
-
- if (STRCASECMP((char*)name, rb_enc_name(enc)) == 0) {
- return ST_CONTINUE;
- }
- str = rb_usascii_str_new2(rb_enc_name(enc));
- OBJ_FREEZE(str);
- rb_ary_store(ary, idx, str);
- }
- key = rb_usascii_str_new2((char *)name);
- OBJ_FREEZE(key);
- rb_hash_aset(aliases, key, str);
- return ST_CONTINUE;
-}
-#endif
-
/*
* call-seq:
* Encoding.aliases => {"alias1" => "orig1", "alias2" => "orig2", ...}
@@ -1367,18 +435,10 @@
static VALUE
rb_enc_aliases(VALUE klass)
{
-#if WITH_OBJC
/* TODO: the CFString IANA <-> charset code does support aliases, we should
* find a way to return them here.
*/
return rb_hash_new();
-#else
- VALUE aliases[2];
- aliases[0] = rb_hash_new();
- aliases[1] = rb_ary_new();
- st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
- return aliases[0];
-#endif
}
VALUE
Modified: MacRuby/trunk/eval.c
===================================================================
--- MacRuby/trunk/eval.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/eval.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -54,6 +54,10 @@
void Init_PreGC(void);
void Init_BareVM(void);
+#if WITH_OBJC
+bool ruby_dlog_enabled = false;
+#endif
+
void
ruby_init(void)
{
@@ -70,6 +74,11 @@
rb_origenviron = environ;
#endif
+#if WITH_OBJC
+ char *s = getenv("MACRUBY_DEBUG");
+ ruby_dlog_enabled = !(s == NULL || *s == '0');
+#endif
+
Init_stack((void *)&state);
Init_PreGC();
Init_BareVM();
@@ -336,7 +345,7 @@
const char *desc = "something(?!)";
if (OBJ_FROZEN(klass)) {
- if (FL_TEST(klass, FL_SINGLETON))
+ if (RCLASS_SINGLETON(klass))
desc = "object";
else {
switch (TYPE(klass)) {
@@ -857,11 +866,11 @@
return module;
}
-void
+VALUE
rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
{
PASS_PASSED_BLOCK();
- rb_funcall2(obj, idInitialize, argc, argv);
+ return rb_funcall2(obj, idInitialize, argc, argv);
}
void
Modified: MacRuby/trunk/ext/extmk.rb
===================================================================
--- MacRuby/trunk/ext/extmk.rb 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/ext/extmk.rb 2008-08-21 06:13:14 UTC (rev 459)
@@ -85,7 +85,6 @@
end
def extmake(target)
-GC.start
print "#{$message} #{target}\n"
$stdout.flush
if $force_static or $static_ext[target]
@@ -431,8 +430,6 @@
FileUtils::makedirs('ext')
Dir::chdir('ext')
-GC.start
-
hdrdir = $hdrdir
$hdrdir = ($top_srcdir = relative_from(srcdir, $topdir = "..")) + "/include"
exts.each do |d|
Modified: MacRuby/trunk/ext/syck/rubyext.c
===================================================================
--- MacRuby/trunk/ext/syck/rubyext.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/ext/syck/rubyext.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -22,11 +22,11 @@
#endif
struct RBasic basic;
struct RObject object;
- struct RClass klass;
/*struct RFloat flonum;*/
/*struct RString string;*/
/*struct RRegexp regexp;*/
#if !WITH_OBJC
+ struct RClass klass;
struct RArray array;
struct RHash hash;
#endif
Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/gc.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,16 +1,14 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's gc.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- gc.c -
-
- $Author: akr $
- created at: Tue Oct 5 09:44:46 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/signal.h"
#include "ruby/st.h"
@@ -33,16 +31,11 @@
#include <sys/resource.h>
#endif
-#if defined _WIN32 || defined __CYGWIN__
-#include <windows.h>
-#endif
-
-#if WITH_OBJC
-# include <mach/mach.h>
-# if HAVE_AUTO_ZONE_H
-# include <auto_zone.h>
-# else
-# include <malloc/malloc.h>
+#include <mach/mach.h>
+#if HAVE_AUTO_ZONE_H
+# include <auto_zone.h>
+#else
+# include <malloc/malloc.h>
typedef malloc_zone_t auto_zone_t;
#define AUTO_MEMORY_SCANNED 0
#define AUTO_MEMORY_UNSCANNED 1
@@ -110,57 +103,17 @@
size_t bytes_freed_during_last_collection[2];
// durations not included
} auto_statistics_t;
-# endif
+#endif
static auto_zone_t *__auto_zone = NULL;
static long xmalloc_count = 0;
-#endif
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-# include <valgrind/memcheck.h>
-# ifndef VALGRIND_MAKE_MEM_DEFINED
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE(p, n)
-# endif
-# ifndef VALGRIND_MAKE_MEM_UNDEFINED
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE(p, n)
-# endif
-#else
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) /* empty */
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) /* empty */
-#endif
-
int rb_io_fptr_finalize(struct rb_io_t*);
-#define rb_setjmp(env) RUBY_SETJMP(env)
#define rb_jmp_buf rb_jmpbuf_t
-/* Make alloca work the best possible way. */
-#ifdef __GNUC__
-# ifndef atarist
-# ifndef alloca
-# define alloca __builtin_alloca
-# endif
-# endif /* atarist */
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca ();
-# endif
-# endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
#ifndef GC_MALLOC_LIMIT
-#if defined(MSDOS) || defined(__human68k__)
-#define GC_MALLOC_LIMIT 200000
-#else
-#define GC_MALLOC_LIMIT 8000000
+# define GC_MALLOC_LIMIT 8000000
#endif
-#endif
static VALUE nomem_error;
@@ -170,169 +123,6 @@
#undef GC_DEBUG
-#if !WITH_OBJC
-
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
-#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
-#endif
-
-typedef struct RVALUE {
- union {
- struct {
- VALUE flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- struct RFloat flonum;
- struct RString string;
- struct RArray array;
- struct RRegexp regexp;
- struct RHash hash;
- struct RData data;
- struct RStruct rstruct;
- struct RBignum bignum;
- struct RFile file;
- struct RNode node;
- struct RMatch match;
- struct RRational rational;
- struct RComplex complex;
- } as;
-#ifdef GC_DEBUG
- char *file;
- int line;
-#endif
-} RVALUE;
-
-#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
-#pragma pack(pop)
-#endif
-
-struct heaps_slot {
- void *membase;
- RVALUE *slot;
- int limit;
-};
-
-#define HEAP_MIN_SLOTS 10000
-#define FREE_MIN 4096
-
-struct gc_list {
- VALUE *varptr;
- struct gc_list *next;
-};
-
-typedef struct rb_objspace {
- struct {
- size_t limit;
- size_t increase;
- } params;
- struct {
- size_t increment;
- struct heaps_slot *ptr;
- size_t length;
- size_t used;
- RVALUE *freelist;
- RVALUE *range[2];
- RVALUE *freed;
- } heap;
- struct {
- int dont_gc;
- int during_gc;
- } flags;
- struct {
- int need_call;
- st_table *table;
- RVALUE *deferred;
- } final;
- struct {
- VALUE buffer[MARK_STACK_MAX];
- VALUE *ptr;
- int overflow;
- } markstack;
- struct gc_list *global_list;
- unsigned int count;
-} rb_objspace_t;
-
-#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
-#define rb_objspace (*GET_VM()->objspace)
-#else
-static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}};
-#endif
-#define malloc_limit objspace->params.limit
-#define malloc_increase objspace->params.increase
-#define heap_slots objspace->heap.slots
-#define heaps objspace->heap.ptr
-#define heaps_length objspace->heap.length
-#define heaps_used objspace->heap.used
-#define freelist objspace->heap.freelist
-#define lomem objspace->heap.range[0]
-#define himem objspace->heap.range[1]
-#define heaps_inc objspace->heap.increment
-#define heaps_freed objspace->heap.freed
-#define dont_gc objspace->flags.dont_gc
-#define during_gc objspace->flags.during_gc
-#define need_call_final objspace->final.need_call
-#define finalizer_table objspace->final.table
-#define deferred_final_list objspace->final.deferred
-#define mark_stack objspace->markstack.buffer
-#define mark_stack_ptr objspace->markstack.ptr
-#define mark_stack_overflow objspace->markstack.overflow
-#define global_List objspace->global_list
-
-rb_objspace_t *
-rb_objspace_alloc(void)
-{
- rb_objspace_t *objspace = malloc(sizeof(rb_objspace_t));
- memset(objspace, 0, sizeof(*objspace));
- malloc_limit = GC_MALLOC_LIMIT;
-
- return objspace;
-}
-
-/* tiny heap size */
-/* 32KB */
-/*#define HEAP_SIZE 0x8000 */
-/* 128KB */
-/*#define HEAP_SIZE 0x20000 */
-/* 64KB */
-/*#define HEAP_SIZE 0x10000 */
-/* 16KB */
-#define HEAP_SIZE 0x4000
-/* 8KB */
-/*#define HEAP_SIZE 0x2000 */
-/* 4KB */
-/*#define HEAP_SIZE 0x1000 */
-/* 2KB */
-/*#define HEAP_SIZE 0x800 */
-
-#define HEAP_OBJ_LIMIT (HEAP_SIZE / sizeof(struct RVALUE))
-#define FREE_MIN 4096
-
-extern st_table *rb_class_tbl;
-VALUE *rb_gc_stack_start = 0;
-#ifdef __ia64
-VALUE *rb_gc_register_stack_start = 0;
-#endif
-
-
-#ifdef DJGPP
-/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
-unsigned int _stklen = 0x180000; /* 1.5 kB */
-#endif
-
-#if defined(DJGPP) || defined(_WIN32_WCE)
-size_t rb_gc_stack_maxsize = 65535*sizeof(VALUE);
-#else
-size_t rb_gc_stack_maxsize = 655300*sizeof(VALUE);
-#endif
-
-static void run_final(rb_objspace_t *objspace, VALUE obj);
-static int garbage_collect(rb_objspace_t *objspace);
-
-#else
-
int ruby_gc_stress = 0;
static long malloc_increase = 0;
bool dont_gc = false;
@@ -343,8 +133,6 @@
#endif
size_t rb_gc_stack_maxsize = 655300*sizeof(VALUE);
-#endif
-
void
rb_global_variable(VALUE *var)
{
@@ -407,8 +195,6 @@
garbage_collect();
}
-#if WITH_OBJC
-
static void
rb_objc_no_gc_error(void)
{
@@ -498,131 +284,13 @@
return ruby_xrealloc(ptr, len);
}
-#else
-
-void *
-ruby_vm_xmalloc(rb_objspace_t *objspace, size_t size)
-{
- void *mem;
-
- if (size < 0) {
- rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
- }
- if (size == 0) size = 1;
- rb_gc_malloc_increase(size);
- RUBY_CRITICAL(mem = malloc(size));
- if (!mem) {
- if (garbage_collect(objspace)) {
- RUBY_CRITICAL(mem = malloc(size));
- }
- if (!mem) {
- rb_memerror();
- }
- }
-
- return mem;
-}
-
-void *
-ruby_xmalloc(size_t size)
-{
- return ruby_vm_xmalloc(&rb_objspace, size);
-}
-
-void *
-ruby_vm_xmalloc2(rb_objspace_t *objspace, size_t n, size_t size)
-{
- size_t len = size * n;
- if (n != 0 && size != len / n) {
- rb_raise(rb_eArgError, "malloc: possible integer overflow");
- }
- return ruby_vm_xmalloc(objspace, len);
-}
-
-void *
-ruby_xmalloc2(size_t n, size_t size)
-{
- return ruby_vm_xmalloc2(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xcalloc(rb_objspace_t *objspace, size_t n, size_t size)
-{
- void *mem;
-
- mem = ruby_vm_xmalloc2(objspace, n, size);
- memset(mem, 0, n * size);
-
- return mem;
-}
-
-void *
-ruby_xcalloc(size_t n, size_t size)
-{
- return ruby_vm_xcalloc(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
-{
- void *mem;
-
- if (size < 0) {
- rb_raise(rb_eArgError, "negative re-allocation size");
- }
- if (!ptr) return ruby_xmalloc(size);
- if (size == 0) size = 1;
- malloc_increase += size;
- if (ruby_gc_stress) garbage_collect();
- RUBY_CRITICAL(mem = realloc(ptr, size));
- if (!mem) {
- if (garbage_collect(objspace)) {
- RUBY_CRITICAL(mem = realloc(ptr, size));
- }
- if (!mem) {
- rb_memerror();
- }
- }
-
- return mem;
-}
-
-void *
-ruby_xrealloc(void *ptr, size_t size)
-{
- return ruby_vm_xrealloc(&rb_objspace, ptr, size);
-}
-
-void *
-ruby_vm_xrealloc2(rb_objspace_t *objspace, void *ptr, size_t n, size_t size)
-{
- size_t len = size * n;
- if (n != 0 && size != len / n) {
- rb_raise(rb_eArgError, "realloc: possible integer overflow");
- }
- return ruby_vm_xrealloc(objspace, ptr, len);
-}
-
-void *
-ruby_xrealloc2(void *ptr, size_t n, size_t size)
-{
- return ruby_vm_xrealloc2(&rb_objspace, ptr, n, size);
-}
-
-#endif
-
void
ruby_xfree(void *x)
{
-#if WITH_OBJC
if (x != NULL) {
auto_zone_retain(__auto_zone, x);
malloc_zone_free(__auto_zone, x);
}
-#else
- if (x)
- RUBY_CRITICAL(free(x));
-#endif
}
@@ -644,9 +312,7 @@
{
int old = dont_gc;
-#if WITH_OBJC
auto_collector_reenable(__auto_zone);
-#endif
dont_gc = Qfalse;
return old;
}
@@ -668,257 +334,14 @@
{
int old = dont_gc;
-#if WITH_OBJC
auto_collector_disable(__auto_zone);
-#endif
dont_gc = Qtrue;
return old;
}
VALUE rb_mGC;
-#if !WITH_OBJC
-
void
-rb_gc_register_address(VALUE *addr)
-{
- rb_objspace_t *objspace = &rb_objspace;
- struct gc_list *tmp;
-
- tmp = ALLOC(struct gc_list);
- tmp->next = global_List;
- tmp->varptr = addr;
- global_List = tmp;
-}
-
-void
-rb_register_mark_object(VALUE obj)
-{
- VALUE ary = GET_THREAD()->vm->mark_object_ary;
- rb_ary_push(ary, obj);
-}
-
-void
-rb_gc_unregister_address(VALUE *addr)
-{
- rb_objspace_t *objspace = &rb_objspace;
- struct gc_list *tmp = global_List;
-
- if (tmp->varptr == addr) {
- global_List = tmp->next;
- RUBY_CRITICAL(free(tmp));
- return;
- }
- while (tmp->next) {
- if (tmp->next->varptr == addr) {
- struct gc_list *t = tmp->next;
-
- tmp->next = tmp->next->next;
- RUBY_CRITICAL(free(t));
- break;
- }
- tmp = tmp->next;
- }
-}
-
-
-static void
-allocate_heaps(rb_objspace_t *objspace, size_t next_heaps_length)
-{
- struct heaps_slot *p;
- size_t size;
-
- size = next_heaps_length*sizeof(struct heaps_slot);
- RUBY_CRITICAL(
- if (heaps_used > 0) {
- p = (struct heaps_slot *)realloc(heaps, size);
- if (p) heaps = p;
- }
- else {
- p = heaps = (struct heaps_slot *)malloc(size);
- }
- );
- if (p == 0) rb_memerror();
- heaps_length = next_heaps_length;
-}
-
-static void
-assign_heap_slot(rb_objspace_t *objspace)
-{
- RVALUE *p, *pend, *membase;
- size_t hi, lo, mid;
- int objs;
-
- objs = HEAP_OBJ_LIMIT;
- RUBY_CRITICAL(p = (RVALUE*)malloc(HEAP_SIZE));
- if (p == 0)
- rb_memerror();
-
- membase = p;
- if ((VALUE)p % sizeof(RVALUE) != 0) {
- p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
- if ((HEAP_SIZE - HEAP_OBJ_LIMIT * sizeof(RVALUE)) < ((char*)p - (char*)membase)) {
- objs--;
- }
- }
-
-
- lo = 0;
- hi = heaps_used;
- while (lo < hi) {
- register RVALUE *mid_membase;
- mid = (lo + hi) / 2;
- mid_membase = heaps[mid].membase;
- if (mid_membase < membase) {
- lo = mid + 1;
- }
- else if (mid_membase > membase) {
- hi = mid;
- }
- else {
- rb_bug("same heap slot is allocated: %p at %ld", membase, mid);
- }
- }
- if (hi < heaps_used) {
- MEMMOVE(&heaps[hi+1], &heaps[hi], struct heaps_slot, heaps_used - hi);
- }
- heaps[hi].membase = membase;
- heaps[hi].slot = p;
- heaps[hi].limit = objs;
- pend = p + objs;
- if (lomem == 0 || lomem > p) lomem = p;
- if (himem < pend) himem = pend;
- heaps_used++;
-
- while (p < pend) {
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- p++;
- }
-}
-
-static void
-init_heap(rb_objspace_t *objspace)
-{
- size_t add, i;
-
- add = HEAP_MIN_SLOTS / HEAP_OBJ_LIMIT;
-
- if ((heaps_used + add) > heaps_length) {
- allocate_heaps(objspace, heaps_used + add);
- }
-
- for (i = 0; i < add; i++) {
- assign_heap_slot(objspace);
- }
- heaps_inc = 0;
-}
-
-
-static void
-set_heaps_increment(rb_objspace_t *objspace)
-{
- size_t next_heaps_length = heaps_used * 1.8;
- heaps_inc = next_heaps_length - heaps_used;
-
- if (next_heaps_length > heaps_length) {
- allocate_heaps(objspace, next_heaps_length);
- }
-}
-
-static int
-heaps_increment(rb_objspace_t *objspace)
-{
- if (heaps_inc > 0) {
- assign_heap_slot(objspace);
- heaps_inc--;
- return Qtrue;
- }
- return Qfalse;
-}
-
-#define RANY(o) ((RVALUE*)(o))
-
-static VALUE
-rb_newobj_from_heap(rb_objspace_t *objspace)
-{
- VALUE obj;
-
- if (ruby_gc_stress || !freelist) {
- if (!heaps_increment(objspace) && !garbage_collect(objspace)) {
- rb_memerror();
- }
- }
-
- obj = (VALUE)freelist;
- freelist = freelist->as.free.next;
-
- MEMZERO((void*)obj, RVALUE, 1);
-#ifdef GC_DEBUG
- RANY(obj)->file = rb_sourcefile();
- RANY(obj)->line = rb_sourceline();
-#endif
-
- return obj;
-}
-
-#if USE_VALUE_CACHE
-static VALUE
-rb_fill_value_cache(rb_thread_t *th)
-{
- rb_objspace_t *objspace = &rb_objspace;
- int i;
- VALUE rv;
-
- /* LOCK */
- for (i=0; i<RUBY_VM_VALUE_CACHE_SIZE; i++) {
- VALUE v = rb_newobj_from_heap(objspace);
-
- th->value_cache[i] = v;
- RBASIC(v)->flags = FL_MARK;
- }
- th->value_cache_ptr = &th->value_cache[0];
- rv = rb_newobj_from_heap(objspace);
- /* UNLOCK */
- return rv;
-}
-#endif
-
-VALUE
-rb_newobj(void)
-{
-#if USE_VALUE_CACHE
- rb_thread_t *th = GET_THREAD();
- VALUE v = *th->value_cache_ptr;
-#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
- rb_objspace_t *objspace = th->vm->objspace;
-#else
- rb_objspace_t *objspace = &rb_objspace;
-#endif
-
- if (v) {
- RBASIC(v)->flags = 0;
- th->value_cache_ptr++;
- }
- else {
- v = rb_fill_value_cache(th);
- }
-
-#if defined(GC_DEBUG)
- printf("cache index: %d, v: %p, th: %p\n",
- th->value_cache_ptr - th->value_cache, v, th);
-#endif
- return v;
-#else
- rb_objspace_t *objspace = &rb_objspace;
- return rb_newobj_from_heap(objspace);
-#endif
-}
-
-#else /* !WITH_OBJC */
-
-void
rb_objc_wb(void *dst, void *newval)
{
if (!SPECIAL_CONST_P(newval)) {
@@ -1029,7 +452,7 @@
#endif
if (__nsobject == NULL)
__nsobject = (void *)objc_getClass("NSObject");
- RBASIC(obj)->isa = __nsobject;
+ RBASIC(obj)->klass = (VALUE)__nsobject;
return obj;
}
@@ -1053,8 +476,6 @@
//(*scanner)(context, th->stack, th->stack + th->stack_size);
}
-#endif /* WITH_OBJC */
-
NODE*
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
@@ -1148,960 +569,13 @@
return ret;
}
-#if !WITH_OBJC
-static void
-init_mark_stack(rb_objspace_t *objspace)
-{
- mark_stack_overflow = 0;
- mark_stack_ptr = mark_stack;
-}
-
-#define MARK_STACK_EMPTY (mark_stack_ptr == mark_stack)
-
-
-static void gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev);
-static void gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev);
-
-static void
-gc_mark_all(rb_objspace_t *objspace)
-{
- RVALUE *p, *pend;
- size_t i;
-
- init_mark_stack(objspace);
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if ((p->as.basic.flags & FL_MARK) &&
- (p->as.basic.flags != FL_MARK)) {
- gc_mark_children(objspace, (VALUE)p, 0);
- }
- p++;
- }
- }
-}
-
-static void
-gc_mark_rest(rb_objspace_t *objspace)
-{
- VALUE tmp_arry[MARK_STACK_MAX];
- VALUE *p;
-
- p = (mark_stack_ptr - mark_stack) + tmp_arry;
- MEMCPY(tmp_arry, mark_stack, VALUE, p - tmp_arry);
-
- init_mark_stack(objspace);
- while (p != tmp_arry) {
- p--;
- gc_mark_children(objspace, *p, 0);
- }
-}
-
-static inline int
-is_pointer_to_heap(rb_objspace_t *objspace, void *ptr)
-{
- register RVALUE *p = RANY(ptr);
- register struct heaps_slot *heap;
- register size_t hi, lo, mid;
-
- if (p < lomem || p > himem) return Qfalse;
- if ((VALUE)p % sizeof(RVALUE) != 0) return Qfalse;
-
- /* check if p looks like a pointer using bsearch*/
- lo = 0;
- hi = heaps_used;
- while (lo < hi) {
- mid = (lo + hi) / 2;
- heap = &heaps[mid];
- if (heap->slot <= p) {
- if (p < heap->slot + heap->limit)
- return Qtrue;
- lo = mid + 1;
- }
- else {
- hi = mid;
- }
- }
- return Qfalse;
-}
-
-static void
-mark_locations_array(rb_objspace_t *objspace, register VALUE *x, register long n)
-{
- VALUE v;
- while (n--) {
- v = *x;
- VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
- if (is_pointer_to_heap(objspace, (void *)v)) {
- gc_mark(objspace, v, 0);
- }
- x++;
- }
-}
-
-static void
-gc_mark_locations(rb_objspace_t *objspace, VALUE *start, VALUE *end)
-{
- long n;
-
- if (end <= start) return;
- n = end - start;
- mark_locations_array(&rb_objspace, start,n);
-}
-
void
-rb_gc_mark_locations(VALUE *start, VALUE *end)
-{
- gc_mark_locations(&rb_objspace, start, end);
-}
-
-#define rb_gc_mark_locations(start, end) gc_mark_locations(objspace, start, end)
-
-struct mark_tbl_arg {
- rb_objspace_t *objspace;
- int lev;
-};
-
-static int
-mark_entry(ID key, VALUE value, st_data_t data)
-{
- struct mark_tbl_arg *arg = (void*)data;
- gc_mark(arg->objspace, value, arg->lev);
- return ST_CONTINUE;
-}
-
-static void
-mark_tbl(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
- struct mark_tbl_arg arg;
- if (!tbl) return;
- arg.objspace = objspace;
- arg.lev = lev;
- st_foreach(tbl, mark_entry, (st_data_t)&arg);
-}
-
-void
-rb_mark_tbl(st_table *tbl)
-{
- mark_tbl(&rb_objspace, tbl, 0);
-}
-
-static int
-mark_key(VALUE key, VALUE value, st_data_t data)
-{
- struct mark_tbl_arg *arg = (void*)data;
- gc_mark(arg->objspace, key, arg->lev);
- return ST_CONTINUE;
-}
-
-static void
-mark_set(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
- struct mark_tbl_arg arg;
- if (!tbl) return;
- arg.objspace = objspace;
- arg.lev = lev;
- st_foreach(tbl, mark_key, (st_data_t)&arg);
-}
-
-void
-rb_mark_set(st_table *tbl)
-{
- mark_set(&rb_objspace, tbl, 0);
-}
-
-static int
-mark_keyvalue(VALUE key, VALUE value, st_data_t data)
-{
- struct mark_tbl_arg *arg = (void*)data;
- gc_mark(arg->objspace, key, arg->lev);
- gc_mark(arg->objspace, value, arg->lev);
- return ST_CONTINUE;
-}
-
-static void
-mark_hash(rb_objspace_t *objspace, st_table *tbl, int lev)
-{
- struct mark_tbl_arg arg;
- if (!tbl) return;
- arg.objspace = objspace;
- arg.lev = lev;
- st_foreach(tbl, mark_keyvalue, (st_data_t)&arg);
-}
-
-void
-rb_mark_hash(st_table *tbl)
-{
- mark_hash(&rb_objspace, tbl, 0);
-}
-
-void
-rb_gc_mark_maybe(VALUE obj)
-{
- if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
- gc_mark(&rb_objspace, obj, 0);
- }
-}
-
-#define GC_LEVEL_MAX 250
-
-static void
-gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev)
-{
- register RVALUE *obj;
-
- obj = RANY(ptr);
- if (rb_special_const_p(ptr)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
- obj->as.basic.flags |= FL_MARK;
-
- if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
- if (!mark_stack_overflow) {
- if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) {
- *mark_stack_ptr = ptr;
- mark_stack_ptr++;
- }
- else {
- mark_stack_overflow = 1;
- }
- }
- return;
- }
- gc_mark_children(objspace, ptr, lev+1);
-}
-
-void
-rb_gc_mark(VALUE ptr)
-{
- gc_mark(&rb_objspace, ptr, 0);
-}
-
-static void
-gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
-{
- register RVALUE *obj = RANY(ptr);
-
- goto marking; /* skip */
-
- again:
- obj = RANY(ptr);
- if (rb_special_const_p(ptr)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
- obj->as.basic.flags |= FL_MARK;
-
- marking:
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_generic_ivar(ptr);
- }
-
- switch (obj->as.basic.flags & T_MASK) {
- case T_NIL:
- case T_FIXNUM:
- rb_bug("rb_gc_mark() called for broken object");
- break;
-
- case T_NODE:
- switch (nd_type(obj)) {
- case NODE_IF: /* 1,2,3 */
- case NODE_FOR:
- case NODE_ITER:
- case NODE_WHEN:
- case NODE_MASGN:
- case NODE_RESCUE:
- case NODE_RESBODY:
- case NODE_CLASS:
- case NODE_BLOCK_PASS:
- gc_mark(objspace, (VALUE)obj->as.node.u2.node, lev);
- /* fall through */
- case NODE_BLOCK: /* 1,3 */
- case NODE_OPTBLOCK:
- case NODE_ARRAY:
- case NODE_DSTR:
- case NODE_DXSTR:
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- case NODE_ENSURE:
- case NODE_CALL:
- case NODE_DEFS:
- case NODE_OP_ASGN1:
- case NODE_ARGS:
- gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
- /* fall through */
- case NODE_SUPER: /* 3 */
- case NODE_FCALL:
- case NODE_DEFN:
- case NODE_ARGS_AUX:
- ptr = (VALUE)obj->as.node.u3.node;
- goto again;
-
- case NODE_METHOD: /* 1,2 */
- case NODE_WHILE:
- case NODE_UNTIL:
- case NODE_AND:
- case NODE_OR:
- case NODE_CASE:
- case NODE_SCLASS:
- case NODE_DOT2:
- case NODE_DOT3:
- case NODE_FLIP2:
- case NODE_FLIP3:
- case NODE_MATCH2:
- case NODE_MATCH3:
- case NODE_OP_ASGN_OR:
- case NODE_OP_ASGN_AND:
- case NODE_MODULE:
- case NODE_ALIAS:
- case NODE_VALIAS:
- case NODE_ARGSCAT:
- gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
- /* fall through */
- case NODE_FBODY: /* 2 */
- case NODE_GASGN:
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_DASGN_CURR:
- case NODE_IASGN:
- case NODE_IASGN2:
- case NODE_CVASGN:
- case NODE_COLON3:
- case NODE_OPT_N:
- case NODE_EVSTR:
- case NODE_UNDEF:
- case NODE_POSTEXE:
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- case NODE_HASH: /* 1 */
- case NODE_LIT:
- case NODE_STR:
- case NODE_XSTR:
- case NODE_DEFINED:
- case NODE_MATCH:
- case NODE_RETURN:
- case NODE_BREAK:
- case NODE_NEXT:
- case NODE_YIELD:
- case NODE_COLON2:
- case NODE_SPLAT:
- case NODE_TO_ARY:
- ptr = (VALUE)obj->as.node.u1.node;
- goto again;
-
- case NODE_SCOPE: /* 2,3 */
- case NODE_CDECL:
- case NODE_OPT_ARG:
- gc_mark(objspace, (VALUE)obj->as.node.u3.node, lev);
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- case NODE_ZARRAY: /* - */
- case NODE_ZSUPER:
- case NODE_CFUNC:
- case NODE_VCALL:
- case NODE_GVAR:
- case NODE_LVAR:
- case NODE_DVAR:
- case NODE_IVAR:
- case NODE_CVAR:
- case NODE_NTH_REF:
- case NODE_BACK_REF:
- case NODE_REDO:
- case NODE_RETRY:
- case NODE_SELF:
- case NODE_NIL:
- case NODE_TRUE:
- case NODE_FALSE:
- case NODE_ERRINFO:
- case NODE_ATTRSET:
- case NODE_BLOCK_ARG:
- break;
- case NODE_ALLOCA:
- mark_locations_array(objspace,
- (VALUE*)obj->as.node.u1.value,
- obj->as.node.u3.cnt);
- ptr = (VALUE)obj->as.node.u2.node;
- goto again;
-
- default: /* unlisted NODE */
- if (is_pointer_to_heap(objspace, obj->as.node.u1.node)) {
- gc_mark(objspace, (VALUE)obj->as.node.u1.node, lev);
- }
- if (is_pointer_to_heap(objspace, obj->as.node.u2.node)) {
- gc_mark(objspace, (VALUE)obj->as.node.u2.node, lev);
- }
- if (is_pointer_to_heap(objspace, obj->as.node.u3.node)) {
- gc_mark(objspace, (VALUE)obj->as.node.u3.node, lev);
- }
- }
- return; /* no need to mark class. */
- }
-
- gc_mark(objspace, obj->as.basic.klass, lev);
- switch (obj->as.basic.flags & T_MASK) {
- case T_ICLASS:
- case T_CLASS:
- case T_MODULE:
- mark_tbl(objspace, RCLASS_M_TBL(obj), lev);
- mark_tbl(objspace, RCLASS_IV_TBL(obj), lev);
- ptr = RCLASS_SUPER(obj);
- goto again;
-
- case T_ARRAY:
- if (FL_TEST(obj, ELTS_SHARED)) {
- ptr = obj->as.array.aux.shared;
- goto again;
- }
- else {
- long i, len = RARRAY_LEN(obj);
- VALUE *ptr = RARRAY_PTR(obj);
- for (i=0; i < len; i++) {
- gc_mark(objspace, *ptr++, lev);
- }
- }
- break;
-
- case T_HASH:
- mark_hash(objspace, obj->as.hash.ntbl, lev);
- ptr = obj->as.hash.ifnone;
- goto again;
-
- case T_STRING:
-#define STR_ASSOC FL_USER3 /* copied from string.c */
- if (FL_TEST(obj, RSTRING_NOEMBED) && FL_ANY(obj, ELTS_SHARED|STR_ASSOC)) {
- ptr = obj->as.string.as.heap.aux.shared;
- goto again;
- }
- break;
-
- case T_DATA:
- if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
- break;
-
- case T_OBJECT:
- {
- long i, len = ROBJECT_NUMIV(obj);
- VALUE *ptr = ROBJECT_IVPTR(obj);
- for (i = 0; i < len; i++) {
- gc_mark(objspace, *ptr++, lev);
- }
- }
- break;
-
- case T_FILE:
- if (obj->as.file.fptr)
- gc_mark(objspace, obj->as.file.fptr->tied_io_for_writing, lev);
- break;
-
- case T_REGEXP:
- case T_FLOAT:
- case T_BIGNUM:
- break;
-
- case T_MATCH:
- gc_mark(objspace, obj->as.match.regexp, lev);
- if (obj->as.match.str) {
- ptr = obj->as.match.str;
- goto again;
- }
- break;
-
- case T_RATIONAL:
- gc_mark(objspace, obj->as.rational.num, lev);
- gc_mark(objspace, obj->as.rational.den, lev);
- break;
-
- case T_COMPLEX:
- gc_mark(objspace, obj->as.complex.real, lev);
- gc_mark(objspace, obj->as.complex.image, lev);
- break;
-
- case T_STRUCT:
- {
- long len = RSTRUCT_LEN(obj);
- VALUE *ptr = RSTRUCT_PTR(obj);
-
- while (len--) {
- gc_mark(objspace, *ptr++, lev);
- }
- }
- break;
-
- case T_VALUES:
- {
- rb_gc_mark(RVALUES(obj)->v1);
- rb_gc_mark(RVALUES(obj)->v2);
- ptr = RVALUES(obj)->v3;
- goto again;
- }
- break;
-
- default:
- rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
- obj->as.basic.flags & T_MASK, obj,
- is_pointer_to_heap(objspace, obj) ? "corrupted object" : "non object");
- }
-}
-
-static void obj_free(rb_objspace_t *, VALUE);
-
-static void
-finalize_list(rb_objspace_t *objspace, RVALUE *p)
-{
- while (p) {
- RVALUE *tmp = p->as.free.next;
- run_final(objspace, (VALUE)p);
- if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- }
- p = tmp;
- }
-}
-
-static void
-free_unused_heaps(rb_objspace_t *objspace)
-{
- size_t i, j;
- RVALUE *last = 0;
-
- for (i = j = 1; j < heaps_used; i++) {
- if (heaps[i].limit == 0) {
- if (!last) {
- last = heaps[i].membase;
- }
- else {
- free(heaps[i].membase);
- }
- heaps_used--;
- }
- else {
- if (i != j) {
- heaps[j] = heaps[i];
- }
- j++;
- }
- }
- if (last) {
- if (last < heaps_freed) {
- free(heaps_freed);
- heaps_freed = last;
- }
- else {
- free(last);
- }
- }
-}
-
-void rb_gc_abort_threads(void);
-
-static void
-gc_sweep(rb_objspace_t *objspace)
-{
- RVALUE *p, *pend, *final_list;
- size_t freed = 0;
- size_t i;
- size_t live = 0, free_min = 0, do_heap_free = 0;
-
- do_heap_free = (heaps_used * HEAP_OBJ_LIMIT) * 0.65;
- free_min = (heaps_used * HEAP_OBJ_LIMIT) * 0.2;
- if (free_min < FREE_MIN) {
- do_heap_free = heaps_used * HEAP_OBJ_LIMIT;
- free_min = FREE_MIN;
- }
-
- freelist = 0;
- final_list = deferred_final_list;
- deferred_final_list = 0;
- for (i = 0; i < heaps_used; i++) {
- int n = 0;
- RVALUE *free = freelist;
- RVALUE *final = final_list;
-
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (!(p->as.basic.flags & FL_MARK)) {
- if (p->as.basic.flags) {
- obj_free(objspace, (VALUE)p);
- }
- if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
- p->as.free.flags = FL_MARK; /* remain marked */
- p->as.free.next = final_list;
- final_list = p;
- }
- else {
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- }
- n++;
- }
- else if (RBASIC(p)->flags == FL_MARK) {
- /* objects to be finalized */
- /* do nothing remain marked */
- }
- else {
- RBASIC(p)->flags &= ~FL_MARK;
- live++;
- }
- p++;
- }
- if (n == heaps[i].limit && freed > do_heap_free) {
- RVALUE *pp;
-
- heaps[i].limit = 0;
- for (pp = final_list; pp != final; pp = pp->as.free.next) {
- p->as.free.flags |= FL_SINGLETON; /* freeing page mark */
- }
- freelist = free; /* cancel this page from freelist */
- }
- else {
- freed += n;
- }
- }
- if (malloc_increase > malloc_limit) {
- malloc_limit += (malloc_increase - malloc_limit) * (double)live / (live + freed);
- if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
- }
- malloc_increase = 0;
- if (freed < free_min) {
- set_heaps_increment(objspace);
- heaps_increment(objspace);
- }
- during_gc = 0;
-
- /* clear finalization list */
- if (final_list) {
- deferred_final_list = final_list;
- return;
- }
- free_unused_heaps(objspace);
-}
-
-#endif /* !WITH_OBJC */
-
-void
rb_gc_force_recycle(VALUE p)
{
-#if WITH_OBJC
xfree((void *)p);
-#else
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- RANY(p)->as.free.flags = 0;
- RANY(p)->as.free.next = freelist;
- freelist = RANY(p);
-#endif
}
-#if !WITH_OBJC
-static void
-obj_free(rb_objspace_t *objspace, VALUE obj)
-{
- switch (RANY(obj)->as.basic.flags & T_MASK) {
- case T_NIL:
- case T_FIXNUM:
- case T_TRUE:
- case T_FALSE:
- rb_bug("obj_free() called for broken object");
- break;
- }
-
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_free_generic_ivar((VALUE)obj);
- }
-
- switch (RANY(obj)->as.basic.flags & T_MASK) {
- case T_OBJECT:
- if (!(RANY(obj)->as.basic.flags & ROBJECT_EMBED) &&
- RANY(obj)->as.object.as.heap.ivptr) {
- RUBY_CRITICAL(free(RANY(obj)->as.object.as.heap.ivptr));
- }
- break;
- case T_MODULE:
- case T_CLASS:
- rb_clear_cache_by_class((VALUE)obj);
- st_free_table(RCLASS_M_TBL(obj));
- if (RCLASS_IV_TBL(obj)) {
- st_free_table(RCLASS_IV_TBL(obj));
- }
- if (RCLASS_IV_INDEX_TBL(obj)) {
- st_free_table(RCLASS_IV_INDEX_TBL(obj));
- }
- RUBY_CRITICAL(free(RANY(obj)->as.klass.ptr));
- break;
- case T_STRING:
- rb_str_free(obj);
- break;
- case T_ARRAY:
- rb_ary_free(obj);
- break;
- case T_HASH:
- if (RANY(obj)->as.hash.ntbl) {
- st_free_table(RANY(obj)->as.hash.ntbl);
- }
- break;
- case T_REGEXP:
- if (RANY(obj)->as.regexp.ptr) {
- onig_free(RANY(obj)->as.regexp.ptr);
- }
- if (RANY(obj)->as.regexp.str) {
- RUBY_CRITICAL(free(RANY(obj)->as.regexp.str));
- }
- break;
- case T_DATA:
- if (DATA_PTR(obj)) {
- if ((long)RANY(obj)->as.data.dfree == -1) {
- RUBY_CRITICAL(free(DATA_PTR(obj)));
- }
- else if (RANY(obj)->as.data.dfree) {
- (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
- }
- }
- break;
- case T_MATCH:
- if (RANY(obj)->as.match.rmatch) {
- struct rmatch *rm = RANY(obj)->as.match.rmatch;
- onig_region_free(&rm->regs, 0);
- if (rm->char_offset)
- RUBY_CRITICAL(free(rm->char_offset));
- RUBY_CRITICAL(free(rm));
- }
- break;
- case T_FILE:
- if (RANY(obj)->as.file.fptr) {
- rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
- }
- break;
- case T_RATIONAL:
- case T_COMPLEX:
- break;
- case T_ICLASS:
- /* iClass shares table with the module */
- break;
-
- case T_FLOAT:
- break;
- case T_VALUES:
- break;
-
- case T_BIGNUM:
- if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
- RUBY_CRITICAL(free(RBIGNUM_DIGITS(obj)));
- }
- break;
- case T_NODE:
- switch (nd_type(obj)) {
- case NODE_SCOPE:
- if (RANY(obj)->as.node.u1.tbl) {
- RUBY_CRITICAL(free(RANY(obj)->as.node.u1.tbl));
- }
- break;
- case NODE_ALLOCA:
- RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
- break;
- }
- return; /* no need to free iv_tbl */
-
- case T_STRUCT:
- if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
- RANY(obj)->as.rstruct.as.heap.ptr) {
- RUBY_CRITICAL(free(RANY(obj)->as.rstruct.as.heap.ptr));
- }
- break;
-
- default:
- rb_bug("gc_sweep(): unknown data type 0x%lx(%p)",
- RANY(obj)->as.basic.flags & T_MASK, (void*)obj);
- }
-}
-
-#ifdef __GNUC__
-#if defined(__human68k__) || defined(DJGPP)
-#undef rb_setjmp
-#undef rb_jmp_buf
-#if defined(__human68k__)
-typedef unsigned long rb_jmp_buf[8];
-__asm__ (".even\n\
-_rb_setjmp:\n\
- move.l 4(sp),a0\n\
- movem.l d3-d7/a3-a5,(a0)\n\
- moveq.l #0,d0\n\
- rts");
-#else
-#if defined(DJGPP)
-typedef unsigned long rb_jmp_buf[6];
-__asm__ (".align 4\n\
-_rb_setjmp:\n\
- pushl %ebp\n\
- movl %esp,%ebp\n\
- movl 8(%ebp),%ebp\n\
- movl %eax,(%ebp)\n\
- movl %ebx,4(%ebp)\n\
- movl %ecx,8(%ebp)\n\
- movl %edx,12(%ebp)\n\
- movl %esi,16(%ebp)\n\
- movl %edi,20(%ebp)\n\
- popl %ebp\n\
- xorl %eax,%eax\n\
- ret");
-#endif
-#endif
-int rb_setjmp (rb_jmp_buf);
-#endif /* __human68k__ or DJGPP */
-#endif /* __GNUC__ */
-
-#define GC_NOTIFY 0
-
-void rb_vm_mark(void *ptr);
-
-static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
-{
- rb_jmp_buf save_regs_gc_mark;
- VALUE *stack_start, *stack_end;
-
- SET_STACK_END;
-#if STACK_GROW_DIRECTION < 0
- stack_start = th->machine_stack_end;
- stack_end = th->machine_stack_start;
-#elif STACK_GROW_DIRECTION > 0
- stack_start = th->machine_stack_start;
- stack_end = th->machine_stack_end + 1;
-#else
- if (th->machine_stack_end < th->machine_stack_start) {
- stack_start = th->machine_stack_end;
- stack_end = th->machine_stack_start;
- }
- else {
- stack_start = th->machine_stack_start;
- stack_end = th->machine_stack_end + 1;
- }
-#endif
-
- FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf (and stack) */
- rb_setjmp(save_regs_gc_mark);
- mark_locations_array(objspace,
- (VALUE*)save_regs_gc_mark,
- sizeof(save_regs_gc_mark) / sizeof(VALUE));
-
- rb_gc_mark_locations(stack_start, stack_end);
-#ifdef __ia64
- rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
-#endif
-#if defined(__human68k__) || defined(__mc68000__)
- mark_locations_array((VALUE*)((char*)STACK_END + 2),
- (STACK_START - STACK_END));
-#endif
-}
-
-void rb_gc_mark_encodings(void);
-
static int
-garbage_collect(rb_objspace_t *objspace)
-{
- struct gc_list *list;
- rb_thread_t *th = GET_THREAD();
-
- if (GC_NOTIFY) printf("start garbage_collect()\n");
-
- if (!heaps) {
- return Qfalse;
- }
-
- if (dont_gc || during_gc) {
- if (!freelist) {
- if (!heaps_increment(objspace)) {
- set_heaps_increment(objspace);
- heaps_increment(objspace);
- }
- }
- return Qtrue;
- }
- during_gc++;
- objspace->count++;
-
- SET_STACK_END;
-
- init_mark_stack(objspace);
-
- th->vm->self ? rb_gc_mark(th->vm->self) : rb_vm_mark(th->vm);
-
- if (finalizer_table) {
- mark_tbl(objspace, finalizer_table, 0);
- }
-
- mark_current_machine_context(objspace, th);
-
- rb_gc_mark_threads();
- rb_gc_mark_symbols();
- rb_gc_mark_encodings();
-
- /* mark protected global variables */
- for (list = global_List; list; list = list->next) {
- rb_gc_mark_maybe(*list->varptr);
- }
- rb_mark_end_proc();
- rb_gc_mark_global_tbl();
-
- mark_tbl(objspace, rb_class_tbl, 0);
- rb_gc_mark_trap_list();
-
- /* mark generic instance variables for special constants */
- rb_mark_generic_ivar_tbl();
-
- rb_gc_mark_parser();
-
- /* gc_mark objects whose marking are not completed*/
- while (!MARK_STACK_EMPTY) {
- if (mark_stack_overflow) {
- gc_mark_all(objspace);
- }
- else {
- gc_mark_rest(objspace);
- }
- }
-
- gc_sweep(objspace);
-
- if (GC_NOTIFY) printf("end garbage_collect()\n");
- return Qtrue;
-}
-
-int
-rb_garbage_collect(void)
-{
- return garbage_collect(&rb_objspace);
-}
-
-void
-rb_gc_mark_machine_stack(rb_thread_t *th)
-{
- rb_objspace_t *objspace = &rb_objspace;
-#if STACK_GROW_DIRECTION < 0
- rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
-#elif STACK_GROW_DIRECTION > 0
- rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end);
-#else
- if (th->machine_stack_start < th->machine_stack_end) {
- rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end);
- }
- else {
- rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
- }
-#endif
-#ifdef __ia64
- rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
-#endif
-}
-
-#else /* !WITH_OBJC */
-
-static int
garbage_collect(void)
{
if (dont_gc)
@@ -2111,15 +585,10 @@
return Qtrue;
}
-#endif
-
void
rb_gc(void)
{
garbage_collect();
-#if !WITH_OBJC
- rb_gc_finalize_deferred();
-#endif
}
/*
@@ -2139,20 +608,6 @@
return Qnil;
}
-#if !WITH_OBJC
-void
-ruby_set_stack_size(size_t size)
-{
- rb_gc_stack_maxsize = size;
-}
-
-void
-Init_stack(VALUE *addr)
-{
- ruby_init_stack(addr);
-}
-#endif
-
#undef ruby_init_stack
void
ruby_init_stack(VALUE *addr
@@ -2231,7 +686,6 @@
*
*/
-#if WITH_OBJC
static bool
rb_objc_is_placeholder(void *obj)
{
@@ -2251,6 +705,48 @@
int count;
};
+static int
+rb_objc_yield_classes(VALUE of)
+{
+ int i, count, rcount;
+ Class *buf;
+
+ count = objc_getClassList(NULL, 0);
+ assert(count > 0);
+
+ buf = (Class *)alloca(sizeof(Class) * count);
+ objc_getClassList(buf, count);
+
+ for (i = rcount = 0; i < count; i++) {
+ Class sk, k = buf[i];
+ bool nsobject_based;
+
+ if (class_getName(k)[0] == '_')
+ continue;
+
+ if (of == rb_cModule && !RCLASS_MODULE(k))
+ continue;
+
+ nsobject_based = false;
+ sk = k;
+ do {
+ sk = (Class)RCLASS_SUPER(sk);
+ if (sk == (Class)rb_cNSObject) {
+ nsobject_based = true;
+ break;
+ }
+ }
+ while (sk != NULL);
+
+ if (nsobject_based) {
+ rb_yield((VALUE)k);
+ rcount++;
+ }
+ }
+
+ return rcount;
+}
+
static void
rb_objc_recorder(task_t task, void *context, unsigned type_mask,
vm_range_t *ranges, unsigned range_count)
@@ -2266,101 +762,38 @@
auto_zone_get_layout_type_no_lock(__auto_zone, (void *)r->address);
if (type != AUTO_OBJECT_SCANNED && type != AUTO_OBJECT_UNSCANNED)
continue;
+ if (*(Class *)r->address == NULL)
+ continue;
if (ctx->class_of != 0) {
- if (ctx->class_of == rb_cClass || ctx->class_of == rb_cModule) {
- /* Class/Module are a special case. */
- if (rb_objc_is_non_native(r->address)
- || FL_TEST(r->address, FL_SINGLETON))
- continue;
- if (ctx->class_of == rb_cClass) {
- /* Only match classes. */
- if (BUILTIN_TYPE(r->address) != T_CLASS)
- continue;
+ bool ok = false;
+ for (c = *(Class *)r->address; c != NULL;
+ c = class_getSuperclass(c)) {
+ if (c ==(Class)ctx->class_of) {
+ ok = true;
+ break;
}
- else {
- /* Match classes & modules. */
- if (BUILTIN_TYPE(r->address) != T_CLASS
- && BUILTIN_TYPE(r->address) != T_MODULE)
- continue;
- }
}
- else {
- unsigned ok = 0;
- for (c = *(Class *)r->address; c != NULL;
- c = class_getSuperclass(c)) {
- if (c == RCLASS(ctx->class_of)->ocklass) {
- ok = 1;
- break;
- }
- }
- if (!ok)
- continue;
- }
+ if (!ok)
+ continue;
}
- if (!rb_objc_is_non_native((VALUE)r->address)) {
- switch (BUILTIN_TYPE(r->address)) {
- case T_NONE:
- case T_ICLASS:
- case T_NODE:
+ switch (TYPE(r->address)) {
+ case T_NONE:
+ case T_NODE:
+ continue;
+ case T_ICLASS:
+ case T_CLASS:
+ case T_MODULE:
+ rb_bug("object %p of type %d should not be recorded",
+ (void *)r->address, TYPE(r->address));
+ case T_NATIVE:
+ if (rb_objc_is_placeholder((void *)r->address))
continue;
- case T_CLASS:
- if (FL_TEST(r->address, FL_SINGLETON))
- continue;
- }
}
- else {
- if (rb_objc_is_placeholder((void *)r->address))
- continue;
- }
rb_yield((VALUE)r->address);
ctx->count++;
}
}
-#else
-void
-Init_heap(void)
-{
- if (!rb_gc_stack_start) {
- Init_stack(0);
- }
- init_heap(&rb_objspace);
-}
-static VALUE
-os_obj_of(rb_objspace_t *objspace, VALUE of)
-{
- size_t i;
- size_t n = 0;
-
- for (i = 0; i < heaps_used; i++) {
- RVALUE *p, *pend;
-
- p = heaps[i].slot; pend = p + heaps[i].limit;
- for (;p < pend; p++) {
- if (p->as.basic.flags) {
- switch (BUILTIN_TYPE(p)) {
- case T_NONE:
- case T_ICLASS:
- case T_NODE:
- case T_VALUES:
- continue;
- case T_CLASS:
- if (FL_TEST(p, FL_SINGLETON)) continue;
- default:
- if (!p->as.basic.klass) continue;
- if (!of || rb_obj_is_kind_of((VALUE)p, of)) {
- rb_yield((VALUE)p);
- n++;
- }
- }
- }
- }
- }
-
- return SIZET2NUM(n);
-}
-#endif
-
/*
* call-seq:
* ObjectSpace.each_object([module]) {|obj| ... } => fixnum
@@ -2398,6 +831,7 @@
os_each_obj(int argc, VALUE *argv, VALUE os)
{
VALUE of;
+ int count;
rb_secure(4);
if (argc == 0) {
@@ -2407,15 +841,21 @@
rb_scan_args(argc, argv, "01", &of);
}
RETURN_ENUMERATOR(os, 1, &of);
-#if WITH_OBJC
- struct rb_objc_recorder_context ctx = {of, 0};
- (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
+
+ /* Class/Module are a special case, because they are not auto objects */
+ count = rb_objc_yield_classes(of);
+
+ if (of != rb_cClass && of != rb_cModule) {
+ struct rb_objc_recorder_context ctx = {of, count};
+
+ (((malloc_zone_t *)__auto_zone)->introspect->enumerator)(
mach_task_self(), (void *)&ctx, MALLOC_PTR_IN_USE_RANGE_TYPE,
(vm_address_t)__auto_zone, NULL, rb_objc_recorder);
- return INT2FIX(ctx.count);
-#else
- return os_obj_of(&rb_objspace, of);
-#endif
+
+ count = ctx.count;
+ }
+
+ return INT2FIX(count);
}
/*
@@ -2426,29 +866,20 @@
*
*/
-#if WITH_OBJC
static CFMutableDictionaryRef __os_finalizers = NULL;
-#endif
static VALUE
undefine_final(VALUE os, VALUE obj)
{
-#if WITH_OBJC
if (__os_finalizers != NULL)
CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
rb_objc_flag_set((void *)obj, FL_FINALIZE, false);
}
else {
FL_UNSET(obj, FL_FINALIZE);
}
-#else
- rb_objspace_t *objspace = &rb_objspace;
- if (finalizer_table) {
- st_delete(finalizer_table, (st_data_t*)&obj, 0);
- }
-#endif
return obj;
}
@@ -2464,7 +895,6 @@
static VALUE
define_final(int argc, VALUE *argv, VALUE os)
{
-#if WITH_OBJC
VALUE obj, block, table;
if (__os_finalizers == NULL)
@@ -2491,52 +921,24 @@
rb_ary_push(table, block);
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
rb_objc_flag_set((void *)obj, FL_FINALIZE, true);
}
else {
FL_SET(obj, FL_FINALIZE);
}
-#else
- rb_objspace_t *objspace = &rb_objspace;
- VALUE obj, block, table;
-
- rb_scan_args(argc, argv, "11", &obj, &block);
- if (argc == 1) {
- block = rb_block_proc();
- }
- else if (!rb_respond_to(block, rb_intern("call"))) {
- rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
- rb_obj_classname(block));
- }
- need_call_final = 1;
- FL_SET(obj, FL_FINALIZE);
-
- block = rb_ary_new3(2, INT2FIX(rb_safe_level()), block);
-
- if (!finalizer_table) {
- finalizer_table = st_init_numtable();
- }
- if (st_lookup(finalizer_table, obj, &table)) {
- rb_ary_push(table, block);
- }
- else {
- st_add_direct(finalizer_table, obj, rb_ary_new3(1, block));
- }
-#endif
return block;
}
void
rb_gc_copy_finalizer(VALUE dest, VALUE obj)
{
-#if WITH_OBJC
VALUE table;
if (__os_finalizers == NULL)
return;
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
if (!rb_objc_flag_check((void *)obj, FL_FINALIZE))
return;
}
@@ -2555,55 +957,8 @@
CFDictionarySetValue(__os_finalizers, (const void *)dest,
(const void *)table);
}
-#else
- rb_objspace_t *objspace = &rb_objspace;
- VALUE table;
-
- if (!finalizer_table) return;
- if (!FL_TEST(obj, FL_FINALIZE)) return;
- if (st_lookup(finalizer_table, obj, &table)) {
- st_insert(finalizer_table, dest, table);
- }
- FL_SET(dest, FL_FINALIZE);
-#endif
}
-#if !WITH_OBJC
-static VALUE
-run_single_final(VALUE arg)
-{
- VALUE *args = (VALUE *)arg;
- rb_eval_cmd(args[0], args[1], (int)args[2]);
- return Qnil;
-}
-
-static void
-run_final(rb_objspace_t *objspace, VALUE obj)
-{
- long i;
- int status, critical_save = rb_thread_critical;
- VALUE args[3], table, objid;
-
- objid = rb_obj_id(obj); /* make obj into id */
- rb_thread_critical = Qtrue;
- args[1] = 0;
- args[2] = (VALUE)rb_safe_level();
- if (finalizer_table && st_delete(finalizer_table, (st_data_t*)&obj, &table)) {
- if (!args[1] && RARRAY_LEN(table) > 0) {
- args[1] = rb_obj_freeze(rb_ary_new3(1, objid));
- }
- for (i=0; i<RARRAY_LEN(table); i++) {
- VALUE final = RARRAY_PTR(table)[i];
- args[0] = RARRAY_PTR(final)[1];
- args[2] = FIX2INT(RARRAY_PTR(final)[0]);
- rb_protect(run_single_final, (VALUE)args, &status);
- }
- }
- rb_thread_critical = critical_save;
-}
-#endif
-
-#if WITH_OBJC
static CFMutableArrayRef __exit_finalize = NULL;
static void
@@ -2662,91 +1017,6 @@
auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
}
-#else /* WITH_OBJC */
-
-static void
-gc_finalize_deferred(rb_objspace_t *objspace)
-{
- RVALUE *p = deferred_final_list;
-
- during_gc++;
- deferred_final_list = 0;
- if (p) {
- finalize_list(objspace, p);
- }
- free_unused_heaps(objspace);
- during_gc = 0;
-}
-
-void
-rb_gc_finalize_deferred(void)
-{
- gc_finalize_deferred(&rb_objspace);
-}
-
-void
-rb_gc_call_finalizer_at_exit(void)
-{
- rb_objspace_t *objspace = &rb_objspace;
- RVALUE *p, *pend;
- size_t i;
-
- /* finalizers are part of garbage collection */
- during_gc++;
- /* run finalizers */
- if (need_call_final) {
- p = deferred_final_list;
- deferred_final_list = 0;
- finalize_list(objspace, p);
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (FL_TEST(p, FL_FINALIZE)) {
- FL_UNSET(p, FL_FINALIZE);
- p->as.basic.klass = 0;
- run_final(objspace, (VALUE)p);
- }
- p++;
- }
- }
- }
- /* run data object's finalizers */
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (BUILTIN_TYPE(p) == T_DATA &&
- DATA_PTR(p) && RANY(p)->as.data.dfree &&
- RANY(p)->as.basic.klass != rb_cThread) {
- p->as.free.flags = 0;
- if ((long)RANY(p)->as.data.dfree == -1) {
- RUBY_CRITICAL(free(DATA_PTR(p)));
- }
- else if (RANY(p)->as.data.dfree) {
- (*RANY(p)->as.data.dfree)(DATA_PTR(p));
- }
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- }
- else if (BUILTIN_TYPE(p) == T_FILE) {
- if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
- p->as.free.flags = 0;
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- }
- }
- p++;
- }
- }
- during_gc = 0;
-}
-
-void
-rb_gc(void)
-{
- rb_objspace_t *objspace = &rb_objspace;
- garbage_collect(objspace);
- gc_finalize_deferred(objspace);
-}
-#endif
-
/*
* call-seq:
* ObjectSpace._id2ref(object_id) -> an_object
@@ -2768,9 +1038,6 @@
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
#define NUM2PTR(x) NUM2ULL(x)
#endif
-#if !WITH_OBJC
- rb_objspace_t *objspace = &rb_objspace;
-#endif
VALUE ptr;
void *p0;
@@ -2781,42 +1048,19 @@
if (ptr == Qtrue) return Qtrue;
if (ptr == Qfalse) return Qfalse;
if (ptr == Qnil) return Qnil;
-#if WITH_OBJC
if (FIXNUM_P(ptr) || SYMBOL_P(ptr))
return ptr;
-#else
- if (FIXNUM_P(ptr)) return (VALUE)ptr;
- ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */
- if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
- ID symid = ptr / sizeof(RVALUE);
- if (rb_id2name(symid) == 0)
- rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
- return ID2SYM(symid);
- }
-#endif
-
-#if WITH_OBJC
if (auto_zone_is_valid_pointer(auto_zone(), p0)) {
auto_memory_type_t type =
auto_zone_get_layout_type_no_lock(__auto_zone, p0);
if ((type == AUTO_OBJECT_SCANNED || type == AUTO_OBJECT_UNSCANNED)
&& !rb_objc_is_placeholder(p0)
- && (rb_objc_is_non_native((VALUE)p0)
+ && (NATIVE((VALUE)p0)
|| (BUILTIN_TYPE(p0) < T_FIXNUM && BUILTIN_TYPE(p0) != T_ICLASS)))
return (VALUE)p0;
}
rb_raise(rb_eRangeError, "%p is not id value", p0);
-#else
- if (!is_pointer_to_heap(objspace, (void *)ptr) ||
- BUILTIN_TYPE(ptr) >= T_VALUES || BUILTIN_TYPE(ptr) == T_ICLASS) {
- rb_raise(rb_eRangeError, "%p is not id value", p0);
- }
- if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
- rb_raise(rb_eRangeError, "%p is recycled object", p0);
- }
- return (VALUE)ptr;
-#endif
}
/*
@@ -2849,47 +1093,7 @@
VALUE
rb_obj_id(VALUE obj)
{
- /*
- * 32-bit VALUE space
- * MSB ------------------------ LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol ssssssssssssssssssssssss00001110
- * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
- * fixnum fffffffffffffffffffffffffffffff1
- *
- * object_id space
- * LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object oooooooooooooooooooooooooooooo0 o...o % A = 0
- * fixnum fffffffffffffffffffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
-#if !WITH_OBJC
- if (TYPE(obj) == T_SYMBOL) {
- return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
- }
-#endif
- if (SPECIAL_CONST_P(obj)) {
- return LONG2NUM((SIGNED_VALUE)obj);
- }
-#if WITH_OBJC
return (VALUE)LONG2NUM((SIGNED_VALUE)obj);
-#else
- return (VALUE)((SIGNED_VALUE)obj|FIXNUM_FLAG);
-#endif
}
/*
@@ -2915,9 +1119,9 @@
static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
-#if WITH_OBJC
+ /* TODO implement me! */
return rb_hash_new();
-#else
+#if 0
rb_objspace_t *objspace = &rb_objspace;
size_t counts[T_MASK+1];
size_t freed = 0;
@@ -3003,18 +1207,12 @@
*
*/
-#if WITH_OBJC
static long _gc_count = 0;
-#endif
static VALUE
gc_count(VALUE self)
{
-#if WITH_OBJC
return UINT2NUM(_gc_count);
-#else
- return UINT2NUM((&rb_objspace)->count);
-#endif
}
/*
@@ -3023,7 +1221,6 @@
* are also available via the <code>ObjectSpace</code> module.
*/
-#if WITH_OBJC
static void (*old_batch_invalidate)(auto_zone_t *,
auto_zone_foreach_object_t, auto_zone_cursor_t, size_t);
@@ -3076,7 +1273,7 @@
__rb_objc_finalize(void *obj, void *data)
{
//printf("finalize %p <%s>\n",obj, class_getName(*(Class *)obj));
- if (rb_objc_is_non_native((VALUE)obj)) {
+ if (NATIVE((VALUE)obj)) {
static SEL sel = NULL;
long flag;
flag = rb_objc_remove_flags(obj);
@@ -3107,20 +1304,16 @@
*/
_gc_count++;
}
-#endif
void
Init_PreGC(void)
{
-#if WITH_OBJC
auto_collection_control_t *control;
__auto_zone = auto_zone();
if (__auto_zone == NULL)
rb_objc_no_gc_error();
-
- //auto_zone_register_thread(__auto_zone);
control = auto_collection_parameters(__auto_zone);
control->scan_external_callout =
@@ -3130,19 +1323,16 @@
| AUTO_LOG_UNUSUAL;
old_batch_invalidate = control->batch_invalidate;
control->batch_invalidate = rb_objc_batch_invalidate;
-#endif
}
void
Init_PostGC(void)
{
-#if WITH_OBJC
-# if 0
+#if 0
/* It is better to let Foundation start the dedicated collection thread
* when necessary.
*/
objc_startCollectorThread();
-# endif
#endif
}
@@ -3177,4 +1367,4 @@
rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
-}
+}
\ No newline at end of file
Modified: MacRuby/trunk/hash.c
===================================================================
--- MacRuby/trunk/hash.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/hash.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,30 +1,24 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's hash.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- hash.c -
-
- $Author: knu $
- created at: Mon Nov 22 18:51:18 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "ruby/signal.h"
+#include "id.h"
-#ifdef __APPLE__
#include <crt_externs.h>
-#endif
static VALUE rb_hash_s_try_convert(VALUE, VALUE);
-#define HASH_DELETED FL_USER1
-#define HASH_PROC_DEFAULT FL_USER2
-
VALUE
rb_hash_freeze(VALUE hash)
{
@@ -32,95 +26,19 @@
}
VALUE rb_cHash;
-#if WITH_OBJC
VALUE rb_cCFHash;
-VALUE rb_cHashRuby;
-#endif
+VALUE rb_cNSHash;
+VALUE rb_cNSMutableHash;
static VALUE envtbl;
static ID id_hash, id_yield, id_default;
-static VALUE
-eql(VALUE *args)
-{
- return (VALUE)rb_eql(args[0], args[1]);
-}
-
-int
-rb_any_cmp(VALUE a, VALUE b)
-{
- VALUE args[2];
-
- if (a == b) return 0;
- if (a == Qundef || b == Qundef) return -1;
- if (FIXNUM_P(a) && FIXNUM_P(b)) {
- return a != b;
- }
- if (SYMBOL_P(a) && SYMBOL_P(b)) {
- return a != b;
- }
-#if WITH_OBJC
- if (TYPE(a) == T_STRING && TYPE(b) == T_STRING)
- return rb_str_hash_cmp(a, b);
-#else
- if (TYPE(a) == T_STRING && RBASIC(a)->klass == rb_cString &&
- TYPE(b) == T_STRING && RBASIC(b)->klass == rb_cString) {
- return rb_str_hash_cmp(a, b);
- }
-#endif
-
- args[0] = a;
- args[1] = b;
- return !rb_with_disable_interrupt(eql, (VALUE)args);
-}
-
VALUE
rb_hash(VALUE obj)
{
return rb_funcall(obj, id_hash, 0);
}
-static int
-rb_any_hash(VALUE a)
-{
- VALUE hval;
- int hnum;
-
- switch (TYPE(a)) {
- case T_FIXNUM:
- case T_SYMBOL:
- hnum = (int)a;
- break;
-
- case T_STRING:
- hnum = rb_str_hash(a);
- break;
-
- default:
- hval = rb_funcall(a, id_hash, 0);
- if (!FIXNUM_P(hval)) {
- hval = rb_funcall(hval, '%', 1, INT2FIX(536870923));
- }
- hnum = (int)FIX2LONG(hval);
- }
-#if WITH_OBJC
- return hnum;
-#else
- hnum <<= 1;
- return RSHIFT(hnum, 1);
-#endif
-}
-
-static const struct st_hash_type objhash = {
- rb_any_cmp,
- rb_any_hash,
-};
-
-static const struct st_hash_type identhash = {
- st_numcmp,
- st_numhash,
-};
-
typedef int st_foreach_func(st_data_t, st_data_t, st_data_t);
struct foreach_safe_arg {
@@ -155,67 +73,9 @@
}
}
-#if !WITH_OBJC
-typedef int rb_foreach_func(VALUE, VALUE, VALUE);
-
-struct hash_foreach_arg {
- VALUE hash;
- rb_foreach_func *func;
- VALUE arg;
-};
-
-static int
-hash_foreach_iter(VALUE key, VALUE value, struct hash_foreach_arg *arg)
-{
- int status;
- st_table *tbl;
-
- tbl = RHASH(arg->hash)->ntbl;
- if (key == Qundef) return ST_CONTINUE;
- status = (*arg->func)(key, value, arg->arg);
- if (RHASH(arg->hash)->ntbl != tbl) {
- rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
- }
- switch (status) {
- case ST_DELETE:
- st_delete_safe(tbl, (st_data_t*)&key, 0, Qundef);
- FL_SET(arg->hash, HASH_DELETED);
- case ST_CONTINUE:
- break;
- case ST_STOP:
- return ST_STOP;
- }
- return ST_CHECK;
-}
-
-static VALUE
-hash_foreach_ensure(VALUE hash)
-{
- RHASH(hash)->iter_lev--;
-
- if (RHASH(hash)->iter_lev == 0) {
- if (FL_TEST(hash, HASH_DELETED)) {
- st_cleanup_safe(RHASH(hash)->ntbl, Qundef);
- FL_UNSET(hash, HASH_DELETED);
- }
- }
- return 0;
-}
-
-static VALUE
-hash_foreach_call(struct hash_foreach_arg *arg)
-{
- if (st_foreach(RHASH(arg->hash)->ntbl, hash_foreach_iter, (st_data_t)arg)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
- }
- return Qnil;
-}
-#endif
-
void
rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
{
-#if WITH_OBJC
CFIndex i, count;
const void **keys;
const void **values;
@@ -230,52 +90,14 @@
CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
for (i = 0; i < count; i++) {
- if ((*func)((VALUE)keys[i], (VALUE)values[i], farg) != ST_CONTINUE)
+ if ((*func)(OC2RB(keys[i]), OC2RB(values[i]), farg) != ST_CONTINUE)
break;
}
-#else
- struct hash_foreach_arg arg;
-
- if (!RHASH(hash)->ntbl)
- return;
- RHASH(hash)->iter_lev++;
- arg.hash = hash;
- arg.func = (rb_foreach_func *)func;
- arg.arg = farg;
- rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash);
-#endif
}
-#if WITH_OBJC
-
# define HASH_KEY_CALLBACKS(h) \
((CFDictionaryKeyCallBacks *)((uint8_t *)h + 52))
-static Boolean
-rb_cfdictionary_equal_cb(const void *v1, const void *v2)
-{
- return v1 == v2 || !rb_any_cmp((VALUE)v1, (VALUE)v2);
-}
-
-static CFHashCode
-rb_cfdictionary_hash_cb(const void *v)
-{
- return (CFHashCode)rb_any_hash((VALUE)v);
-}
-
-const void *
-rb_cfdictionary_retain_cb(CFAllocatorRef allocator, const void *v)
-{
- rb_objc_retain(v);
- return v;
-}
-
-void
-rb_cfdictionary_release_cb(CFAllocatorRef allocator, const void *v)
-{
- rb_objc_release(v);
-}
-
/* TODO optimize me */
struct rb_objc_hash_struct {
VALUE ifnone;
@@ -316,57 +138,46 @@
GC_WB(&s->ifnone, ifnone);
s->has_proc_default = has_proc_default;
}
-#endif
static VALUE
hash_alloc(VALUE klass)
{
-#if WITH_OBJC
- CFDictionaryKeyCallBacks keys_cb;
- CFDictionaryValueCallBacks values_cb;
- VALUE hash;
+ CFMutableDictionaryRef hash;
- memset(&keys_cb, 0, sizeof(keys_cb));
- keys_cb.retain = rb_cfdictionary_retain_cb;
- keys_cb.release = rb_cfdictionary_release_cb;
- keys_cb.equal = rb_cfdictionary_equal_cb;
- keys_cb.hash = rb_cfdictionary_hash_cb;
+ hash = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (klass != 0 && klass != rb_cNSHash && klass != rb_cNSMutableHash)
+ *(Class *)hash = (Class)klass;
- memset(&values_cb, 0, sizeof(values_cb));
- values_cb.retain = rb_cfdictionary_retain_cb;
- values_cb.release = rb_cfdictionary_release_cb;
- values_cb.equal = rb_cfdictionary_equal_cb;
+ CFMakeCollectable(hash);
- hash = (VALUE)CFDictionaryCreateMutable(NULL, 0, &keys_cb, &values_cb);
- if (klass != 0 && klass != rb_cHash && klass != rb_cHashRuby)
- *(Class *)hash = RCLASS_OCID(klass);
+ return (VALUE)hash;
+}
- CFMakeCollectable((CFTypeRef)hash);
- rb_gc_malloc_increase(sizeof(void *));
+VALUE
+rb_hash_dup(VALUE rcv)
+{
+ VALUE dup = (VALUE)CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)rcv);
+ if (OBJ_TAINTED(rcv))
+ OBJ_TAINT(dup);
+ CFMakeCollectable((CFTypeRef)dup);
+ return dup;
+}
- return hash;
-#else
- NEWOBJ(hash, struct RHash);
- OBJSETUP(hash, klass, T_HASH);
-
- hash->ifnone = Qnil;
-
- return (VALUE)hash;
-#endif
+static VALUE
+rb_hash_clone(VALUE rcv)
+{
+ VALUE clone = rb_hash_dup(rcv);
+ if (OBJ_FROZEN(rcv))
+ OBJ_FREEZE(clone);
+ return clone;
}
VALUE
rb_hash_new(void)
{
-#if WITH_OBJC
return hash_alloc(0);
-#else
- return hash_alloc(rb_cHash);
-#endif
}
-#if WITH_OBJC
-
static inline void
rb_hash_modify_check(VALUE hash)
{
@@ -385,34 +196,6 @@
#define rb_hash_modify rb_hash_modify_check
-#else
-
-static void
-rb_hash_modify_check(VALUE hash)
-{
- if (OBJ_FROZEN(hash)) rb_error_frozen("hash");
- if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4)
- rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
-}
-
-struct st_table *
-rb_hash_tbl(VALUE hash)
-{
- if (!RHASH(hash)->ntbl) {
- GC_WB(&RHASH(hash)->ntbl, st_init_table(&objhash));
- }
- return RHASH(hash)->ntbl;
-}
-
-static void
-rb_hash_modify(VALUE hash)
-{
- rb_hash_modify_check(hash);
- rb_hash_tbl(hash);
-}
-#endif
-
-
/*
* call-seq:
* Hash.new => hash
@@ -453,26 +236,18 @@
{
VALUE ifnone;
- rb_hash_modify(hash);
+ hash = (VALUE)objc_msgSend((id)hash, selInit);
+
if (rb_block_given_p()) {
if (argc > 0) {
rb_raise(rb_eArgError, "wrong number of arguments");
}
-#if WITH_OBJC
rb_objc_hash_set_struct(hash, rb_block_proc(), true);
-#else
- RHASH(hash)->ifnone = rb_block_proc();
- FL_SET(hash, HASH_PROC_DEFAULT);
-#endif
}
else {
rb_scan_args(argc, argv, "01", &ifnone);
-#if WITH_OBJC
if (ifnone != Qnil)
rb_objc_hash_set_struct(hash, ifnone, false);
-#else
- RHASH(hash)->ifnone = ifnone;
-#endif
}
return hash;
@@ -500,7 +275,6 @@
if (argc == 1) {
tmp = rb_hash_s_try_convert(Qnil, argv[0]);
if (!NIL_P(tmp)) {
-#if WITH_OBJC
CFIndex i, count;
const void **keys;
const void **values;
@@ -517,16 +291,9 @@
for (i = 0; i < count; i++)
CFDictionarySetValue((CFMutableDictionaryRef)hash,
- keys[i], values[i]);
+ RB2OC(keys[i]), RB2OC(values[i]));
return hash;
-#else
- hash = hash_alloc(klass);
- if (RHASH(argv[0])->ntbl) {
- GC_WB(&RHASH(hash)->ntbl, st_copy(RHASH(argv[0])->ntbl));
- }
-#endif
- return hash;
}
tmp = rb_check_array_type(argv[0]);
@@ -579,15 +346,6 @@
return rb_check_convert_type(hash, T_HASH, "Hash", "to_hash");
}
-#if !WITH_OBJC
-static int
-rb_hash_rehash_i(VALUE key, VALUE value, st_table *tbl)
-{
- if (key != Qundef) st_insert(tbl, key, value);
- return ST_CONTINUE;
-}
-#endif
-
/*
* call-seq:
* hsh.rehash -> hsh
@@ -611,7 +369,6 @@
static VALUE
rb_hash_rehash(VALUE hash)
{
-#if WITH_OBJC
CFIndex i, count;
const void **keys;
const void **values;
@@ -633,22 +390,6 @@
(const void *)keys[i], (const void *)values[i]);
return hash;
-#else
- st_table *tbl;
-
- if (RHASH(hash)->iter_lev > 0) {
- rb_raise(rb_eRuntimeError, "rehash during iteration");
- }
- rb_hash_modify_check(hash);
- if (!RHASH(hash)->ntbl)
- return hash;
- tbl = st_init_table_with_size(RHASH(hash)->ntbl->type, RHASH(hash)->ntbl->num_entries);
- rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl);
- st_free_table(RHASH(hash)->ntbl);
- GC_WB(&RHASH(hash)->ntbl, tbl);
-
- return hash;
-#endif
}
/*
@@ -670,16 +411,11 @@
{
VALUE val;
-#if WITH_OBJC
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
(const void **)&val)) {
return rb_funcall(hash, id_default, 1, key);
}
-#else
- if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
- return rb_funcall(hash, id_default, 1, key);
- }
-#endif
+ val = OC2RB(val);
return val;
}
@@ -688,16 +424,11 @@
{
VALUE val;
-#if WITH_OBJC
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
(const void **)&val)) {
return Qnil;
}
-#else
- if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
- return Qnil; /* without Hash#default */
- }
-#endif
+ val = OC2RB(val);
return val;
}
@@ -743,19 +474,15 @@
if (block_given && argc == 2) {
rb_warn("block supersedes default value argument");
}
-#if WITH_OBJC
- if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)key,
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)hash, (const void *)RB2OC(key),
(const void **)&val)) {
-#else
- if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
-#endif
if (block_given) return rb_yield(key);
if (argc == 1) {
rb_raise(rb_eKeyError, "key not found");
}
return if_none;
}
- return val;
+ return OC2RB(val);
}
/*
@@ -782,7 +509,6 @@
static VALUE
rb_hash_default(int argc, VALUE *argv, VALUE hash)
{
-#if WITH_OBJC
struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
VALUE key;
@@ -795,16 +521,6 @@
return rb_funcall(s->ifnone, id_yield, 2, hash, key);
}
return s->ifnone;
-#else
- VALUE key;
-
- rb_scan_args(argc, argv, "01", &key);
- if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- if (argc == 0) return Qnil;
- return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, key);
- }
- return RHASH(hash)->ifnone;
-#endif
}
/*
@@ -831,12 +547,7 @@
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
rb_hash_modify(hash);
-#if WITH_OBJC
rb_objc_hash_set_struct(hash, ifnone, false);
-#else
- RHASH(hash)->ifnone = ifnone;
- FL_UNSET(hash, HASH_PROC_DEFAULT);
-#endif
return ifnone;
}
@@ -858,17 +569,10 @@
static VALUE
rb_hash_default_proc(VALUE hash)
{
-#if WITH_OBJC
struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash);
if (s != NULL && s->has_proc_default)
return s->ifnone;
return Qnil;
-#else
- if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- return RHASH(hash)->ifnone;
- }
- return Qnil;
-#endif
}
static int
@@ -917,30 +621,15 @@
static VALUE
rb_hash_delete_key(VALUE hash, VALUE key)
{
-#if WITH_OBJC
VALUE val;
+ id ockey = RB2OC(key);
if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)key, (const void **)&val)) {
+ (const void *)ockey, (const void **)&val)) {
CFDictionaryRemoveValue((CFMutableDictionaryRef)hash,
- (const void *)key);
- return val;
+ (const void *)ockey);
+ return OC2RB(val);
}
return Qundef;
-#else
- st_data_t ktmp = (st_data_t)key, val;
-
- if (!RHASH(hash)->ntbl)
- return Qundef;
- if (RHASH(hash)->iter_lev > 0) {
- if (st_delete_safe(RHASH(hash)->ntbl, &ktmp, &val, Qundef)) {
- FL_SET(hash, HASH_DELETED);
- return (VALUE)val;
- }
- }
- else if (st_delete(RHASH(hash)->ntbl, &ktmp, &val))
- return (VALUE)val;
- return Qundef;
-#endif
}
/*
@@ -975,32 +664,6 @@
return Qnil;
}
-#if !WITH_OBJC
-struct shift_var {
- VALUE key;
- VALUE val;
-};
-
-static int
-shift_i(VALUE key, VALUE value, struct shift_var *var)
-{
- if (key == Qundef) return ST_CONTINUE;
- if (var->key != Qundef) return ST_STOP;
- var->key = key;
- var->val = value;
- return ST_DELETE;
-}
-
-static int
-shift_i_safe(VALUE key, VALUE value, struct shift_var *var)
-{
- if (key == Qundef) return ST_CONTINUE;
- var->key = key;
- var->val = value;
- return ST_STOP;
-}
-#endif
-
/*
* call-seq:
* hsh.shift -> anArray or obj
@@ -1014,14 +677,11 @@
* h #=> {2=>"b", 3=>"c"}
*/
-#if WITH_OBJC
static VALUE rb_hash_keys(VALUE);
-#endif
static VALUE
rb_hash_shift(VALUE hash)
{
-#if WITH_OBJC
VALUE keys, key, val;
keys = rb_hash_keys(hash);
@@ -1041,27 +701,6 @@
rb_hash_delete(hash, key);
return rb_assoc_new(key, val);
-#else
- struct shift_var var;
-
- rb_hash_modify(hash);
- var.key = Qundef;
- rb_hash_foreach(hash, RHASH(hash)->iter_lev > 0 ? shift_i_safe : shift_i,
- (st_data_t)&var);
-
- if (var.key != Qundef) {
- if (RHASH(hash)->iter_lev > 0) {
- rb_hash_delete_key(hash, var.key);
- }
- return rb_assoc_new(var.key, var.val);
- }
- else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
- return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, Qnil);
- }
- else {
- return RHASH(hash)->ifnone;
- }
-#endif
}
static int
@@ -1106,7 +745,6 @@
VALUE
rb_hash_reject_bang(VALUE hash)
{
-#if WITH_OBJC
CFIndex n;
RETURN_ENUMERATOR(hash, 0, 0);
@@ -1115,17 +753,6 @@
if (n == CFDictionaryGetCount((CFDictionaryRef)hash))
return Qnil;
return hash;
-#else
- int n;
-
- RETURN_ENUMERATOR(hash, 0, 0);
- if (!RHASH(hash)->ntbl)
- return Qnil;
- n = RHASH(hash)->ntbl->num_entries;
- rb_hash_delete_if(hash);
- if (n == RHASH(hash)->ntbl->num_entries) return Qnil;
- return hash;
-#endif
}
/*
@@ -1198,14 +825,6 @@
return result;
}
-#if !WITH_OBJC
-static int
-clear_i(VALUE key, VALUE value, VALUE dummy)
-{
- return ST_DELETE;
-}
-#endif
-
/*
* call-seq:
* hsh.clear -> hsh
@@ -1221,18 +840,7 @@
rb_hash_clear(VALUE hash)
{
rb_hash_modify_check(hash);
-#if WITH_OBJC
CFDictionaryRemoveAllValues((CFMutableDictionaryRef)hash);
-#else
- if (!RHASH(hash)->ntbl)
- return hash;
- if (RHASH(hash)->ntbl->num_entries > 0) {
- if (RHASH(hash)->iter_lev > 0)
- rb_hash_foreach(hash, clear_i, 0);
- else
- st_clear(RHASH(hash)->ntbl);
- }
-#endif
return hash;
}
@@ -1259,18 +867,8 @@
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
rb_hash_modify(hash);
-#if WITH_OBJC
- CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)key,
- (const void *)val);
-#else
- if (RHASH(hash)->ntbl->type == &identhash ||
- TYPE(key) != T_STRING || st_lookup(RHASH(hash)->ntbl, key, 0)) {
- st_insert(RHASH(hash)->ntbl, key, val);
- }
- else {
- st_add_direct(RHASH(hash)->ntbl, rb_str_new4(key), val);
- }
-#endif
+ CFDictionarySetValue((CFMutableDictionaryRef)hash, (const void *)RB2OC(key),
+ (const void *)RB2OC(val));
return val;
}
@@ -1303,21 +901,11 @@
if (hash == hash2) return hash;
rb_hash_clear(hash);
rb_hash_foreach(hash2, replace_i, hash);
-#if WITH_OBJC
{
struct rb_objc_hash_struct *s = rb_objc_hash_get_struct(hash2);
if (s != NULL)
rb_objc_hash_set_struct(hash, s->ifnone, s->has_proc_default);
}
-#else
- RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
- if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
- FL_SET(hash, HASH_PROC_DEFAULT);
- }
- else {
- FL_UNSET(hash, HASH_PROC_DEFAULT);
- }
-#endif
return hash;
}
@@ -1338,13 +926,7 @@
static VALUE
rb_hash_size(VALUE hash)
{
-#if WITH_OBJC
return INT2FIX(CFDictionaryGetCount((CFDictionaryRef)hash));
-#else
- if (!RHASH(hash)->ntbl)
- return INT2FIX(0);
- return INT2FIX(RHASH(hash)->ntbl->num_entries);
-#endif
}
@@ -1503,15 +1085,9 @@
}
str2 = rb_inspect(key);
rb_str_buf_append(str, str2);
-#if !WITH_OBJC
- OBJ_INFECT(str, str2);
-#endif
rb_str_buf_cat2(str, "=>");
str2 = rb_inspect(value);
rb_str_buf_append(str, str2);
-#if !WITH_OBJC
- OBJ_INFECT(str, str2);
-#endif
return ST_CONTINUE;
}
@@ -1642,33 +1218,12 @@
static VALUE
rb_hash_has_key(VALUE hash, VALUE key)
{
-#if WITH_OBJC
- if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)key))
+ if (CFDictionaryContainsKey((CFDictionaryRef)hash, (const void *)RB2OC(key)))
return Qtrue;
-#else
- if (!RHASH(hash)->ntbl)
- return Qfalse;
- if (st_lookup(RHASH(hash)->ntbl, key, 0)) {
- return Qtrue;
- }
-#endif
return Qfalse;
}
-#if !WITH_OBJC
-static int
-rb_hash_search_value(VALUE key, VALUE value, VALUE *data)
-{
- if (key == Qundef) return ST_CONTINUE;
- if (rb_equal(value, data[1])) {
- data[0] = Qtrue;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-#endif
-
/*
* call-seq:
* hsh.has_value?(value) => true or false
@@ -1685,58 +1240,11 @@
static VALUE
rb_hash_has_value(VALUE hash, VALUE val)
{
-#if WITH_OBJC
- return CFDictionaryContainsValue((CFDictionaryRef)hash, (const void *)val)
+ return CFDictionaryContainsValue((CFDictionaryRef)hash, (const void *)RB2OC(val))
? Qtrue : Qfalse;
-#else
- VALUE data[2];
-
- data[0] = Qfalse;
- data[1] = val;
- rb_hash_foreach(hash, rb_hash_search_value, (st_data_t)data);
- return data[0];
-#endif
}
-#if !WITH_OBJC
-struct equal_data {
- VALUE result;
- st_table *tbl;
- int eql;
-};
-
-static int
-eql_i(VALUE key, VALUE val1, struct equal_data *data)
-{
- VALUE val2;
-
- if (key == Qundef) return ST_CONTINUE;
- if (!st_lookup(data->tbl, key, &val2)) {
- data->result = Qfalse;
- return ST_STOP;
- }
- if (!(data->eql ? rb_eql(val1, val2) : rb_equal(val1, val2))) {
- data->result = Qfalse;
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
static VALUE
-recursive_eql(VALUE hash, VALUE dt, int recur)
-{
- struct equal_data *data;
-
- if (recur) return Qfalse;
- data = (struct equal_data*)dt;
- data->result = Qtrue;
- rb_hash_foreach(hash, eql_i, (st_data_t)data);
-
- return data->result;
-}
-#endif
-
-static VALUE
hash_equal(VALUE hash1, VALUE hash2, int eql)
{
if (hash1 == hash2) return Qtrue;
@@ -1751,23 +1259,7 @@
}
if (RHASH_SIZE(hash1) != RHASH_SIZE(hash2))
return Qfalse;
-#if WITH_OBJC
return CFEqual((CFTypeRef)hash1, (CFTypeRef)hash2) ? Qtrue : Qfalse;
-#else
- if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
- return Qtrue;
- if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
- return Qfalse;
-#if 0
- if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
- FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
- return Qfalse;
-#endif
-
- data.tbl = RHASH(hash2)->ntbl;
- data.eql = eql;
- return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
-#endif
}
/*
@@ -1809,50 +1301,7 @@
return hash_equal(hash1, hash2, Qtrue);
}
-#if !WITH_OBJC
static int
-hash_i(VALUE key, VALUE val, int *hval)
-{
- if (key == Qundef) return ST_CONTINUE;
- *hval ^= rb_hash(key);
- *hval *= 137;
- *hval ^= rb_hash(val);
- return ST_CONTINUE;
-}
-
-static VALUE
-recursive_hash(VALUE hash, VALUE dummy, int recur)
-{
- int hval;
-
- if (recur) {
- return LONG2FIX(0);
- }
- if (!RHASH(hash)->ntbl)
- return LONG2FIX(0);
- hval = RHASH(hash)->ntbl->num_entries;
- rb_hash_foreach(hash, hash_i, (st_data_t)&hval);
- return INT2FIX(hval);
-}
-#endif
-
-/*
- * call-seq:
- * array.hash -> fixnum
- *
- * Compute a hash-code for this array. Two arrays with the same content
- * will have the same hash code (and will compare using <code>eql?</code>).
- */
-
-#if !WITH_OBJC
-static VALUE
-rb_hash_hash(VALUE hash)
-{
- return rb_exec_recursive(recursive_hash, hash, 0);
-}
-#endif
-
-static int
rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
{
if (key == Qundef) return ST_CONTINUE;
@@ -1955,7 +1404,7 @@
static VALUE
rb_hash_merge(VALUE hash1, VALUE hash2)
{
- return rb_hash_update(rb_obj_dup(hash1), hash2);
+ return rb_hash_update(rb_hash_dup(hash1), hash2);
}
static int
@@ -2080,12 +1529,7 @@
rb_hash_compare_by_id(VALUE hash)
{
rb_hash_modify(hash);
-#if WITH_OBJC
HASH_KEY_CALLBACKS(hash)->equal = NULL;
-#else
- RHASH(hash)->ntbl->type = &identhash;
- rb_hash_rehash(hash);
-#endif
return hash;
}
@@ -2101,37 +1545,16 @@
static VALUE
rb_hash_compare_by_id_p(VALUE hash)
{
-#if WITH_OBJC
return HASH_KEY_CALLBACKS(hash)->equal == NULL ? Qtrue : Qfalse;
-#else
- if (!RHASH(hash)->ntbl)
- return Qfalse;
- if (RHASH(hash)->ntbl->type == &identhash) {
- return Qtrue;
- }
- return Qfalse;
-#endif
}
static int path_tainted = -1;
static char **origenviron;
-#ifdef _WIN32
-#define GET_ENVIRON(e) (e = rb_w32_get_environ())
-#define FREE_ENVIRON(e) rb_w32_free_environ(e)
-static char **my_environ;
#undef environ
-#define environ my_environ
-#elif defined(__APPLE__)
-#undef environ
#define environ (*_NSGetEnviron())
#define GET_ENVIRON(e) (e)
#define FREE_ENVIRON(e)
-#else
-extern char **environ;
-#define GET_ENVIRON(e) (e)
-#define FREE_ENVIRON(e)
-#endif
static VALUE
env_str_new(const char *ptr, long len)
@@ -2267,107 +1690,15 @@
return path_tainted;
}
-#if !defined(_WIN32) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV))
-static int
-envix(const char *nam)
-{
- register int i, len = strlen(nam);
- char **env;
-
- env = GET_ENVIRON(environ);
- for (i = 0; env[i]; i++) {
- if (
-#ifdef ENV_IGNORECASE
- STRNCASECMP(env[i],nam,len) == 0
-#else
- memcmp(env[i],nam,len) == 0
-#endif
- && env[i][len] == '=')
- break; /* memcmp must come first to avoid */
- } /* potential SEGV's */
- FREE_ENVIRON(environ);
- return i;
-}
-#endif
-
void
ruby_setenv(const char *name, const char *value)
{
-#if defined(_WIN32)
- /* The sane way to deal with the environment.
- * Has these advantages over putenv() & co.:
- * * enables us to store a truly empty value in the
- * environment (like in UNIX).
- * * we don't have to deal with RTL globals, bugs and leaks.
- * * Much faster.
- * Why you may want to enable USE_WIN32_RTL_ENV:
- * * environ[] and RTL functions will not reflect changes,
- * which might be an issue if extensions want to access
- * the env. via RTL. This cuts both ways, since RTL will
- * not see changes made by extensions that call the Win32
- * functions directly, either.
- * GSAR 97-06-07
- *
- * REMARK: USE_WIN32_RTL_ENV is already obsoleted since we don't use
- * RTL's environ global variable directly yet.
- */
- SetEnvironmentVariable(name,value);
-#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
#undef setenv
#undef unsetenv
if (value)
setenv(name,value,1);
else
unsetenv(name);
-#else /* WIN32 */
- size_t len;
- int i=envix(name); /* where does it go? */
-
- if (environ == origenviron) { /* need we copy environment? */
- int j;
- int max;
- char **tmpenv;
-
- for (max = i; environ[max]; max++) ;
- tmpenv = ALLOC_N(char*, max+2);
- for (j=0; j<max; j++) /* copy environment */
- tmpenv[j] = strdup(environ[j]);
- tmpenv[max] = 0;
- environ = tmpenv; /* tell exec where it is now */
- }
- if (environ[i]) {
- char **envp = origenviron;
- while (*envp && *envp != environ[i]) envp++;
- if (!*envp)
- free(environ[i]);
- if (!value) {
- while (environ[i]) {
- environ[i] = environ[i+1];
- i++;
- }
- return;
- }
- }
- else { /* does not exist yet */
- if (!value) return;
- REALLOC_N(environ, char*, i+2); /* just expand it a bit */
- environ[i+1] = 0; /* make sure it's null terminated */
- }
- len = strlen(name) + strlen(value) + 2;
- environ[i] = ALLOC_N(char, len);
-#ifndef MSDOS
- snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
-#else
- /* MS-DOS requires environment variable names to be in uppercase */
- /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
- * some utilities and applications may break because they only look
- * for upper case strings. (Fixed strupr() bug here.)]
- */
- strcpy(environ[i],name); strupr(environ[i]);
- sprintf(environ[i] + strlen(name),"=%s", value);
-#endif /* MSDOS */
-
-#endif /* WIN32 */
}
void
@@ -2903,26 +2234,9 @@
return env;
}
-/*
- * A <code>Hash</code> is a collection of key-value pairs. It is
- * similar to an <code>Array</code>, except that indexing is done via
- * arbitrary keys of any object type, not an integer index. The order
- * in which you traverse a hash by either key or value may seem
- * arbitrary, and will generally not be in the insertion order.
- *
- * Hashes have a <em>default value</em> that is returned when accessing
- * keys that do not exist in the hash. By default, that value is
- * <code>nil</code>.
- *
- */
-
-#if WITH_OBJC
-
-#define NSCFDICTIONARY() RCLASS_OCID(rb_cCFHash)
-
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFDICTIONARY();
+ *(Class *)x = (Class)rb_cCFHash;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -2930,7 +2244,7 @@
bool
rb_objc_hash_is_pure(VALUE ary)
{
- return *(Class *)ary == NSCFDICTIONARY();
+ return *(Class *)ary == (Class)rb_cCFHash;
}
static CFIndex
@@ -3046,10 +2360,24 @@
INSTALL_METHOD("isEqual:", imp_rb_hash_isEqual);
INSTALL_METHOD("containsObject:", imp_rb_hash_containsObject);
+ rb_define_alloc_func((VALUE)klass, hash_alloc);
+
#undef INSTALL_METHOD
}
-#endif
+/*
+ * A <code>Hash</code> is a collection of key-value pairs. It is
+ * similar to an <code>Array</code>, except that indexing is done via
+ * arbitrary keys of any object type, not an integer index. The order
+ * in which you traverse a hash by either key or value may seem
+ * arbitrary, and will generally not be in the insertion order.
+ *
+ * Hashes have a <em>default value</em> that is returned when accessing
+ * keys that do not exist in the hash. By default, that value is
+ * <code>nil</code>.
+ *
+ */
+
void
Init_Hash(void)
{
@@ -3057,19 +2385,18 @@
id_yield = rb_intern("yield");
id_default = rb_intern("default");
-#if WITH_OBJC
- rb_cCFHash = rb_objc_import_class((Class)objc_getClass("NSCFDictionary"));
- rb_cHash = rb_objc_import_class((Class)objc_getClass("NSDictionary"));
- rb_cHashRuby = rb_objc_import_class((Class)objc_getClass("NSMutableDictionary"));
- FL_UNSET(rb_cHashRuby, RCLASS_OBJC_IMPORTED);
- rb_const_set(rb_cObject, rb_intern("Hash"), rb_cHashRuby);
-#else
- rb_cHash = rb_define_class("Hash", rb_cObject);
-#endif
+ rb_cCFHash = (VALUE)objc_getClass("NSCFDictionary");
+ rb_cHash = rb_cNSHash = (VALUE)objc_getClass("NSDictionary");
+ rb_cNSMutableHash = (VALUE)objc_getClass("NSMutableDictionary");
+ rb_set_class_path(rb_cNSMutableHash, rb_cObject, "NSMutableDictionary");
+ rb_const_set(rb_cObject, rb_intern("Hash"), rb_cNSMutableHash);
rb_include_module(rb_cHash, rb_mEnumerable);
- rb_define_alloc_func(rb_cHash, hash_alloc);
+ /* to return mutable copies */
+ rb_define_method(rb_cHash, "dup", rb_hash_dup, 0);
+ rb_define_method(rb_cHash, "clone", rb_hash_clone, 0);
+
rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
@@ -3083,9 +2410,6 @@
rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
-#if !WITH_OBJC
- rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
-#endif
rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
@@ -3116,6 +2440,10 @@
rb_define_method(rb_cHash,"reject!", rb_hash_reject_bang, 0);
rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
+
+ /* to override the private -[NSMutableDictionary invert] method */
+ rb_define_method(rb_cNSMutableHash,"invert", rb_hash_invert, 0);
+
rb_define_method(rb_cHash,"update", rb_hash_update, 1);
rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
rb_define_method(rb_cHash,"merge!", rb_hash_update, 1);
@@ -3134,7 +2462,6 @@
rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
-#ifndef __MACOS__ /* environment variables nothing on MacOS. */
origenviron = environ;
envtbl = rb_obj_alloc(rb_cObject);
rb_extend_object(envtbl, rb_mEnumerable);
@@ -3180,8 +2507,4 @@
rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
rb_define_global_const("ENV", envtbl);
-#else /* __MACOS__ */
- envtbl = rb_hash_s_new(0, NULL, rb_cHash);
- rb_define_global_const("ENV", envtbl);
-#endif /* ifndef __MACOS__ environment variables nothing on MacOS. */
}
Modified: MacRuby/trunk/id.c
===================================================================
--- MacRuby/trunk/id.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/id.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -40,6 +40,31 @@
idNot = rb_intern("!");
idNeq = rb_intern("!=");
+#if WITH_OBJC
+ selPLUS = sel_registerName("+:");
+ selMINUS = sel_registerName("-:");
+ selMULT = sel_registerName("*:");
+ selDIV = sel_registerName("/:");
+ selMOD = sel_registerName("%:");
+ selEq = sel_registerName("==:");
+ selNeq = sel_registerName("!=:");
+ selLT = sel_registerName("<:");
+ selLE = sel_registerName("<=:");
+ selGT = sel_registerName(">:");
+ selGE = sel_registerName(">=:");
+ selLTLT = sel_registerName("<<:");
+ selAREF = sel_registerName("[]:");
+ selASET = sel_registerName("[]=:");
+ selLength = sel_registerName("length");
+ selSucc = sel_registerName("succ");
+ selNot = sel_registerName("!");
+ selInit = sel_registerName("init");
+ selCopy = sel_registerName("copy");
+ sel_ignored = sel_registerName("retain");
+ assert(sel_ignored == sel_registerName("release"));
+ sel_zone = sel_registerName("zone");
+#endif
+
idAREF = rb_intern("[]");
idASET = rb_intern("[]=");
@@ -66,4 +91,7 @@
idRespond_to = rb_intern("respond_to?");
idInitialize = rb_intern("initialize");
+
+ idIncludedModules = rb_intern("__included_modules__");
+ idIncludedInClasses = rb_intern("__included_in_classes__");
}
Modified: MacRuby/trunk/id.h
===================================================================
--- MacRuby/trunk/id.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/id.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -52,4 +52,29 @@
extern ID id__send__;
extern ID idRespond_to;
extern ID idInitialize;
+#if WITH_OBJC
+extern SEL selPLUS;
+extern SEL selMINUS;
+extern SEL selMULT;
+extern SEL selDIV;
+extern SEL selMOD;
+extern SEL selEq;
+extern SEL selNeq;
+extern SEL selLT;
+extern SEL selLE;
+extern SEL selGT;
+extern SEL selGE;
+extern SEL selLTLT;
+extern SEL selAREF;
+extern SEL selASET;
+extern SEL selLength;
+extern SEL selSucc;
+extern SEL selNot;
+extern SEL selInit;
+extern SEL selCopy;
+extern SEL sel_ignored;
+extern SEL sel_zone;
+extern ID idIncludedModules;
+extern ID idIncludedInClasses;
+#endif
#endif /* RUBY_ID_H */
Modified: MacRuby/trunk/include/ruby/defines.h
===================================================================
--- MacRuby/trunk/include/ruby/defines.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/defines.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -296,7 +296,7 @@
void rb_objc_wb(void *dst, void *newval);
void rb_objc_wb_range(void *dest, size_t len);
void rb_objc_root(void *addr);
-# define GC_WB(dst, newval) (rb_objc_wb((void *)dst, (void *)newval))
+# define GC_WB(dst, newval) (SPECIAL_CONST_P(newval) ? *(void **)dst = (void *)newval : rb_objc_wb((void *)dst, (void *)newval))
# define GC_ROOT(dst) (rb_objc_root((void *)dst))
# define GC_WEAK(dst) (rb_objc_weak((void *)dst))
#else
Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/intern.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -77,6 +77,7 @@
VALUE rb_ary_cmp(VALUE, VALUE);
VALUE rb_ary_replace(VALUE copy, VALUE orig);
VALUE rb_get_values_at(VALUE, long, int, VALUE*, VALUE(*)(VALUE,long));
+void rb_ary_insert(VALUE, long, VALUE);
#if WITH_OBJC
VALUE rb_ary_elt(VALUE, long);
bool rb_objc_ary_is_pure(VALUE);
@@ -147,10 +148,9 @@
#define rb_Complex2(x,y) rb_Complex(x, y)
/* class.c */
#if WITH_OBJC
-VALUE rb_objc_import_class(Class);
VALUE rb_objc_create_class(const char *name, VALUE super);
-VALUE rb_objc_rename_class(VALUE klass, const char *name);
bool rb_objc_install_primitives(Class ocklass, Class ocsuper);
+void rb_define_object_special_methods(VALUE klass);
#endif
VALUE rb_class_boot(VALUE);
VALUE rb_class_new(VALUE);
@@ -279,7 +279,7 @@
void rb_provide(const char*);
VALUE rb_f_require(VALUE, VALUE);
VALUE rb_require_safe(VALUE, int);
-void rb_obj_call_init(VALUE, int, VALUE*);
+VALUE rb_obj_call_init(VALUE, int, VALUE*);
VALUE rb_class_new_instance(int, VALUE*, VALUE);
VALUE rb_block_proc(void);
VALUE rb_f_lambda(void);
@@ -691,6 +691,7 @@
VALUE rb_mod_remove_cvar(VALUE, VALUE);
/* objc.m */
#if WITH_OBJC
+void rb_objc_alias(VALUE, ID, ID);
VALUE rb_mod_objc_ancestors(VALUE);
VALUE rb_mod_objc_ib_outlet(int, VALUE *, VALUE);
VALUE rb_require_framework(int, VALUE *, VALUE);
@@ -700,9 +701,9 @@
void rb_objc_flag_set(const void *, int, bool);
bool rb_objc_flag_check(const void *, int);
long rb_objc_remove_flags(const void *obj);
-void rb_objc_sync_ruby_methods(VALUE, VALUE);
void rb_objc_methods(VALUE, Class);
bool rb_objc_is_immutable(VALUE);
+VALUE rb_objc_call(VALUE, SEL, int, VALUE *);
#endif
/* version.c */
void ruby_show_version(void);
Modified: MacRuby/trunk/include/ruby/node.h
===================================================================
--- MacRuby/trunk/include/ruby/node.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/node.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -507,7 +507,10 @@
void rb_add_method(VALUE, ID, NODE *, int);
void rb_add_method_direct(VALUE, ID, NODE *);
#if WITH_OBJC
-NODE *rb_objc_define_objc_mid_closure(VALUE, ID, ID);
+void rb_objc_register_ruby_method(VALUE, ID, NODE *);
+NODE *rb_objc_method_node(VALUE, ID, IMP *, SEL *);
+NODE *rb_objc_method_node2(VALUE, SEL, IMP *);
+NODE *rb_objc_method_node3(IMP);
#endif
NODE *rb_node_newnode(enum node_type,VALUE,VALUE,VALUE);
Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/include/ruby/ruby.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -229,9 +229,15 @@
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
-#define SYMBOL_P(x) (((VALUE)(x)&~(~(VALUE)0<<RUBY_SPECIAL_SHIFT))==SYMBOL_FLAG)
-#define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
-#define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
+#if WITH_OBJC
+# define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
+# define ID2SYM(x) (rb_id2str((ID)x))
+# define SYM2ID(x) (RSYMBOL(x)->id)
+#else
+# define SYMBOL_P(x) (((VALUE)(x)&~(~(VALUE)0<<RUBY_SPECIAL_SHIFT))==SYMBOL_FLAG)
+# define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
+# define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
+#endif
/* special contants - i.e. non-zero and non-fixnum constants */
enum ruby_special_consts {
@@ -242,7 +248,9 @@
RUBY_IMMEDIATE_MASK = 0x03,
RUBY_FIXNUM_FLAG = 0x01,
+#if !WITH_OBJC
RUBY_SYMBOL_FLAG = 0x0e,
+#endif
RUBY_SPECIAL_SHIFT = 8,
};
@@ -252,7 +260,9 @@
#define Qundef ((VALUE)RUBY_Qundef) /* undefined value for placeholder */
#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK
#define FIXNUM_FLAG RUBY_FIXNUM_FLAG
-#define SYMBOL_FLAG RUBY_SYMBOL_FLAG
+#if !WITH_OBJC
+# define SYMBOL_FLAG RUBY_SYMBOL_FLAG
+#endif
#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
#define NIL_P(v) ((VALUE)(v) == Qnil)
@@ -283,6 +293,9 @@
RUBY_T_FALSE = 0x13,
RUBY_T_SYMBOL = 0x14,
RUBY_T_FIXNUM = 0x15,
+#if WITH_OBJC
+ RUBY_T_NATIVE = 0x16,
+#endif
RUBY_T_UNDEF = 0x1b,
RUBY_T_NODE = 0x1c,
@@ -306,6 +319,9 @@
#define T_BIGNUM RUBY_T_BIGNUM
#define T_FILE RUBY_T_FILE
#define T_FIXNUM RUBY_T_FIXNUM
+#if WITH_OBJC
+# define T_NATIVE RUBY_T_NATIVE
+#endif
#define T_TRUE RUBY_T_TRUE
#define T_FALSE RUBY_T_FALSE
#define T_DATA RUBY_T_DATA
@@ -416,20 +432,11 @@
#else
# define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
#endif
-#define __OBJSETUP(obj,c,t) do {\
+#define OBJSETUP(obj,c,t) do {\
RBASIC(obj)->flags = (t);\
RBASIC(obj)->klass = (c);\
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
} while (0)
-#if WITH_OBJC
-# define OBJSETUP(obj,c,t) do {\
- __OBJSETUP(obj,c,t);\
- if (c != 0) \
- RBASIC(obj)->isa = (void *)RCLASS_OCID(c); \
-} while (0)
-#else
-# define OBJSETUP(obj,c,t) __OBJSETUP(obj,c,t)
-#endif
#define CLONESETUP(clone,obj) do {\
OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
@@ -441,37 +448,34 @@
} while (0)
struct RBasic {
- void *isa;
+ VALUE klass; /* isa */
VALUE flags;
- VALUE klass;
};
-#define ROBJECT_EMBED_LEN_MAX 3
-struct RObject {
- struct RBasic basic;
+struct rb_ivars {
+#define RB_IVAR_ARY 0
+#define RB_IVAR_TBL 1
+#define RB_IVAR_TYPE(ivars) (ivars.type & 0x1)
+#define RB_IVAR_SET_TYPE(ivars, t) (ivars.type |= t)
+#define RB_IVAR_ARY_LEN(ivars) (ivars.type >> 1)
+#define RB_IVAR_ARY_SET_LEN(ivars, len) (ivars.type = (len << 1) | (ivars.type & 0x1))
+#define RB_IVAR_ARY_MAX 10
+ short type;
union {
- struct {
- long numiv;
- VALUE *ivptr;
- struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
- } heap;
- VALUE ary[ROBJECT_EMBED_LEN_MAX];
+ struct rb_ivar_ary_entry {
+ ID name;
+ VALUE value;
+ } *ary;
+ CFMutableDictionaryRef tbl;
} as;
};
-#define ROBJECT_EMBED FL_USER1
-#define ROBJECT_NUMIV(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT_EMBED_LEN_MAX : \
- ROBJECT(o)->as.heap.numiv)
-#define ROBJECT_IVPTR(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT(o)->as.ary : \
- ROBJECT(o)->as.heap.ivptr)
-#define ROBJECT_IV_INDEX_TBL(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
- ROBJECT(o)->as.heap.iv_index_tbl)
+struct RObject {
+ struct RBasic basic;
+ struct rb_ivars ivars;
+};
+
+#if !WITH_OBJC
typedef struct {
VALUE super;
struct st_table *iv_tbl;
@@ -484,17 +488,41 @@
struct st_table *m_tbl;
struct st_table *iv_index_tbl;
};
-#define RCLASS_IV_TBL(c) (RCLASS(c)->ptr->iv_tbl)
-#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
-#define RCLASS_SUPER(c) (RCLASS(c)->ptr->super)
-#define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
-#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
-#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
-#define RMODULE_SUPER(m) RCLASS_SUPER(m)
-#if WITH_OBJC
-# define RCLASS_ANONYMOUS FL_USER1
-# define RCLASS_OBJC_IMPORTED FL_USER2
-# define RCLASS_OCID(obj) ((Class)RCLASS(obj)->ocklass)
+# define RCLASS_IV_TBL(c) (RCLASS(c)->ptr->iv_tbl)
+# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+# define RCLASS_SUPER(c) (RCLASS(c)->ptr->super)
+# define RCLASS_IV_INDEX_TBL(c) (RCLASS(c)->iv_index_tbl)
+# define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
+# define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
+# define RMODULE_SUPER(m) RCLASS_SUPER(m)
+#else
+# define RCLASS_IS_OBJECT_SUBCLASS 0x100 /* class is a true RBObject subclass */
+# define RCLASS_IS_RUBY_CLASS 0x200 /* class was created from Ruby */
+# define RCLASS_IS_MODULE 0x400 /* class represents a Ruby Module */
+# define RCLASS_IS_SINGLETON 0x800 /* class represents a singleton */
+# define RCLASS_IS_FROZEN 0x1000 /* class is frozen */
+# define RCLASS_IS_TAINTED 0x2000 /* class is tainted */
+# define RCLASS_IS_STRING_SUBCLASS 0x10000 /* class is a subclass of NSCFString */
+# define RCLASS_IS_ARRAY_SUBCLASS 0x20000 /* class is a subclass of NSCFArray */
+# define RCLASS_IS_HASH_SUBCLASS 0x40000 /* class is a subclass of NSCFDictionary */
+# if __OBJC2__
+# define RCLASS_VERSION(m) (class_getVersion((Class)m))
+# define RCLASS_SET_VERSION_FLAG(m,f) (class_setVersion((Class)m, (RCLASS_VERSION(m) | f)))
+# define RCLASS_SUPER(m) (class_getSuperclass((Class)m))
+# define RCLASS_META(m) (class_isMetaclass((Class)m))
+# else
+# define RCLASS_VERSION(m) (*(long *)((void *)m + (sizeof(void *) * 3)))
+# define RCLASS_SET_VERSION_FLAG(m,f) (RCLASS_VERSION(m) |= f)
+# define RCLASS_SUPER(m) (*(VALUE *)((void *)m + (sizeof(void *) * 1)))
+# define _RCLASS_INFO(m) (*(long *)((void *)m + (sizeof(void *) * 4)))
+# define RCLASS_META(m) (_RCLASS_INFO(m) & CLS_META)
+# endif
+# define RCLASS_RUBY(m) ((RCLASS_VERSION(m) & RCLASS_IS_RUBY_CLASS) == RCLASS_IS_RUBY_CLASS)
+# define RCLASS_MODULE(m) ((RCLASS_VERSION(m) & RCLASS_IS_MODULE) == RCLASS_IS_MODULE)
+# define RCLASS_SINGLETON(m) ((RCLASS_VERSION(m) & RCLASS_IS_SINGLETON) == RCLASS_IS_SINGLETON)
+CFMutableDictionaryRef rb_class_ivar_dict(VALUE);
+CFMutableDictionaryRef rb_class_ivar_dict_or_create(VALUE);
+void rb_class_ivar_set_dict(VALUE, CFMutableDictionaryRef);
#endif
struct RFloat {
@@ -504,6 +532,20 @@
#define RFLOAT_VALUE(v) (RFLOAT(v)->float_value)
#define DOUBLE2NUM(dbl) rb_float_new(dbl)
+#if WITH_OBJC
+struct RFixnum {
+ VALUE klass;
+ long value;
+};
+
+struct RSymbol {
+ VALUE klass;
+ char *str;
+ unsigned int len;
+ ID id;
+};
+#endif
+
#define ELTS_SHARED FL_USER2
#if !WITH_OBJC
@@ -576,7 +618,6 @@
*/
const VALUE *rb_ary_ptr(VALUE);
# define RARRAY_PTR(a) (rb_ary_ptr((VALUE)a))
-# define RARRAY_AT(a,i) ((VALUE)CFArrayGetValueAtIndex((CFArrayRef)a, (long)i))
#endif
struct RRegexp {
@@ -710,12 +751,16 @@
#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
-#define RCLASS(obj) (R_CAST(RClass)(obj))
-#define RMODULE(obj) RCLASS(obj)
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
+#if WITH_OBJC
+# define RFIXNUM(obj) (R_CAST(RFixnum)(obj))
+# define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
+#endif
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
#if !WITH_OBJC
+# define RCLASS(obj) (R_CAST(RClass)(obj))
+# define RMODULE(obj) RCLASS(obj)
# define RSTRING(obj) (R_CAST(RString)(obj))
# define RARRAY(obj) (R_CAST(RArray)(obj))
# define RHASH(obj) (R_CAST(RHash)(obj))
@@ -771,7 +816,7 @@
#define FL_REVERSE(x,f) do {if (FL_ABLE(x)) RBASIC(x)->flags ^= (f);} while (0)
#if WITH_OBJC
-# define OBJ_TAINTED(x) (rb_obj_tainted((VALUE)x))
+# define OBJ_TAINTED(x) (SPECIAL_CONST_P(x) || NATIVE(x) ? rb_obj_tainted((VALUE)x) : FL_TEST((x), FL_TAINT))
# define OBJ_TAINT(x) (rb_obj_taint((VALUE)x))
#else
# define OBJ_TAINTED(x) FL_TEST((x), FL_TAINT)
@@ -781,7 +826,7 @@
#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & FL_TAINT;} while (0)
#if WITH_OBJC
-# define OBJ_FROZEN(x) (rb_obj_frozen_p((VALUE)x))
+# define OBJ_FROZEN(x) (SPECIAL_CONST_P(x) || NATIVE(x) ? rb_obj_frozen_p((VALUE)x) : FL_TEST((x), FL_FREEZE))
# define OBJ_FREEZE(x) (rb_obj_freeze((VALUE)x))
#else
# define OBJ_FROZEN(x) FL_TEST((x), FL_FREEZE)
@@ -839,9 +884,19 @@
ID rb_intern(const char*);
ID rb_intern2(const char*, long);
ID rb_intern_str(VALUE str);
-const char *rb_id2name(ID);
ID rb_to_id(VALUE);
VALUE rb_id2str(ID);
+#if WITH_OBJC
+# define rb_sym2name(sym) (RSYMBOL(sym)->str)
+static inline
+const char *rb_id2name(ID val)
+{
+ VALUE s = rb_id2str(val);
+ return s == 0 ? NULL : rb_sym2name(s);
+}
+#else
+const char *rb_id2name(ID);
+#endif
#ifdef __GNUC__
/* __builtin_constant_p and statement expression is available
@@ -946,6 +1001,9 @@
RUBY_EXTERN VALUE rb_cBasicObject;
RUBY_EXTERN VALUE rb_cObject;
+#if WITH_OBJC
+RUBY_EXTERN VALUE rb_cNSObject;
+#endif
RUBY_EXTERN VALUE rb_cArray;
RUBY_EXTERN VALUE rb_cBignum;
RUBY_EXTERN VALUE rb_cBinding;
@@ -984,6 +1042,19 @@
RUBY_EXTERN VALUE rb_cVM;
RUBY_EXTERN VALUE rb_cEnv;
+#if WITH_OBJC
+RUBY_EXTERN VALUE rb_cCFString;
+RUBY_EXTERN VALUE rb_cNSString;
+RUBY_EXTERN VALUE rb_cNSMutableString;
+RUBY_EXTERN VALUE rb_cCFArray;
+RUBY_EXTERN VALUE rb_cNSArray;
+RUBY_EXTERN VALUE rb_cNSMutableArray;
+RUBY_EXTERN VALUE rb_cCFHash;
+RUBY_EXTERN VALUE rb_cNSHash;
+RUBY_EXTERN VALUE rb_cNSMutableHash;
+RUBY_EXTERN VALUE rb_cCFNumber;
+#endif
+
RUBY_EXTERN VALUE rb_eException;
RUBY_EXTERN VALUE rb_eStandardError;
RUBY_EXTERN VALUE rb_eSystemExit;
@@ -1019,19 +1090,75 @@
RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
#if WITH_OBJC
-static inline unsigned
-rb_objc_is_non_native(VALUE obj)
+static inline bool
+rb_is_native(VALUE obj) {
+ Class k = *(Class *)obj;
+ return k != NULL && (RCLASS_VERSION(k) & RCLASS_IS_OBJECT_SUBCLASS) != RCLASS_IS_OBJECT_SUBCLASS;
+}
+#define NATIVE(obj) (rb_is_native((VALUE)obj))
+
+VALUE rb_box_fixnum(VALUE);
+
+static inline id
+rb_rval_to_ocid(VALUE obj)
{
- void *isa = RBASIC(obj)->isa;
- if (isa == NULL || class_isMetaClass(isa))
- return 0;
- while (isa != NULL) {
- if (rb_cObject != 0 && isa == RCLASS_OCID(rb_cObject))
- return 0;
- isa = (void *)class_getSuperclass(isa);
+ if (SPECIAL_CONST_P(obj)) {
+ if (obj == Qtrue) {
+ return (id)kCFBooleanTrue;
+ }
+ if (obj == Qfalse) {
+ return (id)kCFBooleanFalse;
+ }
+ if (obj == Qnil) {
+ return (id)kCFNull;
+ }
+ if (FIXNUM_P(obj)) {
+ return (id)rb_box_fixnum(obj);
+ }
}
- return 1;
+ return (id)obj;
}
+
+static inline VALUE
+rb_ocid_to_rval(id obj)
+{
+ if (obj == (id)kCFBooleanTrue) {
+ return Qtrue;
+ }
+ if (obj == (id)kCFBooleanFalse) {
+ return Qfalse;
+ }
+ if (obj == (id)kCFNull) {
+ return Qnil;
+ }
+ if (*(Class *)obj == (Class)rb_cFixnum) {
+ return LONG2FIX(RFIXNUM(obj)->value);
+ }
+ if (*(Class *)obj == (Class)rb_cCFNumber) {
+ /* TODO NSNumber should implement the Numeric primitive methods */
+ if (CFNumberIsFloatType((CFNumberRef)obj)) {
+ double v;
+ assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberDoubleType, &v));
+ extern VALUE rb_float_new(double);
+ return rb_float_new(v);
+ }
+ else {
+ long v;
+ assert(CFNumberGetValue((CFNumberRef)obj, kCFNumberLongType, &v));
+ return LONG2FIX(v);
+ }
+ }
+ return (VALUE)obj;
+}
+#define RB2OC(obj) (rb_rval_to_ocid((VALUE)obj))
+#define OC2RB(obj) (rb_ocid_to_rval((id)obj))
+
+static inline VALUE
+rb_ary_elt_fast(CFArrayRef ary, long i)
+{
+ return OC2RB(CFArrayGetValueAtIndex(ary, i));
+}
+#define RARRAY_AT(a,i) (rb_ary_elt_fast((CFArrayRef)a, (long)i))
#endif
static inline VALUE
@@ -1040,36 +1167,27 @@
if (IMMEDIATE_P(obj)) {
if (FIXNUM_P(obj)) return rb_cFixnum;
if (obj == Qtrue) return rb_cTrueClass;
+#if !WITH_OBJC
if (SYMBOL_P(obj)) return rb_cSymbol;
+#endif
}
else if (!RTEST(obj)) {
if (obj == Qnil) return rb_cNilClass;
if (obj == Qfalse) return rb_cFalseClass;
}
-#if WITH_OBJC
- extern VALUE rb_cCFString;
- extern VALUE rb_cCFArray;
- extern VALUE rb_cCFHash;
- if (rb_cCFString != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFString))
- return rb_cCFString;
- if (rb_cCFArray != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFArray))
- return rb_cCFArray;
- if (rb_cCFHash != 0 && *(Class *)obj == RCLASS_OCID(rb_cCFHash))
- return rb_cCFHash;
- VALUE rb_objc_import_class(Class);
- if (rb_objc_is_non_native(obj))
- return rb_objc_import_class(RBASIC(obj)->isa);
-#endif
return RBASIC(obj)->klass;
}
static inline int
rb_type(VALUE obj)
{
+ Class k;
if (IMMEDIATE_P(obj)) {
if (FIXNUM_P(obj)) return T_FIXNUM;
if (obj == Qtrue) return T_TRUE;
+#if !WITH_OBJC
if (SYMBOL_P(obj)) return T_SYMBOL;
+#endif
if (obj == Qundef) return T_UNDEF;
}
else if (!RTEST(obj)) {
@@ -1077,20 +1195,26 @@
if (obj == Qfalse) return T_FALSE;
}
#if WITH_OBJC
- /* FIXME this is super slow */
- else if (rb_cHash != 0
- && rb_cArray != 0
- && rb_cString != 0) {
- Class k = *(Class *)obj;
- while (k != NULL) {
- if (k == RCLASS_OCID(rb_cHash))
- return T_HASH;
- if (k == RCLASS_OCID(rb_cArray))
- return T_ARRAY;
- if (k == RCLASS_OCID(rb_cString))
- return T_STRING;
- k = class_getSuperclass(k);
+ else if ((k = *(Class *)obj) != NULL) {
+ if (RCLASS_META(k)) {
+ if (RCLASS_MODULE(obj)) return T_MODULE;
+ else return T_CLASS;
}
+ if (k == (Class)rb_cSymbol) return T_SYMBOL;
+ if (k == (Class)rb_cCFString
+ || (RCLASS_VERSION(k) & RCLASS_IS_STRING_SUBCLASS)
+ == RCLASS_IS_STRING_SUBCLASS)
+ return T_STRING;
+ if (k == (Class)rb_cCFArray
+ || (RCLASS_VERSION(k) & RCLASS_IS_ARRAY_SUBCLASS)
+ == RCLASS_IS_ARRAY_SUBCLASS)
+ return T_ARRAY;
+ if (k == (Class)rb_cCFHash
+ || (RCLASS_VERSION(k) & RCLASS_IS_HASH_SUBCLASS)
+ == RCLASS_IS_HASH_SUBCLASS)
+ return T_HASH;
+ if (k == (Class)rb_cFixnum) return T_FIXNUM;
+ if (NATIVE(obj)) return T_NATIVE;
}
#endif
return BUILTIN_TYPE(obj);
Modified: MacRuby/trunk/insnhelper.h
===================================================================
--- MacRuby/trunk/insnhelper.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/insnhelper.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -112,8 +112,8 @@
c1->nd_next = __tmp_c2->nd_next; \
} while (0)
-#define CALL_METHOD(num, blockptr, flag, id, mn, recv, klass) do { \
- VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, mn, recv, klass); \
+#define CALL_METHOD(num, blockptr, flag, id, recv, klass, mcache) do { \
+ VALUE v = vm_call_method(th, GET_CFP(), num, blockptr, flag, id, recv, klass, (struct rb_method_cache *)mcache); \
if (v == Qundef) { \
RESTORE_REGS(); \
NEXT_INSN(); \
@@ -140,9 +140,13 @@
#define BASIC_OP_UNREDEFINED_P(op) ((ruby_vm_redefined_flag & (op)) == 0)
#define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
-#define CALL_SIMPLE_METHOD(num, id, recv) do { \
- VALUE klass = CLASS_OF(recv); \
- CALL_METHOD(num, 0, 0, id, rb_method_node(klass, id), recv, CLASS_OF(recv)); \
+#define CALL_SIMPLE_METHOD(num, id, recv, asel) do { \
+ struct rb_method_cache mcache; \
+ mcache.flags = RB_MCACHE_RCALL_FLAG; \
+ mcache.as.rcall.sel = asel; \
+ mcache.as.rcall.klass = 0; \
+ mcache.as.rcall.node = NULL; \
+ CALL_METHOD(num, 0, 0, id, recv, CLASS_OF(recv), &mcache); \
} while (0)
#endif /* RUBY_INSNHELPER_H */
Modified: MacRuby/trunk/insns.def
===================================================================
--- MacRuby/trunk/insns.def 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/insns.def 2008-08-21 06:13:14 UTC (rev 459)
@@ -812,9 +812,21 @@
break;
case DEFINED_METHOD:{
VALUE klass = CLASS_OF(v);
+#if WITH_OBJC
+ NODE *method;
+ IMP imp;
+
+ method = rb_objc_method_node(klass, SYM2ID(obj), &imp, NULL);
+
+ if (method == NULL && imp != NULL) {
+ expr_type = "method";
+ }
+ else if (method != NULL) {
+#else
NODE *method = (NODE *) rb_method_node(klass, SYM2ID(obj));
if (method) {
+#endif
if (!(method->nd_noex & NOEX_PRIVATE)) {
if (!((method->nd_noex & NOEX_PROTECTED) &&
!rb_obj_is_kind_of(GET_SELF(),
@@ -1023,11 +1035,13 @@
*/
DEFINE_INSN
send
-(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)
+(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, VALUE mcache)
(...)
(VALUE val) // inc += - (op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
{
+#if !WITH_OBJC
NODE *mn;
+#endif
VALUE recv, klass;
rb_block_t *blockptr = 0;
rb_num_t num = caller_setup_args(th, GET_CFP(), op_flag, op_argc,
@@ -1038,17 +1052,16 @@
/* get receiver */
recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
klass = CLASS_OF(recv);
+#if !WITH_OBJC
mn = vm_method_search(id, klass, ic);
-#if WITH_OBJC
- vm_method_process_named_args(&id, &mn, recv, &num, GET_CFP());
-#endif
/* send/funcall optimization */
if (flag & VM_CALL_SEND_BIT) {
vm_send_optimize(GET_CFP(), &mn, &flag, &num, &id, klass);
}
+#endif
- CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
+ CALL_METHOD(num, blockptr, flag, id, recv, klass, mcache);
}
/**
@@ -1069,16 +1082,34 @@
VALUE recv, klass;
NODE *mn;
ID id;
+ IMP imp;
+ SEL sel;
const VALUE flag = VM_CALL_SUPER_BIT | VM_CALL_FCALL_BIT;
recv = GET_SELF();
- vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass);
+ mn = NULL; imp = NULL; sel = 0;
+ vm_search_superclass(GET_CFP(), GET_ISEQ(), recv, TOPN(num), &id, &klass, &mn, &imp, &sel);
+#if !WITH_OBJC
mn = rb_method_node(klass, id);
+#endif
+
#if WITH_OBJC
- vm_method_process_named_args(&id, &mn, recv, (rb_num_t *)&num, GET_CFP());
+ struct rb_method_cache mcache;
+ void *mcachep;
+
+ if (mn != NULL) {
+ mcache.flags = RB_MCACHE_RCALL_FLAG;
+ mcache.as.rcall.sel = sel;
+ mcache.as.rcall.klass = klass;
+ mcache.as.rcall.node = mn;
+ mcachep = &mcache;
+ }
+ else {
+ mcachep = NULL;
+ }
#endif
- CALL_METHOD(num, blockptr, flag, id, mn, recv, klass);
+ CALL_METHOD(num, blockptr, flag, id, recv, klass, mcachep);
}
/**
@@ -1298,8 +1329,9 @@
VALUE val;
#if WITH_OBJC
if (CFDictionaryGetValueIfPresent((CFDictionaryRef)hash,
- (const void *)key,
+ (const void *)RB2OC(key),
(const void **)&val)) {
+ val = OC2RB(val);
#else
if (st_lookup(RHASH_TBL(hash), key, &val)) {
#endif
@@ -1405,7 +1437,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idPLUS, recv);
+ CALL_SIMPLE_METHOD(1, idPLUS, recv, selPLUS);
}
}
@@ -1439,7 +1471,7 @@
/* other */
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idMINUS, recv);
+ CALL_SIMPLE_METHOD(1, idMINUS, recv, selMINUS);
}
}
@@ -1492,7 +1524,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idMULT, recv);
+ CALL_SIMPLE_METHOD(1, idMULT, recv, selMULT);
}
}
@@ -1556,7 +1588,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idDIV, recv);
+ CALL_SIMPLE_METHOD(1, idDIV, recv, selDIV);
}
}
@@ -1635,7 +1667,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idMOD, recv);
+ CALL_SIMPLE_METHOD(1, idMOD, recv, selMOD);
}
}
@@ -1656,7 +1688,7 @@
/* other */
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idEq, recv);
+ CALL_SIMPLE_METHOD(1, idEq, recv, selEq);
}
}
@@ -1687,7 +1719,7 @@
/* other */
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idNeq, recv);
+ CALL_SIMPLE_METHOD(1, idNeq, recv, selNeq);
}
}
@@ -1716,7 +1748,7 @@
else {
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idLT, recv);
+ CALL_SIMPLE_METHOD(1, idLT, recv, selLT);
}
}
@@ -1746,7 +1778,7 @@
/* other */
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idLE, recv);
+ CALL_SIMPLE_METHOD(1, idLE, recv, selLE);
}
}
@@ -1775,7 +1807,7 @@
else {
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idGT, recv);
+ CALL_SIMPLE_METHOD(1, idGT, recv, selGT);
}
}
@@ -1804,7 +1836,7 @@
else {
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idGE, recv);
+ CALL_SIMPLE_METHOD(1, idGE, recv, selGE);
}
}
@@ -1838,7 +1870,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idLTLT, recv);
+ CALL_SIMPLE_METHOD(1, idLTLT, recv, selLTLT);
}
}
@@ -1868,7 +1900,7 @@
INSN_LABEL(normal_dispatch):
PUSH(recv);
PUSH(obj);
- CALL_SIMPLE_METHOD(1, idAREF, recv);
+ CALL_SIMPLE_METHOD(1, idAREF, recv, selAREF);
}
}
@@ -1902,7 +1934,7 @@
PUSH(recv);
PUSH(obj);
PUSH(set);
- CALL_SIMPLE_METHOD(2, idASET, recv);
+ CALL_SIMPLE_METHOD(2, idASET, recv, selASET);
}
}
@@ -1935,7 +1967,7 @@
else {
INSN_LABEL(normal_dispatch):
PUSH(recv);
- CALL_SIMPLE_METHOD(0, idLength, recv);
+ CALL_SIMPLE_METHOD(0, idLength, recv, selLength);
}
}
@@ -1982,7 +2014,7 @@
if (0) {
INSN_LABEL(normal_dispatch):
PUSH(recv);
- CALL_SIMPLE_METHOD(0, idSucc, recv);
+ CALL_SIMPLE_METHOD(0, idSucc, recv, selSucc);
}
}
@@ -2005,7 +2037,7 @@
}
else {
PUSH(recv);
- CALL_SIMPLE_METHOD(0, idNot, recv);
+ CALL_SIMPLE_METHOD(0, idNot, recv, selNot);
}
}
Modified: MacRuby/trunk/instruby.rb
===================================================================
--- MacRuby/trunk/instruby.rb 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/instruby.rb 2008-08-21 06:13:14 UTC (rev 459)
@@ -501,22 +501,30 @@
end
end
-puts "fixing bridge support dylibs"
-unless File.exist?('markgc')
- unless system("gcc markgc.c -std=gnu99 -o markgc")
- $stderr.puts "cannot build the markgc tool"
- exit 1
+touch_file = '/System/Library/Frameworks/.bridgesupport_dylib_gcmarked'
+if $destdir.empty? and File.exist?(touch_file)
+ puts "bridge support dylibs already fixed"
+else
+ puts "fixing bridge support dylibs"
+ unless File.exist?('markgc')
+ unless system("gcc markgc.c -std=gnu99 -o markgc")
+ $stderr.puts "cannot build the markgc tool"
+ exit 1
+ end
end
-end
-Dir.glob('/System/Library/Frameworks/**/BridgeSupport/*.dylib').each do |p|
- unless system("./markgc '#{p}' >& /dev/null")
- $stderr.puts "cannot markgc #{p}"
- exit 1
+ Dir.glob('/System/Library/Frameworks/**/BridgeSupport/*.dylib').each do |p|
+ unless system("./markgc '#{p}' >& /dev/null")
+ $stderr.puts "cannot markgc #{p}"
+ exit 1
+ end
+ unless $destdir.empty?
+ dirname = File.dirname(p)
+ mkdir_p(dirname)
+ install(p, dirname)
+ end
end
- unless $destdir.empty?
- dirname = File.dirname(p)
- mkdir_p(dirname)
- install(p, dirname)
+ if $destdir.empty?
+ touch(touch_file)
end
end
Modified: MacRuby/trunk/io.c
===================================================================
--- MacRuby/trunk/io.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/io.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -3972,7 +3972,7 @@
write_fptr->fd = write_fd;
write_fptr->mode = (modef & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
fptr->mode &= ~FMODE_WRITABLE;
- fptr->tied_io_for_writing = write_port;
+ GC_WB(&fptr->tied_io_for_writing, write_port);
rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
}
@@ -4589,7 +4589,7 @@
write_io = GetWriteIO(io);
if (io != write_io) {
write_io = rb_obj_dup(write_io);
- fptr->tied_io_for_writing = write_io;
+ GC_WB(&fptr->tied_io_for_writing, write_io);
rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
}
@@ -5209,7 +5209,7 @@
p->filename = Qnil;
p->current_file = Qnil;
p->lineno = Qnil;
- p->argv = v;
+ GC_WB(&p->argv, v);
}
static VALUE
@@ -5248,11 +5248,11 @@
argf_initialize_copy(VALUE argf, VALUE orig)
{
ARGF = argf_of(orig);
- rb_argv = rb_obj_dup(rb_argv);
+ GC_WB(&rb_argv, rb_obj_dup(rb_argv));
if (ARGF.inplace) {
const char *inplace = ARGF.inplace;
ARGF.inplace = 0;
- ARGF.inplace = ruby_strdup(inplace);
+ GC_WB(&ARGF.inplace, ruby_strdup(inplace));
}
return argf;
}
@@ -7812,7 +7812,7 @@
rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, 0);
- filename = rb_str_new2("-");
+ GC_WB(&filename, rb_str_new2("-"));
rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
rb_define_hooked_variable("$*", &argf, argf_argv_getter, 0);
Modified: MacRuby/trunk/lib/delegate.rb
===================================================================
--- MacRuby/trunk/lib/delegate.rb 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/lib/delegate.rb 2008-08-21 06:13:14 UTC (rev 459)
@@ -117,9 +117,8 @@
class Delegator
preserved = [
:__id__, :object_id, :__send__, :public_send, :respond_to?, :send,
- :instance_eval, :instance_exec, :extend,
+ :instance_eval, :instance_exec, :extend, :initialize
]
- preserved.concat(NSObject.instance_methods)
instance_methods.each do |m|
next if preserved.include?(m)
undef_method m
Modified: MacRuby/trunk/lib/fileutils.rb
===================================================================
--- MacRuby/trunk/lib/fileutils.rb 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/lib/fileutils.rb 2008-08-21 06:13:14 UTC (rev 459)
@@ -1507,7 +1507,8 @@
end
METHODS = singleton_methods() - [:private_module_function,
- :commands, :options, :have_option?, :options_of, :collect_method]
+ :commands, :options, :have_option?, :options_of,
+ :collect_method]
#
# This module has all methods of FileUtils module, but it outputs messages
Modified: MacRuby/trunk/marshal.c
===================================================================
--- MacRuby/trunk/marshal.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/marshal.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -420,14 +420,16 @@
{
const char *path;
- if (check && FL_TEST(klass, FL_SINGLETON)) {
+ if (check && RCLASS_SINGLETON(klass)) {
+#if !WITH_OBJC // TODO
if (RCLASS_M_TBL(klass)->num_entries ||
(RCLASS_IV_TBL(klass) && RCLASS_IV_TBL(klass)->num_entries > 1)) {
rb_raise(rb_eTypeError, "singleton can't be dumped");
}
+#endif
klass = RCLASS_SUPER(klass);
}
- while (BUILTIN_TYPE(klass) == T_ICLASS) {
+ while (TYPE(klass) == T_ICLASS) {
path = rb_class2name(RBASIC(klass)->klass);
w_byte(TYPE_EXTENDED_R, arg);
w_unique(path, arg);
@@ -534,6 +536,7 @@
static void
w_objivar(VALUE obj, struct dump_call_arg *arg)
{
+#if !WITH_OBJC /* TODO */
VALUE *ptr;
long i, len, num;
@@ -548,6 +551,7 @@
if (num != 0) {
rb_ivar_foreach(obj, w_obj_each, (st_data_t)arg);
}
+#endif
}
static void
@@ -650,7 +654,7 @@
st_add_direct(arg->data, obj, arg->data->num_entries);
#if WITH_OBJC
- if (!rb_objc_is_non_native(obj))
+ if (!NATIVE(obj))
#endif
{
st_data_t compat_data;
@@ -667,7 +671,7 @@
switch (/*BUILTIN_*/TYPE(obj)) {
case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(obj)) {
rb_raise(rb_eTypeError, "singleton class can't be dumped");
}
w_byte(TYPE_CLASS, arg);
@@ -1279,28 +1283,20 @@
{
VALUE c = path2class(r_unique(arg));
- if (FL_TEST(c, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(c)) {
rb_raise(rb_eTypeError, "singleton can't be loaded");
}
v = r_object0(arg, 0, extmod);
-#if WITH_OBJC
- if (rb_objc_is_non_native(v)) {
- *(Class *)v = RCLASS_OCID(c);
- }
- else
-#endif
- {
- if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
+ if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) {
format_error:
- rb_raise(rb_eArgError, "dump format error (user class)");
- }
- if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
- VALUE tmp = rb_obj_alloc(c);
+ rb_raise(rb_eArgError, "dump format error (user class)");
+ }
+ if (TYPE(v) == T_MODULE || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
+ VALUE tmp = rb_obj_alloc(c);
- if (TYPE(v) != TYPE(tmp)) goto format_error;
- }
- RBASIC(v)->klass = c;
+ if (TYPE(v) != TYPE(tmp)) goto format_error;
}
+ RBASIC(v)->klass = c;
}
break;
Modified: MacRuby/trunk/numeric.c
===================================================================
--- MacRuby/trunk/numeric.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/numeric.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -83,6 +83,9 @@
static ID id_coerce, id_to_i, id_eq;
VALUE rb_cNumeric;
+#if WITH_OBJC
+VALUE rb_cCFNumber;
+#endif
VALUE rb_cFloat;
VALUE rb_cInteger;
VALUE rb_cFixnum;
@@ -90,6 +93,45 @@
VALUE rb_eZeroDivError;
VALUE rb_eFloatDomainError;
+#if WITH_OBJC
+static CFMutableDictionaryRef fixnum_dict = NULL;
+static struct RFixnum *fixnum_cache = NULL;
+
+VALUE
+rb_box_fixnum(VALUE fixnum)
+{
+ struct RFixnum *val;
+ long value;
+
+ if (fixnum_dict == NULL)
+ fixnum_dict = CFDictionaryCreateMutable(kCFAllocatorMalloc, 0, NULL, NULL);
+
+ value = FIX2LONG(fixnum);
+
+ if (value >= 0 && value <= 1000000) {
+ if (fixnum_cache == NULL) {
+ fixnum_cache = (struct RFixnum *)calloc(1, sizeof(struct RFixnum) * 1000000);
+ }
+ val = &fixnum_cache[value];
+ if (val->klass == 0) {
+ val->klass = rb_cFixnum;
+ val->value = value;
+ }
+ return (VALUE)val;
+ }
+
+ val = (struct RFixnum *)CFDictionaryGetValue(fixnum_dict, (const void *)fixnum);
+ if (val == NULL) {
+ val = (struct RFixnum *)malloc(sizeof(struct RFixnum));
+ val->klass = rb_cFixnum;
+ val->value = FIX2LONG(fixnum);
+ CFDictionarySetValue(fixnum_dict, (const void *)fixnum, (const void *)val);
+ }
+
+ return (VALUE)val;
+}
+#endif
+
void
rb_num_zerodiv(void)
{
@@ -3106,9 +3148,9 @@
}
static const char *
-imp_rb_integer_objCType(void *rcv, SEL sel)
+imp_rb_fixnum_objCType(void *rcv, SEL sel)
{
- return "q";
+ return "l";
}
static void
@@ -3119,10 +3161,10 @@
}
static void
-imp_rb_integer_getValue(void *rcv, SEL sel, void *buffer)
+imp_rb_fixnum_getValue(void *rcv, SEL sel, void *buffer)
{
- long long v = NUM2LL(rcv);
- *(long long *)buffer = v;
+ long v = RFIXNUM(rcv)->value;
+ *(long *)buffer = v;
}
static double
@@ -3132,9 +3174,9 @@
}
static long long
-imp_rb_integer_longLongValue(void *rcv, SEL sel)
+imp_rb_fixnum_longValue(void *rcv, SEL sel)
{
- return NUM2LL(rcv);
+ return RFIXNUM(rcv)->value;
}
static inline void
@@ -3146,27 +3188,25 @@
}
static void
-rb_install_nsnumber_float_primitives(void)
+rb_install_nsnumber_primitives(void)
{
- Class klass = RCLASS_OCID(rb_cFloat);
+ Class klass;
+
+ klass = (Class)rb_cFloat;
rb_objc_install_method(klass, sel_registerName("objCType"),
(IMP)imp_rb_float_objCType);
rb_objc_install_method(klass, sel_registerName("getValue:"),
(IMP)imp_rb_float_getValue);
rb_objc_install_method(klass, sel_registerName("doubleValue"),
(IMP)imp_rb_float_doubleValue);
-}
-static void
-rb_install_nsnumber_integer_primitives(void)
-{
- Class klass = RCLASS_OCID(rb_cNumeric);
+ klass = (Class)rb_cFixnum;
rb_objc_install_method(klass, sel_registerName("objCType"),
- (IMP)imp_rb_integer_objCType);
+ (IMP)imp_rb_fixnum_objCType);
rb_objc_install_method(klass, sel_registerName("getValue:"),
- (IMP)imp_rb_integer_getValue);
- rb_objc_install_method(klass, sel_registerName("longLongValue"),
- (IMP)imp_rb_integer_longLongValue);
+ (IMP)imp_rb_fixnum_getValue);
+ rb_objc_install_method(klass, sel_registerName("longValue"),
+ (IMP)imp_rb_fixnum_longValue);
}
#endif
@@ -3190,8 +3230,13 @@
rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
#if WITH_OBJC
- rb_cNumeric = rb_define_class("Numeric",
- rb_objc_import_class((void*)objc_getClass("NSNumber")));
+ rb_cCFNumber = (VALUE)objc_getClass("NSCFNumber");
+ rb_cNumeric = rb_define_class("Numeric", (VALUE)objc_getClass("NSNumber"));
+ RCLASS_SET_VERSION_FLAG(rb_cNumeric, RCLASS_IS_OBJECT_SUBCLASS);
+ rb_define_object_special_methods(rb_cNumeric);
+ /* overriding NSObject methods */
+ rb_define_method(rb_cNumeric, "class", rb_obj_class, 0);
+ rb_define_method(rb_cNumeric, "dup", rb_obj_dup, 0);
#else
rb_cNumeric = rb_define_class("Numeric", rb_cObject);
#endif
@@ -3354,7 +3399,6 @@
rb_define_method(rb_cFloat, "finite?", flo_is_finite_p, 0);
#if WITH_OBJC
- rb_install_nsnumber_integer_primitives();
- rb_install_nsnumber_float_primitives();
+ rb_install_nsnumber_primitives();
#endif
}
Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/objc.m 2008-08-21 06:13:14 UTC (rev 459)
@@ -40,6 +40,7 @@
#endif
#include "vm_core.h"
#include "vm.h"
+#include "eval_intern.h"
typedef struct {
bs_element_type_t type;
@@ -58,11 +59,9 @@
static ID rb_ivar_type;
static VALUE bs_const_magic_cookie = Qnil;
-static VALUE rb_objc_class_magic_cookie = Qnil;
static struct st_table *bs_constants;
-static struct st_table *bs_functions;
-static struct st_table *bs_function_syms;
+struct st_table *bs_functions;
static struct st_table *bs_boxeds;
static struct st_table *bs_classes;
static struct st_table *bs_inf_prot_cmethods;
@@ -401,56 +400,6 @@
return NULL;
}
-bool
-rb_objc_rval_to_ocid(VALUE rval, void **ocval, bool force_nsnil)
-{
- if (SPECIAL_CONST_P(rval)) {
- if (rval == Qtrue) {
- *(id *)ocval = (id)kCFBooleanTrue;
- }
- else if (rval == Qfalse) {
- *(id *)ocval = (id)kCFBooleanFalse;
- }
- else if (rval == Qnil) {
- *(id *)ocval = force_nsnil ? (id)kCFNull : nil;
- }
- else if (SYMBOL_P(rval)) {
- *(id *)ocval = (id)rb_id2str(SYM2ID(rval));
- }
- else if (FIXNUM_P(rval)) {
-#define FIXNUM_CFNUMBER_CACHE_SIZE 2000
- static void *fixnum_cfnumber_cache[FIXNUM_CFNUMBER_CACHE_SIZE];
- static bool fixnum_cfnumber_cache_init = false;
- long v = FIX2LONG(rval);
- CFNumberRef number;
- if (!fixnum_cfnumber_cache_init) {
- memset(fixnum_cfnumber_cache, 0, sizeof(void *) * FIXNUM_CFNUMBER_CACHE_SIZE);
- fixnum_cfnumber_cache_init = true;
- }
- /* cache -500..1500 */
- if (v >= -500 && v < 1500) {
- number = fixnum_cfnumber_cache[v+500];
- if (number == NULL) {
- number = CFNumberCreate(NULL, kCFNumberLongType, &v);
- fixnum_cfnumber_cache[v+500] = (void *)number;
- }
- }
- else {
- number = CFNumberCreate(NULL, kCFNumberLongType, &v);
- CFMakeCollectable(number);
- }
- *(id *)ocval = (id)number;
- }
- }
- else if (class_isMetaClass(*(Class *)rval)) {
- *(id *)ocval = (id)RCLASS_OCID(rval);
- }
- else {
- *(id *)ocval = (id)rval;
- }
- return true;
-}
-
static bool
rb_objc_rval_to_ocsel(VALUE rval, void **ocval)
{
@@ -467,7 +416,7 @@
break;
case T_SYMBOL:
- cstr = rb_id2name(SYM2ID(rval));
+ cstr = rb_sym2name(rval);
break;
default:
@@ -697,7 +646,8 @@
if (*octype == _C_VOID)
return;
- if (st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
+ if (bs_boxeds != NULL
+ && st_lookup(bs_boxeds, (st_data_t)octype, (st_data_t *)&bs_boxed)) {
void *data;
data = rb_objc_rval_to_boxed_data(rval, bs_boxed, &ok);
@@ -712,7 +662,7 @@
goto bails;
}
- if (st_lookup(bs_cftypes, (st_data_t)octype, NULL))
+ if (bs_cftypes != NULL && st_lookup(bs_cftypes, (st_data_t)octype, NULL))
octype = "@";
if (*octype != _C_BOOL && *octype != _C_ID) {
@@ -725,7 +675,8 @@
switch (*octype) {
case _C_ID:
case _C_CLASS:
- ok = rb_objc_rval_to_ocid(rval, ocval, false);
+ *(id *)ocval = rval == Qnil ? NULL : RB2OC(rval);
+ ok = true;
break;
case _C_SEL:
@@ -851,39 +802,7 @@
RSTRING_PTR(rb_inspect(rval)), octype);
}
-VALUE
-rb_objc_boot_ocid(id ocid)
-{
- if (rb_objc_is_non_native((VALUE)ocid)) {
- /* Make sure the ObjC class is imported in Ruby. */
- rb_objc_import_class(object_getClass(ocid));
- }
- else if (RBASIC(ocid)->klass == 0) {
- /* This pure-Ruby object was created from Objective-C, we need to
- * initialize the Ruby bits.
- */
- VALUE klass;
-
- klass = rb_objc_import_class(object_getClass(ocid));
-
- RBASIC(ocid)->klass = klass;
- RBASIC(ocid)->flags =
- klass == rb_cString
- ? T_STRING
- : klass == rb_cArray
- ? T_ARRAY
- : klass == rb_cHash
- ? T_HASH
- : T_OBJECT;
- }
-
- return (VALUE)ocid;
-}
-
-static void
-rb_objc_ocval_to_rbval(void **ocval, const char *octype, VALUE *rbval);
-
-bool
+static inline bool
rb_objc_ocid_to_rval(void **ocval, VALUE *rbval)
{
id ocid = *(id *)ocval;
@@ -892,7 +811,7 @@
*rbval = Qnil;
}
else {
- *rbval = rb_objc_boot_ocid(ocid);
+ *rbval = (VALUE)ocid;
}
return true;
@@ -909,23 +828,23 @@
{
bs_element_boxed_t *bs_boxed;
- if (st_lookup(bs_boxeds, (st_data_t)octype,
+ if (bs_boxeds != NULL
+ && st_lookup(bs_boxeds, (st_data_t)octype,
(st_data_t *)&bs_boxed)) {
*rbval = rb_bs_boxed_new_from_ocdata(bs_boxed, ocval);
goto bails;
}
- if (st_lookup(bs_cftypes, (st_data_t)octype, NULL))
+ if (bs_cftypes != NULL
+ && st_lookup(bs_cftypes, (st_data_t)octype, NULL))
octype = "@";
}
-
+
switch (*octype) {
case _C_ID:
- ok = rb_objc_ocid_to_rval(ocval, rbval);
- break;
-
case _C_CLASS:
- *rbval = rb_objc_import_class(*(Class *)ocval);
+ *rbval = *(void **)ocval == NULL ? Qnil : *(VALUE *)ocval;
+ ok = true;
break;
case _C_BOOL:
@@ -1024,9 +943,11 @@
rb_raise(rb_eRuntimeError, "%s: %s", name, desc);
}
-static bs_element_method_t *
+bs_element_method_t *
rb_bs_find_method(Class klass, SEL sel)
{
+ if (bs_classes == NULL)
+ return NULL;
do {
bs_element_indexed_class_t *bs_class;
bs_element_method_t *bs_method;
@@ -1077,20 +998,8 @@
return type;
}
-extern NODE *rb_current_cfunc_node;
-
-struct objc_ruby_closure_context {
- SEL selector;
- bs_element_method_t *bs_method;
- Method method;
- ffi_cif *cif;
- IMP imp;
- Class klass;
-};
-
-static VALUE
-rb_objc_call_objc(int argc, VALUE *argv, id ocrcv, Class klass,
- bool super_call, struct objc_ruby_closure_context *ctx)
+VALUE
+rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, int argc, VALUE *argv)
{
unsigned i, real_count, count;
ffi_type *ffi_rettype, **ffi_argtypes;
@@ -1098,13 +1007,27 @@
ffi_cif *cif;
const char *type;
char buf[128];
- void *imp;
+ id ocrcv;
- count = method_getNumberOfArguments(ctx->method);
+ /* XXX very special exceptions! */
+ if (recv == rb_cNSMutableHash && sel == @selector(new)) {
+ /* because Hash.new can accept a block */
+ return rb_class_new_instance(0, NULL, recv);
+ }
+ else if (RCLASS_META(klass) && sel == @selector(class)) {
+ /* because +[NSObject class] returns self */
+ return rb_cClass;
+ }
+
+ ocrcv = RB2OC(recv);
+
+ DLOG("OCALL", "%c[<%s %p> %s]", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)ocrcv, (char *)sel);
+
+ count = method_getNumberOfArguments(method);
assert(count >= 2);
real_count = count;
- if (ctx->bs_method != NULL && ctx->bs_method->variadic) {
+ if (bs_method != NULL && bs_method->variadic) {
if (argc < count - 2)
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, count - 2);
@@ -1116,97 +1039,68 @@
}
if (count == 2) {
- method_getReturnType(ctx->method, buf, sizeof buf);
- if (buf[0] == '@' || buf[0] == 'v') {
+ method_getReturnType(method, buf, sizeof buf);
+ if (buf[0] == '@' || buf[0] == '#' || buf[0] == 'v') {
/* Easy case! */
@try {
- if (super_call) {
+ if (klass == RCLASS_SUPER(*(Class *)ocrcv)) {
struct objc_super s;
s.receiver = ocrcv;
- s.class = klass;
- ffi_ret = objc_msgSendSuper(&s, ctx->selector);
+ s.class = (Class)klass;
+ ffi_ret = objc_msgSendSuper(&s, sel);
}
else {
- ffi_ret = objc_msgSend(ocrcv, ctx->selector);
+ ffi_ret = objc_msgSend(ocrcv, sel);
}
}
@catch (id e) {
rb_objc_exc_raise(e);
}
- return buf[0] == '@' ? (VALUE)ffi_ret : Qnil;
+ if (buf[0] == '@' || buf[0] == '#')
+ return ffi_ret == NULL ? Qnil : (VALUE)ffi_ret;
+ else
+ return Qnil;
}
}
- if (ctx->cif == NULL) {
- const size_t s = sizeof(ffi_type *) * (count + 1);
- ffi_argtypes = ctx->bs_method != NULL && ctx->bs_method->variadic
- ? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
- ffi_argtypes[0] = &ffi_type_pointer;
- ffi_argtypes[1] = &ffi_type_pointer;
- }
+ const size_t s = sizeof(ffi_type *) * (count + 1);
+ ffi_argtypes = bs_method != NULL && bs_method->variadic
+ ? (ffi_type **)alloca(s) : (ffi_type **)malloc(s);
+ ffi_argtypes[0] = &ffi_type_pointer;
+ ffi_argtypes[1] = &ffi_type_pointer;
+
ffi_args = (void **)alloca(sizeof(void *) * (count + 1));
ffi_args[0] = &ocrcv;
- ffi_args[1] = &ctx->selector;
+ ffi_args[1] = &sel;
- if (super_call) {
- Method smethod;
- smethod = class_getInstanceMethod(klass, ctx->selector);
- if (klass == ctx->klass)
- assert(smethod != ctx->method);
- imp = method_getImplementation(smethod);
- assert(imp != NULL);
- }
- else {
- if (ctx->imp != NULL && ctx->klass == klass) {
- imp = ctx->imp;
- }
- else {
- ctx->imp = imp = method_getImplementation(ctx->method);
- ctx->klass = klass;
- }
- }
-
for (i = 0; i < argc; i++) {
ffi_type *ffi_argtype;
- type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method,
+ type = rb_objc_method_get_type(method, real_count, bs_method,
i, buf, sizeof buf);
- if (ctx->cif == NULL) {
- ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
- assert(ffi_argtypes[i + 2]->size > 0);
- ffi_argtype = ffi_argtypes[i + 2];
- }
- else {
- ffi_argtype = ctx->cif->arg_types[i + 2];
- }
-
+ ffi_argtypes[i + 2] = rb_objc_octype_to_ffitype(type);
+ assert(ffi_argtypes[i + 2]->size > 0);
+ ffi_argtype = ffi_argtypes[i + 2];
ffi_args[i + 2] = (void *)alloca(ffi_argtype->size);
rb_objc_rval_to_ocval(argv[i], type, ffi_args[i + 2]);
}
- if (ctx->cif == NULL)
- ffi_argtypes[count] = NULL;
+ ffi_argtypes[count] = NULL;
ffi_args[count] = NULL;
- type = rb_objc_method_get_type(ctx->method, real_count, ctx->bs_method,
+ type = rb_objc_method_get_type(method, real_count, bs_method,
-1, buf, sizeof buf);
- ffi_rettype = ctx->cif == NULL
- ? rb_objc_octype_to_ffitype(type) : ctx->cif->rtype;
+ ffi_rettype = rb_objc_octype_to_ffitype(type);
- cif = ctx->cif;
- if (cif == NULL) {
- if (ctx->bs_method != NULL && ctx->bs_method->variadic)
- cif = (ffi_cif *)alloca(sizeof(ffi_cif));
- else
- cif = ctx->cif = (ffi_cif *)malloc(sizeof(ffi_cif));
- if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype,
- ffi_argtypes) != FFI_OK) {
- rb_fatal("can't prepare cif for objc method type `%s'",
- method_getTypeEncoding(ctx->method));
- }
+ cif = (ffi_cif *)alloca(sizeof(ffi_cif));
+ if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, ffi_rettype,
+ ffi_argtypes) != FFI_OK) {
+ rb_fatal("can't prepare cif for objc method type `%s'",
+ method_getTypeEncoding(method));
}
+
if (ffi_rettype != &ffi_type_void) {
ffi_ret = (void *)alloca(ffi_rettype->size);
}
@@ -1231,75 +1125,89 @@
}
}
-static VALUE
-rb_objc_to_ruby_closure(int argc, VALUE *argv, VALUE rcv)
+VALUE
+rb_objc_call(VALUE recv, SEL sel, int argc, VALUE *argv)
{
- id ocrcv;
- bool super_call;
- Class klass;
- struct objc_ruby_closure_context *ctx;
+ VALUE klass;
+ Method method;
- rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
- super_call = (ruby_current_thread->cfp->flag >> FRAME_MAGIC_MASK_BITS)
- & VM_CALL_SUPER_BIT;
- klass = *(Class *)ocrcv;
-
- assert(rb_current_cfunc_node != NULL);
+ klass = CLASS_OF(recv);
+ method = class_getInstanceMethod((Class)klass, sel);
- if (rb_current_cfunc_node->u3.value == 0) {
- const char *selname;
- size_t selnamelen;
+ return rb_objc_call2(recv, klass, sel, method_getImplementation(method), method, NULL, argc, argv);
+}
- ctx = (struct objc_ruby_closure_context *)xmalloc(sizeof(
- struct objc_ruby_closure_context));
+void
+rb_objc_alias(VALUE klass, ID name, ID def)
+{
+ const char *name_str, *def_str;
+ SEL name_sel, def_sel;
+ Method method, dest_method;
+ bool redo = false;
- selname = rb_id2name(rb_frame_this_func());
- selnamelen = strlen(selname);
- if (argc == 1 && selname[selnamelen - 1] != ':') {
- char *tmp = alloca(selnamelen + 2);
- snprintf(tmp, selnamelen + 2, "%s:", selname);
- selname = (const char *)tmp;
+ name_str = rb_id2name(name);
+ def_str = rb_id2name(def);
+
+ name_sel = sel_registerName(name_str);
+ def_sel = sel_registerName(def_str);
+
+ method = class_getInstanceMethod((Class)klass, def_sel);
+ if (method == NULL) {
+ size_t len = strlen(def_str);
+ if (def_str[len - 1] != ':') {
+ char buf[100];
+
+ snprintf(buf, sizeof buf, "%s:", def_str);
+ def_sel = sel_registerName(buf);
+ method = class_getInstanceMethod((Class)klass, def_sel);
+ if (method == NULL) {
+ rb_print_undef(klass, def, 0);
+ }
+ len = strlen(name_str);
+ if (name_str[len - 1] != ':') {
+ snprintf(buf, sizeof buf, "%s:", name_str);
+ name_sel = sel_registerName(buf);
+ }
}
- ctx->selector = sel_registerName(selname);
+ }
- ctx->bs_method = rb_bs_find_method(*(Class *)ocrcv, ctx->selector);
- GC_WB(&rb_current_cfunc_node->u3.value, ctx);
+alias_method:
+
+ dest_method = class_getInstanceMethod((Class)klass, name_sel);
+
+ DLOG("ALIAS", "%c[%s %s -> %s] types=%s direct_override=%d orig_node=%p",
+ class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (char *)name_sel, (char *)def_sel, method_getTypeEncoding(method), dest_method != NULL, rb_objc_method_node3(method_getImplementation(method)));
+
+ if (dest_method != NULL
+ && dest_method != class_getInstanceMethod((Class)RCLASS_SUPER(klass), name_sel)) {
+ method_setImplementation(dest_method, method_getImplementation(method));
}
else {
- ctx = (struct objc_ruby_closure_context *)
- rb_current_cfunc_node->u3.value;
+ assert(class_addMethod((Class)klass, name_sel,
+ method_getImplementation(method),
+ method_getTypeEncoding(method)));
}
- ctx->method = class_getInstanceMethod(*(Class *)ocrcv, ctx->selector);
- assert(ctx->method != NULL);
- ctx->cif = NULL;
- ctx->imp = NULL;
- ctx->klass = klass;
- if (super_call) {
- Class sklass = klass;
- Method orig_method = ctx->klass == klass
- ? ctx->method : class_getInstanceMethod(klass, ctx->selector);
- for (;;) {
- Method smethod;
- sklass = class_getSuperclass(sklass);
- if (sklass == NULL)
- break;
- smethod = class_getInstanceMethod(sklass, ctx->selector);
- if (smethod != orig_method) {
- klass = sklass;
- break;
- }
- }
- }
-
-//NSLog(@"Ruby -> ObjC [%@ klass=%@ sel=%s argc=%d super_call=%d", ocrcv, (id)klass, (char *)ctx->selector, argc, super_call);
+ if (!redo && name_str[strlen(name_str) - 1] != ':') {
+ char buf[100];
- return rb_objc_call_objc(argc, argv, ocrcv, klass, super_call, ctx);
+ snprintf(buf, sizeof buf, "%s:", def_str);
+ def_sel = sel_registerName(buf);
+ method = class_getInstanceMethod((Class)klass, def_sel);
+ if (method != NULL) {
+ snprintf(buf, sizeof buf, "%s:", name_str);
+ name_sel = sel_registerName(buf);
+ redo = true;
+ goto alias_method;
+ }
+ }
}
static VALUE
rb_super_objc_send(int argc, VALUE *argv, VALUE rcv)
{
+ return Qnil;
+#if 0
struct objc_ruby_closure_context fake_ctx;
id ocrcv;
ID mid;
@@ -1312,7 +1220,7 @@
argv++;
argc--;
- rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
+ ocrcv = RB2OC(rcv);
klass = class_getSuperclass(*(Class *)ocrcv);
fake_ctx.selector = sel_registerName(rb_id2name(mid));
@@ -1324,6 +1232,7 @@
fake_ctx.klass = NULL;
return rb_objc_call_objc(argc, argv, ocrcv, klass, true, &fake_ctx);
+#endif
}
#define IGNORE_PRIVATE_OBJC_METHODS 1
@@ -1337,42 +1246,55 @@
ID mid;
VALUE rrcv, ret;
Method method;
- char type[128];
+ const char *type;
+ char buf[128];
long i, argc;
- VALUE *argv;
- NODE *body;
+ VALUE *argv, klass;
+ NODE *body, *node;
+ bs_element_method_t *bs_method;
rcv = (*(id **)args)[0];
sel = (*(SEL **)args)[1];
body = (NODE *)userdata;
+ node = body->nd_body;
method = class_getInstanceMethod(*(Class *)rcv, sel);
assert(method != NULL);
+ bs_method = rb_bs_find_method(*(Class *)rcv, sel);
- argc = cif->nargs - 2;
- argv = (VALUE *)alloca(sizeof(VALUE) * argc);
- for (i = 0; i < argc; i++) {
- VALUE val;
-
- method_getArgumentType(method, i + 2, type, sizeof type);
- rb_objc_ocval_to_rbval(args[i + 2], type, &val);
- argv[i] = val;
+ argc = method_getNumberOfArguments(method) - 2;
+ if (argc > 0) {
+ argv = (VALUE *)alloca(sizeof(VALUE) * argc);
+ for (i = 0; i < argc; i++) {
+ VALUE val;
+
+ type = rb_objc_method_get_type(method, cif->nargs, bs_method,
+ i, buf, sizeof buf);
+
+ rb_objc_ocval_to_rbval(args[i + 2], type, &val);
+ argv[i] = val;
+ }
}
+ else {
+ argv = NULL;
+ }
- rb_objc_ocid_to_rval(&rcv, &rrcv);
+ rrcv = rcv == NULL ? Qnil : (VALUE)rcv;
mid = rb_intern((const char *)sel);
+ klass = CLASS_OF(rrcv);
-//NSLog(@"ObjC -> Ruby [%@ mid=%s]\n", rrcv, rb_id2name(mid));
+ DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)rrcv, (char *)sel, body);
VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id,
ID oid, int argc, const VALUE *argv, const NODE *body,
int nosuper);
- ret = rb_vm_call(GET_THREAD(), CLASS_OF(rrcv), rrcv, mid, Qnil,
- argc, argv, body, 0);
+ ret = rb_vm_call(GET_THREAD(), klass, rrcv, mid, Qnil,
+ argc, argv, node, 0);
- method_getReturnType(method, type, sizeof type);
+ type = rb_objc_method_get_type(method, cif->nargs, bs_method,
+ -1, buf, sizeof buf);
rb_objc_rval_to_ocval(ret, type, resp);
}
@@ -1407,320 +1329,261 @@
!= FFI_OK)
rb_fatal("can't prepare ruby to objc closure");
+ rb_objc_retain(node);
+
return closure;
}
-void
-rb_objc_sync_ruby_method(VALUE mod, ID mid, NODE *node, unsigned override)
+NODE *
+rb_objc_method_node3(IMP imp)
{
- SEL sel;
- Class ocklass;
- Method method;
- char *types;
- int arity;
- char *mid_str;
- IMP imp;
- bool direct_override;
+ if (imp == NULL || ((ffi_closure *)imp)->fun != rb_ruby_to_objc_closure_handler)
+ return NULL;
- /* Do not expose C functions. */
- if (bs_functions != NULL
- && mod == CLASS_OF(rb_mKernel)
- && st_lookup(bs_functions, (st_data_t)mid, NULL))
- return;
-
- arity = rb_node_arity(node);
- mid_str = (char *)rb_id2name(mid);
-
- if (arity < 0) {
- //printf("mid %s has negative arity %d\n", mid_str, arity);
- return;
- }
-
- if (arity == 1 && mid_str[strlen(mid_str) - 1] != ':') {
- char buf[100];
- snprintf(buf, sizeof buf, "%s:", mid_str);
- sel = sel_registerName(buf);
- }
- else {
- sel = sel_registerName(mid_str);
- }
-
- ocklass = RCLASS_OCID(mod);
- direct_override = false;
- method = class_getInstanceMethod(ocklass, sel);
-
- if (method != NULL) {
- void *klass;
- if (!override)
- return;
-
- /* Do not override certain NSObject selectors. */
- if (sel == @selector(superclass)
- || sel == @selector(hash)
- || sel == @selector(zone)) {
- klass = RCLASS_OCID(rb_cBasicObject);
- if (class_getInstanceMethod(klass, sel) == method)
- return;
- }
-
- if (arity >= 0 && arity + 2 != method_getNumberOfArguments(method)) {
- rb_warning("cannot override Objective-C method `%s' in " \
- "class `%s' because of an arity mismatch (%d for %d)",
- (char *)sel,
- class_getName(ocklass),
- arity + 2,
- method_getNumberOfArguments(method));
- return;
- }
- types = (char *)method_getTypeEncoding(method);
- klass = class_getSuperclass(ocklass);
- direct_override =
- klass == NULL || class_getInstanceMethod(klass, sel) != method;
- }
- else {
- struct st_table *t = class_isMetaClass(ocklass)
- ? bs_inf_prot_cmethods
- : bs_inf_prot_imethods;
-
- if (t == NULL || !st_lookup(t, (st_data_t)sel, (st_data_t *)&types)) {
- types = (char *)alloca((arity + 4) * sizeof(char));
- types[0] = '@';
- types[1] = '@';
- types[2] = ':';
- memset(&types[3], '@', arity);
- types[arity + 3] = '\0';
- }
- }
-
-// printf("registering sel %s of types %s arity %d to class %s\n",
-// (char *)sel, types, arity, class_getName(ocklass));
-
- imp = rb_ruby_to_objc_closure(types, arity, node);
-
- if (method != NULL && direct_override) {
- method_setImplementation(method, imp);
- }
- else {
- assert(class_addMethod(ocklass, sel, imp, types));
- }
+ return ((ffi_closure *)imp)->user_data;
}
-static int
-__rb_objc_add_ruby_method(ID mid, NODE *body, VALUE mod)
+NODE *
+rb_objc_method_node2(VALUE mod, SEL sel, IMP *pimp)
{
- if (mid == ID_ALLOCATOR)
- return ST_CONTINUE;
-
- if (body == NULL || body->nd_body->nd_body == NULL)
- return ST_CONTINUE;
+ IMP imp;
- if ((body->nd_body->nd_noex & NOEX_MASK) != NOEX_PUBLIC)
- return ST_CONTINUE;
+ if (pimp != NULL)
+ *pimp = NULL;
- rb_objc_sync_ruby_method(mod, mid, body->nd_body->nd_body, 0);
+ imp = class_getMethodImplementation((Class)mod, sel);
+ extern void *_objc_msgForward;
+ if (imp == (IMP)&_objc_msgForward)
+ imp = NULL;
- return ST_CONTINUE;
-}
+ if (pimp != NULL)
+ *pimp = imp;
-void
-rb_objc_sync_ruby_methods(VALUE mod, VALUE klass)
-{
- for (;;) {
- st_foreach(RCLASS_M_TBL(mod), __rb_objc_add_ruby_method,
- (st_data_t)klass);
- mod = RCLASS_SUPER(mod);
- if (mod == 0 || BUILTIN_TYPE(mod) != T_ICLASS)
- break;
- }
-}
+ if (imp == NULL || ((ffi_closure *)imp)->fun != rb_ruby_to_objc_closure_handler)
+ return NULL;
-static inline unsigned
-is_ignored_selector(SEL sel)
-{
-#if defined(__ppc__)
- return sel == (SEL)0xfffef000;
-#elif defined(__i386__)
- return sel == (SEL)0xfffeb010;
-#else
-# error Unsupported arch
-#endif
+ return ((ffi_closure *)imp)->user_data;
}
-#if 0
-static void
-__rb_objc_sync_methods(VALUE mod, Class ocklass)
+NODE *
+rb_objc_method_node(VALUE mod, ID mid, IMP *pimp, SEL *psel)
{
- Method *methods;
- unsigned int i, count;
- char buffer[128];
- VALUE imod;
+ SEL sel;
+ IMP imp;
+ NODE *node;
- methods = class_copyMethodList(ocklass, &count);
+ if (mid == ID_ALLOCATOR)
+ sel = @selector(alloc);
+ else
+ sel = sel_registerName(rb_id2name(mid));
- imod = mod;
-#if 0
- for (;;) {
- st_foreach(RCLASS_M_TBL(imod), __rb_objc_add_ruby_method,
- (st_data_t)mod);
- imod = RCLASS_SUPER(imod);
- if (imod == 0 || BUILTIN_TYPE(imod) != T_ICLASS)
- break;
- }
-#endif
+ if (psel != NULL)
+ *psel = sel;
- for (i = 0; i < count; i++) {
- SEL sel;
- ID mid;
- st_data_t data;
- NODE *node;
+ node = rb_objc_method_node2(mod, sel, &imp);
- sel = method_getName(methods[i]);
- if (is_ignored_selector(sel))
- continue;
-#if IGNORE_PRIVATE_OBJC_METHODS
- if (*(char *)sel == '_')
- continue;
-#endif
+ if (pimp != NULL)
+ *pimp = imp;
- rb_objc_sel_to_mid(sel, buffer, sizeof buffer);
- mid = rb_intern(buffer);
+ if (imp == NULL) {
+ char buf[100];
+ size_t slen;
- if (rb_method_boundp(mod, mid, 1) == Qtrue)
- continue;
-
- node = NEW_CFUNC(rb_objc_to_ruby_closure(methods[i]), -2);
- data = (st_data_t)NEW_FBODY(NEW_METHOD(node, mod,
- NOEX_WITH_SAFE(NOEX_PUBLIC)), 0);
-
- st_insert(RCLASS_M_TBL(mod), mid, data);
+ slen = strlen((char *)sel);
+ if (((char *)sel)[slen - 1] == ':') {
+ return NULL;
+ }
+ strlcpy(buf, (char *)sel, sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+ sel = sel_registerName(buf);
+ if (psel != NULL)
+ *psel = sel;
+ return rb_objc_method_node2(mod, sel, pimp);
}
- free(methods);
+ return node;
}
-#endif
-NODE *
-rb_objc_define_objc_mid_closure(VALUE recv, ID mid, ID alias_mid)
+void
+rb_objc_register_ruby_method(VALUE mod, ID mid, NODE *body)
{
SEL sel;
- Class ocklass;
Method method;
- VALUE mod;
- NODE *node, *data;
- Method (*getMethod)(Class, SEL);
+ char *types;
+ int arity, oc_arity;
+ IMP imp;
+ bool direct_override;
+ NODE *node;
+ VALUE included_in_classes;
+ int included_in_classes_count = - 1;
- assert(mid > 1);
+#define forward_method_definition(ary,sel,imp,types) \
+ do { \
+ if (included_in_classes != Qnil) { \
+ int i; \
+ if (included_in_classes_count == -1) \
+ included_in_classes_count = RARRAY_LEN(included_in_classes); \
+ for (i = 0; i < included_in_classes_count; i++) { \
+ VALUE k = RARRAY_AT(included_in_classes, i); \
+ Method m = class_getInstanceMethod((Class)k, sel); \
+ DLOG("DEFI", "-[%s %s]", class_getName((Class)k), (char *)sel); \
+ if (m != NULL) { \
+ Method m2 = class_getInstanceMethod((Class)RCLASS_SUPER(k), sel); \
+ if (m != m2) { \
+ method_setImplementation(m, imp); \
+ break; \
+ } \
+ } \
+ assert(class_addMethod((Class)k, sel, imp, types)); \
+ } \
+ } \
+ } \
+ while (0)
- sel = sel_registerName(rb_id2name(mid));
+ if (body != NULL) {
+ if (nd_type(body) != NODE_METHOD)
+ rb_bug("non-method node (%d)", nd_type(body));
- if (!rb_special_const_p(recv) && !rb_objc_is_non_native(recv)
- && TYPE(recv) == T_CLASS) {
- mod = recv;
- getMethod = class_getClassMethod;
+ node = body->nd_body;
+ arity = oc_arity = rb_node_arity(node);
}
else {
- mod = CLASS_OF(recv);
- getMethod = class_getInstanceMethod;
+ node = NULL;
+ arity = oc_arity = 0;
}
- ocklass = RCLASS_OCID(mod);
+ if (mid == ID_ALLOCATOR) {
+ sel = @selector(alloc);
+ }
+ else {
+ char *mid_str;
+ size_t mid_str_len;
+ char buf[100];
- if (class_isMetaClass(ocklass))
- return NULL;
+ mid_str = (char *)rb_id2name(mid);
+ mid_str_len = strlen(mid_str);
- method = (*getMethod)(ocklass, sel);
- if (method == NULL || method_getImplementation(method) == NULL)
- return NULL; /* recv doesn't respond to this selector */
-
- do {
- Class ocsuper = class_getSuperclass(ocklass);
- if ((*getMethod)(ocsuper, sel) == NULL) /* != method */
- break;
- ocklass = ocsuper;
+ if ((arity < 0 || arity > 0) && mid_str[mid_str_len - 1] != ':') {
+ assert(sizeof(buf) > mid_str_len + 1);
+ snprintf(buf, sizeof buf, "%s:", mid_str);
+ sel = sel_registerName(buf);
+ oc_arity = 1;
+ }
+ else {
+ sel = sel_registerName(mid_str);
+ if (sel == sel_ignored || sel == sel_zone) {
+ assert(sizeof(buf) > mid_str_len + 7);
+ snprintf(buf, sizeof buf, "__rb_%s__", mid_str);
+ sel = sel_registerName(buf);
+ }
+ }
}
- while (1);
- if (RCLASS(mod)->ocklass != ocklass) {
- mod = rb_objc_import_class(ocklass);
- if (TYPE(recv) == T_CLASS)
- mod = CLASS_OF(mod);
- }
+ included_in_classes = RCLASS_MODULE(mod) ? rb_attr_get(mod, idIncludedInClasses) : Qnil;
- /* Already defined. */
- node = rb_method_node(mod, mid);
- if (node != NULL)
- return node;
+ direct_override = false;
+ method = class_getInstanceMethod((Class)mod, sel);
- node = NEW_CFUNC(rb_objc_to_ruby_closure, -1);
- data = NEW_FBODY(NEW_METHOD(node, mod,
- NOEX_WITH_SAFE(NOEX_PUBLIC)), 0);
+ if (method != NULL) {
+ Class klass;
- rb_add_method_direct(mod, mid, data);
+ if (oc_arity + 2 != method_getNumberOfArguments(method)) {
+ rb_warn("cannot override Objective-C method `%s' in " \
+ "class `%s' because of an arity mismatch (%d for %d)",
+ (char *)method_getName(method),
+ class_getName((Class)mod),
+ oc_arity + 2,
+ method_getNumberOfArguments(method));
+ return;
+ }
+ types = (char *)method_getTypeEncoding(method);
+ klass = (Class)RCLASS_SUPER(mod);
+ direct_override =
+ klass == NULL || class_getInstanceMethod(klass, sel) != method;
+ }
+ else {
+ struct st_table *t = class_isMetaClass((Class)mod)
+ ? bs_inf_prot_cmethods
+ : bs_inf_prot_imethods;
- if (alias_mid != 0)
- rb_add_method_direct(mod, alias_mid, data);
+ if (t == NULL || !st_lookup(t, (st_data_t)sel, (st_data_t *)&types)) {
+ if (oc_arity == 0) {
+ types = "@@:";
+ }
+ else if (oc_arity == 1) {
+ types = "@@:@";
+ }
+ else {
+ int i;
+ types = alloca(3 + oc_arity + 1);
+ types[0] = '@';
+ types[1] = '@';
+ types[2] = ':';
+ for (i = 0; i < oc_arity; i++)
+ types[3 + i] = '@';
+ types[3 + oc_arity] = '\0';
+ }
+ }
+ }
- return data->nd_body;
-}
+ DLOG("DEFM", "%c[%s %s] types=%s arity=%d body=%p override=%d direct_override=%d",
+ class_isMetaClass((Class)mod) ? '+' : '-', class_getName((Class)mod), (char *)sel, types, arity, body, method != NULL, direct_override);
-#if 0
-rb_objc_sync_objc_methods_into(VALUE mod, Class ocklass)
-{
- /* Load instance methods */
- __rb_objc_sync_methods(mod, ocklass);
+ imp = body == NULL ? NULL : rb_ruby_to_objc_closure(types, oc_arity, body);
- /* Load class methods */
- __rb_objc_sync_methods(rb_singleton_class(mod),
- object_getClass((id)ocklass));
-}
-
-void
-rb_objc_sync_objc_methods(VALUE mod)
-{
- rb_objc_sync_objc_methods_into(mod, RCLASS_OCID(mod));
-}
-#endif
-
-VALUE
-rb_mod_objc_ancestors(VALUE recv)
-{
- void *klass;
- VALUE ary;
-
- ary = rb_ary_new();
-
- for (klass = RCLASS(recv)->ocklass; klass != NULL;
- klass = class_getSuperclass(klass)) {
- rb_ary_push(ary, rb_str_new2(class_getName(klass)));
+ if (method != NULL && direct_override) {
+ method_setImplementation(method, imp);
}
+ else {
+ assert(class_addMethod((Class)mod, sel, imp, types));
+ }
+ forward_method_definition(included_in_classes, sel, imp, types);
- return ary;
-}
+ if (node != NULL) {
+ const char *sel_str = (const char *)sel;
+ const size_t sel_len = strlen(sel_str);
+ SEL new_sel;
+ char *new_types;
+ bool override;
-void
-rb_objc_methods(VALUE ary, Class ocklass)
-{
- while (ocklass != NULL) {
- unsigned i, count;
- Method *methods;
+ if (sel_str[sel_len - 1] == ':') {
+ char buf[100];
+ strlcpy(buf, sel_str, sizeof buf);
+ assert(sizeof buf > sel_len);
+ buf[sel_len - 1] = '\0';
+ new_sel = sel_registerName(buf);
+ new_types = "@@:";
+ override = arity == -1 || arity == -2;
+ arity = 0;
+ }
+ else {
+ char buf[100];
+ strlcpy(buf, sel_str, sizeof buf);
+ strlcat(buf, ":", sizeof buf);
+ new_sel = sel_registerName(buf);
+ new_types = "@@:@";
+ override = false;
+ arity = -1;
+ }
- methods = class_copyMethodList(ocklass, &count);
- if (methods != NULL) {
- for (i = 0; i < count; i++) {
- SEL sel = method_getName(methods[i]);
- if (is_ignored_selector(sel))
- continue;
- rb_ary_push(ary, ID2SYM(rb_intern(sel_getName(sel))));
+ method = class_getInstanceMethod((Class)mod, new_sel);
+ direct_override = false;
+ if (method != NULL || override) {
+ direct_override = method != NULL && class_getInstanceMethod((Class)RCLASS_SUPER(mod), new_sel) != method;
+ DLOG("DEFM", "%c[%s %s] types=%s arity=%d body=%p override=%d direct_override=%d",
+ class_isMetaClass((Class)mod) ? '+' : '-', class_getName((Class)mod), (char *)new_sel, new_types, arity, body, method != NULL, direct_override);
+ if (method != NULL && direct_override) {
+ method_setImplementation(method, imp);
}
- free(methods);
- }
- ocklass = class_getSuperclass(ocklass);
+ else {
+ assert(class_addMethod((Class)mod, new_sel, imp, new_types));
+ }
+ forward_method_definition(included_in_classes, new_sel, imp, new_types);
+ }
}
-
- rb_funcall(ary, rb_intern("uniq!"), 0);
}
-static bool
+static inline bool
rb_objc_resourceful(VALUE obj)
{
/* TODO we should export this function in the runtime
@@ -1738,36 +1601,21 @@
return false;
}
-static VALUE
-bs_function_dispatch(int argc, VALUE *argv, VALUE recv)
+VALUE
+rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv)
{
- ID callee;
- bs_element_function_t *bs_func;
- void *sym;
unsigned i;
ffi_type *ffi_rettype, **ffi_argtypes;
void *ffi_ret, **ffi_args;
ffi_cif *cif;
VALUE resp;
- callee = rb_frame_this_func();
- assert(callee > 1);
- if (!st_lookup(bs_functions, (st_data_t)callee, (st_data_t *)&bs_func))
- rb_bug("bridgesupport function `%s' not in cache", rb_id2name(callee));
-
- if (!st_lookup(bs_function_syms, (st_data_t)callee, (st_data_t *)&sym)
- || sym == NULL) {
- sym = dlsym(RTLD_DEFAULT, bs_func->name);
- if (sym == NULL)
- rb_bug("cannot locate symbol for bridgesupport function `%s'",
- bs_func->name);
- st_insert(bs_function_syms, (st_data_t)callee, (st_data_t)sym);
- }
-
if (argc != bs_func->args_count)
rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
argc, bs_func->args_count);
+ DLOG("FCALL", "%s() sym=%p argc=%d", bs_func->name, sym, argc);
+
ffi_argtypes = (ffi_type **)alloca(sizeof(ffi_type *) * argc + 1);
ffi_args = (void **)alloca(sizeof(void *) * argc + 1);
@@ -1819,10 +1667,7 @@
void *sym;
bs_element_constant_t *bs_const;
- if (v == rb_objc_class_magic_cookie) {
- v = rb_objc_import_class(objc_getClass(rb_id2name(id)));
- }
- else if (v == bs_const_magic_cookie) {
+ if (v == bs_const_magic_cookie) {
if (!st_lookup(bs_constants, (st_data_t)id, (st_data_t *)&bs_const))
rb_bug("unresolved bridgesupport constant `%s' not in cache",
rb_id2name(id));
@@ -1833,15 +1678,10 @@
"constant `%s'", bs_const->name);
rb_objc_ocval_to_rbval(sym, bs_const->type, &v);
-
- /* To avoid a runtime warning when re-defining the constant, we remove
- * its entry from the table before.
- */
- klass = rb_cObject;
- assert(RCLASS_IV_TBL(klass) != NULL);
- assert(st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&id, NULL));
- rb_const_set(klass, id, v);
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
+ assert(iv_dict != NULL);
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)v);
}
return v;
@@ -1901,13 +1741,18 @@
static ID
rb_bs_struct_field_ivar_id(void)
{
+ const char *frame_str;
char ivar_name[128];
- int len;
+ size_t len;
- len = snprintf(ivar_name, sizeof ivar_name, "@%s",
- rb_id2name(rb_frame_this_func()));
+ frame_str = rb_id2name(rb_frame_this_func());
+ len = snprintf(ivar_name, sizeof ivar_name, "@%s", frame_str);
+
+ if (ivar_name[len - 1] == ':')
+ len--;
if (ivar_name[len - 1] == '=')
- ivar_name[len - 1] = '\0';
+ len--;
+ ivar_name[len] = '\0';
return rb_intern(ivar_name);
}
@@ -2224,16 +2069,25 @@
bs_parse_cb(const char *path, bs_element_type_t type, void *value, void *ctx)
{
bool do_not_free = false;
+ static CFMutableDictionaryRef rb_cObject_dict = NULL;
+
+ if (rb_cObject_dict == NULL) {
+ rb_cObject_dict = rb_class_ivar_dict(rb_cObject);
+ assert(rb_cObject_dict != NULL);
+ }
+
switch (type) {
case BS_ELEMENT_ENUM:
{
bs_element_enum_t *bs_enum = (bs_element_enum_t *)value;
ID name = generate_const_name(bs_enum->name);
- if (!rb_const_defined(rb_cObject, name)) {
+ if (!CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
VALUE val = strchr(bs_enum->value, '.') != NULL
? rb_float_new(rb_cstr_to_dbl(bs_enum->value, 1))
: rb_cstr_to_inum(bs_enum->value, 10, 1);
- rb_const_set(rb_cObject, name, val);
+ CFDictionarySetValue(rb_cObject_dict, (const void *)name,
+ (const void *)val);
}
else {
rb_warning("bs: enum `%s' already defined", rb_id2name(name));
@@ -2245,9 +2099,11 @@
{
bs_element_constant_t *bs_const = (bs_element_constant_t *)value;
ID name = generate_const_name(bs_const->name);
- if (!rb_const_defined(rb_cObject, name)) {
+ if (!CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
st_insert(bs_constants, (st_data_t)name, (st_data_t)bs_const);
- rb_const_set(rb_cObject, name, bs_const_magic_cookie);
+ CFDictionarySetValue(rb_cObject_dict, (const void *)name,
+ (const void *)bs_const_magic_cookie);
do_not_free = true;
}
else {
@@ -2262,7 +2118,8 @@
bs_element_string_constant_t *bs_strconst =
(bs_element_string_constant_t *)value;
ID name = generate_const_name(bs_strconst->name);
- if (!rb_const_defined(rb_cObject, name)) {
+ if (!CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)rb_cObject_dict, (const void *)name, NULL)) {
VALUE val;
if (bs_strconst->nsstring) {
CFStringRef string;
@@ -2273,7 +2130,8 @@
else {
val = rb_str_new2(bs_strconst->value);
}
- rb_const_set(rb_cObject, name, val);
+ CFDictionarySetValue(rb_cObject_dict, (const void *)name,
+ (const void *)val);
}
else {
rb_warning("bs: string constant `%s' already defined",
@@ -2286,11 +2144,8 @@
{
bs_element_function_t *bs_func = (bs_element_function_t *)value;
ID name = rb_intern(bs_func->name);
- if (1) {
+ if (!st_lookup(bs_functions, (st_data_t)name, NULL)) {
st_insert(bs_functions, (st_data_t)name, (st_data_t)bs_func);
- /* FIXME we should reuse the same node for all functions */
- rb_define_global_function(
- bs_func->name, bs_function_dispatch, -1);
do_not_free = true;
}
else {
@@ -2303,8 +2158,19 @@
{
bs_element_function_alias_t *bs_func_alias =
(bs_element_function_alias_t *)value;
- rb_define_alias(CLASS_OF(rb_mKernel), bs_func_alias->name,
- bs_func_alias->original);
+ bs_element_function_t *bs_func_original;
+ if (st_lookup(bs_functions,
+ (st_data_t)rb_intern(bs_func_alias->original),
+ (st_data_t *)&bs_func_original)) {
+ st_insert(bs_functions,
+ (st_data_t)rb_intern(bs_func_alias->name),
+ (st_data_t)bs_func_original);
+ }
+ else {
+ rb_raise(rb_eRuntimeError,
+ "cannot alias '%s' to '%s' because it doesn't exist",
+ bs_func_alias->name, bs_func_alias->original);
+ }
break;
}
@@ -2433,7 +2299,7 @@
if (name[0] != '_') {
ID id = rb_intern(name);
if (!rb_const_defined(rb_cObject, id))
- rb_const_set(rb_cObject, id, rb_objc_class_magic_cookie);
+ rb_const_set(rb_cObject, id, (VALUE)buf[i]);
}
}
@@ -2592,18 +2458,19 @@
}
static void
-rb_install_objc_primitives(void)
+rb_install_boxed_primitives(void)
{
Class klass;
/* Boxed */
- klass = RCLASS_OCID(rb_cBoxed);
+ klass = (Class)rb_cBoxed;
rb_objc_install_method(klass, @selector(objCType),
(IMP)imp_rb_boxed_objCType);
rb_objc_install_method(klass, @selector(getValue:),
(IMP)imp_rb_boxed_getValue);
}
+#if 0
static void *
rb_objc_allocate(void *klass)
{
@@ -2640,57 +2507,8 @@
rb_objc_install_method(RCLASS_OCID(rb_cObject), @selector(init),
(IMP)imp_rb_obj_init);
}
+#endif
-ID
-rb_objc_missing_sel(ID mid, int arity)
-{
- const char *name;
- size_t len;
- char buf[100];
-
- if (mid == 0)
- return mid;
-
- name = rb_id2name(mid);
- if (name == NULL)
- return mid;
-
- len = strlen(name);
- if (len == 0)
- return mid;
-
- if (arity == 1 && name[len - 1] == '=') {
- strlcpy(buf, "set", sizeof buf);
- buf[3] = toupper(name[0]);
- buf[4] = '\0';
- strlcat(buf, &name[1], sizeof buf);
- buf[len + 2] = ':';
- }
- else if (arity == 0 && name[len - 1] == '?') {
- strlcpy(buf, "is", sizeof buf);
- buf[2] = toupper(name[0]);
- buf[3] = '\0';
- strlcat(buf, &name[1], sizeof buf);
- buf[len + 1] = '\0';
- }
- else if (arity >= 1 && name[len - 1] != ':' && len < sizeof buf) {
- strlcpy(buf, name, sizeof buf);
- buf[len] = ':';
- buf[len + 1] = '\0';
- }
- else if (arity == 1 && name[len - 1] == ':' && len < sizeof buf) {
- strlcpy(buf, name, sizeof buf);
- buf[len - 1] = '\0';
- }
- else {
- return mid;
- }
-
- //printf("new sel %s for %s\n", buf, name);
-
- return rb_intern(buf);
-}
-
static const char *
resources_path(char *path, size_t len)
{
@@ -2752,7 +2570,6 @@
const char *selname;
char buf[128];
size_t s;
- VALUE rvalue;
selname = sel_getName(sel);
buf[0] = '@';
@@ -2760,15 +2577,14 @@
s = strlcpy(&buf[2], &selname[4], sizeof buf - 2);
buf[s + 1] = '\0';
- rb_objc_ocid_to_rval(&value, &rvalue);
- rb_ivar_set((VALUE)recv, rb_intern(buf), rvalue);
+ rb_ivar_set((VALUE)recv, rb_intern(buf), value == NULL ? Qnil : (VALUE)value);
}
VALUE
rb_mod_objc_ib_outlet(int argc, VALUE *argv, VALUE recv)
{
int i;
- char buf[128];
+ char buf[100];
buf[0] = 's'; buf[1] = 'e'; buf[2] = 't';
@@ -2777,7 +2593,7 @@
const char *symname;
Check_Type(sym, T_SYMBOL);
- symname = rb_id2name(SYM2ID(sym));
+ symname = rb_sym2name(sym);
if (strlen(symname) == 0)
rb_raise(rb_eArgError, "empty symbol given");
@@ -2787,7 +2603,7 @@
strlcat(buf, &symname[1], sizeof buf);
strlcat(buf, ":", sizeof buf);
- if (!class_addMethod(RCLASS_OCID(recv), sel_registerName(buf),
+ if (!class_addMethod((Class)recv, sel_registerName(buf),
(IMP)rb_objc_ib_outlet_imp, "v@:@"))
rb_raise(rb_eArgError,
"can't register `%s' (method %s) as an IB outlet",
@@ -3067,7 +2883,6 @@
{
rb_objc_retain(bs_constants = st_init_numtable());
rb_objc_retain(bs_functions = st_init_numtable());
- rb_objc_retain(bs_function_syms = st_init_numtable());
rb_objc_retain(bs_boxeds = st_init_strtable());
rb_objc_retain(bs_classes = st_init_strtable());
rb_objc_retain(bs_inf_prot_cmethods = st_init_numtable());
@@ -3076,14 +2891,13 @@
rb_objc_retain((const void *)(
bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie")));
- rb_objc_retain((const void *)(
- rb_objc_class_magic_cookie = rb_str_new2("rb_objc_class_magic_cookie")));
- rb_cBoxed = rb_define_class("Boxed",
- rb_objc_import_class(objc_getClass("NSValue")));
+ rb_cBoxed = rb_define_class("Boxed", (VALUE)objc_getClass("NSValue"));
+ RCLASS_SET_VERSION_FLAG(rb_cBoxed, RCLASS_IS_OBJECT_SUBCLASS);
rb_define_singleton_method(rb_cBoxed, "objc_type", rb_boxed_objc_type, 0);
rb_define_singleton_method(rb_cBoxed, "opaque?", rb_boxed_is_opaque, 0);
rb_define_singleton_method(rb_cBoxed, "fields", rb_boxed_fields, 0);
+ rb_install_boxed_primitives();
rb_cPointer = rb_define_class("Pointer", rb_cObject);
rb_undef_alloc_func(rb_cPointer);
@@ -3091,8 +2905,7 @@
rb_ivar_type = rb_intern("@__objc_type__");
- rb_install_objc_primitives();
- rb_install_alloc_methods();
+ //rb_install_alloc_methods();
rb_define_global_function("load_bridge_support_file", rb_objc_load_bs, 1);
@@ -3106,6 +2919,9 @@
rb_define_method(rb_cBasicObject, "__super_objc_send__", rb_super_objc_send, -1);
}
+// for debug in gdb
+int __rb_type(VALUE v) { return TYPE(v); }
+
@interface Protocol
@end
Modified: MacRuby/trunk/object.c
===================================================================
--- MacRuby/trunk/object.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/object.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,20 +1,19 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's object.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- object.c -
-
- $Author: nobu $
- created at: Thu Jul 15 12:01:24 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "debug.h"
+#include "id.h"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
@@ -23,6 +22,7 @@
VALUE rb_cBasicObject;
VALUE rb_mKernel;
+VALUE rb_cNSObject;
VALUE rb_cObject;
VALUE rb_cModule;
VALUE rb_cClass;
@@ -128,7 +128,9 @@
{
if (cl == 0)
return 0;
- while ((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS) {
+ if (RCLASS_META(cl))
+ return rb_cClass;
+ while (RCLASS_SINGLETON(cl)) {
cl = RCLASS_SUPER(cl);
}
return cl;
@@ -157,13 +159,11 @@
static void
init_copy(VALUE dest, VALUE obj)
{
-#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
+ if (NATIVE(obj)) {
if (rb_objc_flag_check((const void *)obj, FL_TAINT))
rb_objc_flag_set((const void *)dest, FL_TAINT, true);
goto call_init_copy;
}
-#endif
if (OBJ_FROZEN(dest)) {
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
@@ -172,36 +172,58 @@
rb_copy_generic_ivar(dest, obj);
rb_gc_copy_finalizer(dest, obj);
switch (TYPE(obj)) {
- case T_OBJECT:
- if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
- xfree(ROBJECT_IVPTR(dest));
- ROBJECT(dest)->as.heap.ivptr = 0;
- ROBJECT(dest)->as.heap.numiv = 0;
- ROBJECT(dest)->as.heap.iv_index_tbl = 0;
- }
- if (RBASIC(obj)->flags & ROBJECT_EMBED) {
- MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX);
- RBASIC(dest)->flags |= ROBJECT_EMBED;
- }
- else {
- long len = ROBJECT(obj)->as.heap.numiv;
- VALUE *ptr = ALLOC_N(VALUE, len);
- MEMCPY(ptr, ROBJECT(obj)->as.heap.ivptr, VALUE, len);
- ROBJECT(dest)->as.heap.ivptr = ptr;
- ROBJECT(dest)->as.heap.numiv = len;
- ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
- RBASIC(dest)->flags &= ~ROBJECT_EMBED;
- }
+ case T_NATIVE:
+ if (rb_objc_flag_check((const void *)obj, FL_TAINT))
+ rb_objc_flag_set((const void *)dest, FL_TAINT, true);
break;
+
+ case T_OBJECT:
+ ROBJECT(dest)->ivars.type = ROBJECT(obj)->ivars.type;
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ GC_WB(&ROBJECT(dest)->ivars.as.ary,
+ (struct rb_ivar_ary_entry *)xmalloc(
+ sizeof(struct rb_ivar_ary_entry)
+ * RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars)));
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ ROBJECT(dest)->ivars.as.ary[i].name = ROBJECT(obj)->ivars.as.ary[i].name;
+ GC_WB(&ROBJECT(dest)->ivars.as.ary[i].value, ROBJECT(obj)->ivars.as.ary[i].value);
+ }
+ }
+ break;
+
+ case RB_IVAR_TBL:
+ {
+ CFMutableDictionaryRef new_tbl;
+ new_tbl = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl);
+ assert(new_tbl != NULL);
+ GC_WB(&ROBJECT(dest)->ivars.as.tbl, new_tbl);
+ CFMakeCollectable(new_tbl);
+ }
+ break;
+ }
+ break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(dest)) {
- st_free_table(RCLASS_IV_TBL(dest));
- RCLASS_IV_TBL(dest) = 0;
+ {
+ CFMutableDictionaryRef dest_dict, obj_dict;
+
+ obj_dict = rb_class_ivar_dict(obj);
+ dest_dict = rb_class_ivar_dict(dest);
+ if (dest_dict != NULL)
+ CFDictionaryRemoveAllValues(dest_dict);
+ if (obj_dict != NULL) {
+ dest_dict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)obj_dict);
+ CFMakeCollectable(dest_dict);
+ rb_class_ivar_set_dict(dest, dest_dict);
+ }
+ else {
+ if (dest_dict)
+ rb_class_ivar_set_dict(dest, NULL);
+ }
}
- if (RCLASS_IV_TBL(obj)) {
- RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
- }
break;
}
call_init_copy:
@@ -232,6 +254,8 @@
* the class.
*/
+static VALUE rb_class_s_alloc(VALUE);
+
VALUE
rb_obj_clone(VALUE obj)
{
@@ -240,23 +264,25 @@
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
}
-#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
- clone = rb_obj_alloc(rb_obj_class(obj));
- init_copy(clone, obj);
- if (OBJ_FROZEN(obj))
- OBJ_FREEZE(clone);
- return clone;
+ switch (TYPE(obj)) {
+ case T_NATIVE:
+ clone = rb_obj_alloc(rb_obj_class(obj));
+ RBASIC(clone)->klass = rb_singleton_class_clone(obj);
+ break;
+ case T_CLASS:
+ case T_MODULE:
+ clone = rb_class_s_alloc(Qnil);
+ break;
+ default:
+ clone = rb_obj_alloc(rb_obj_class(obj));
+ RBASIC(clone)->klass = rb_singleton_class_clone(obj);
+ RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
+ break;
}
-#endif
- clone = rb_obj_alloc(rb_obj_class(obj));
-#if WITH_OBJC
- RBASIC(clone)->isa = RBASIC(obj)->isa;
-#endif
- RBASIC(clone)->klass = rb_singleton_class_clone(obj);
- RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT)) & ~(FL_FREEZE|FL_FINALIZE);
+
init_copy(clone, obj);
- RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+ if (OBJ_FROZEN(obj))
+ OBJ_FREEZE(clone);
return clone;
}
@@ -284,7 +310,7 @@
{
VALUE dup;
- if (rb_special_const_p(obj)) {
+ if (rb_special_const_p(obj) || TYPE(obj) == T_SYMBOL) {
rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
}
dup = rb_obj_alloc(rb_obj_class(obj));
@@ -293,13 +319,20 @@
return dup;
}
+static VALUE
+rb_nsobj_dup(VALUE obj)
+{
+ return (VALUE)objc_msgSend((id)obj, selCopy);
+}
+
/* :nodoc: */
VALUE
rb_obj_init_copy(VALUE obj, VALUE orig)
{
if (obj == orig) return obj;
rb_check_frozen(obj);
- if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
+ if (TYPE(obj) != TYPE(orig)) {
+ /* FIXME rb_obj_class(obj) != rb_obj_class(orig) */
rb_raise(rb_eTypeError, "initialize_copy should take same class object");
}
return obj;
@@ -347,11 +380,7 @@
if (!rb_is_instance_id(id)) return ST_CONTINUE;
if (cstr[0] == '-') { /* first element */
-#if WITH_OBJC
rb_str_update(str, 0, 0, rb_str_new2("#"));
-#else
- RSTRING_BYTEPTR(str)[0] = '#';
-#endif
rb_str_cat2(str, " ");
}
else {
@@ -377,11 +406,7 @@
rb_ivar_foreach(obj, inspect_i, str);
}
rb_str_cat2(str, ">");
-#if WITH_OBJC
rb_str_update(str, 0, 0, rb_str_new2("#"));
-#else
- RSTRING_BYTEPTR(str)[0] = '#';
-#endif
OBJ_INFECT(str, obj);
return str;
@@ -406,17 +431,28 @@
if (TYPE(obj) == T_OBJECT) {
int has_ivar = 0;
- VALUE *ptr = ROBJECT_IVPTR(obj);
- long len = ROBJECT_NUMIV(obj);
- long i;
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i, len = RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars);
+ if (len == 0)
+ break;
+ for (i = 0; i < len; i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].value != Qundef) {
+ has_ivar = 1;
+ break;
+ }
+ }
+ break;
+ }
- for (i = 0; i < len; i++) {
- if (ptr[i] != Qundef) {
- has_ivar = 1;
- break;
- }
- }
-
+ case RB_IVAR_TBL:
+ has_ivar =
+ CFDictionaryGetCount(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl)
+ > 0;
+ break;
+ }
if (has_ivar) {
VALUE str;
const char *c = rb_obj_classname(obj);
@@ -496,7 +532,7 @@
}
while (cl) {
- if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
+ if (cl == c) // TODO check included modules
return Qtrue;
cl = RCLASS_SUPER(cl);
}
@@ -676,11 +712,9 @@
VALUE
rb_obj_tainted(VALUE obj)
{
-#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
return rb_objc_flag_check((const void *)obj, FL_TAINT) ? Qtrue : Qfalse;
}
-#endif
if (FL_TEST(obj, FL_TAINT))
return Qtrue;
return Qfalse;
@@ -699,12 +733,10 @@
rb_obj_taint(VALUE obj)
{
rb_secure(4);
-#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_TAINT, true);
return obj;
}
-#endif
if (!OBJ_TAINTED(obj)) {
if (OBJ_FROZEN(obj)) {
rb_error_frozen("object");
@@ -726,12 +758,10 @@
rb_obj_untaint(VALUE obj)
{
rb_secure(3);
-#if WITH_OBJC
- if (!SPECIAL_CONST_P(obj) && rb_objc_is_non_native(obj)) {
+ if (!SPECIAL_CONST_P(obj) && NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_TAINT, false);
return obj;
}
-#endif
if (OBJ_TAINTED(obj)) {
if (OBJ_FROZEN(obj)) {
rb_error_frozen("object");
@@ -772,6 +802,7 @@
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
+ int type;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
}
@@ -782,11 +813,12 @@
}
st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
}
-#if WITH_OBJC
- else if (rb_objc_is_non_native(obj)) {
+ else if (NATIVE(obj)) {
rb_objc_flag_set((const void *)obj, FL_FREEZE, true);
}
-#endif
+ else if ((type = TYPE(obj)) == T_CLASS || type == T_MODULE) {
+ RCLASS_SET_VERSION_FLAG(obj, RCLASS_IS_FROZEN);
+ }
else {
FL_SET(obj, FL_FREEZE);
}
@@ -813,15 +845,21 @@
if (st_lookup(immediate_frozen_tbl, obj, 0)) return Qtrue;
return Qfalse;
}
-#if WITH_OBJC
- if (rb_objc_is_non_native(obj)) {
- return rb_objc_is_immutable(obj)
- || rb_objc_flag_check((const void *)obj, FL_FREEZE)
- ? Qtrue : Qfalse;
+ switch (TYPE(obj)) {
+ case T_STRING:
+ case T_ARRAY:
+ case T_HASH:
+ case T_NATIVE:
+ return rb_objc_is_immutable(obj)
+ || rb_objc_flag_check((const void *)obj, FL_FREEZE)
+ ? Qtrue : Qfalse;
+ case T_CLASS:
+ case T_ICLASS:
+ case T_MODULE:
+ return (RCLASS_VERSION(obj) & RCLASS_IS_FROZEN) == RCLASS_IS_FROZEN ? Qtrue : Qfalse;
+ default:
+ return FL_TEST(obj, FL_FREEZE) ? Qtrue : Qfalse;
}
-#endif
- if (FL_TEST(obj, FL_FREEZE)) return Qtrue;
- return Qfalse;
}
@@ -1155,7 +1193,7 @@
static VALUE
rb_mod_to_s(VALUE klass)
{
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
VALUE s = rb_usascii_str_new2("#<");
VALUE v = rb_iv_get(klass, "__attached__");
@@ -1231,13 +1269,13 @@
rb_raise(rb_eTypeError, "compared with non class/module");
}
while (mod) {
- if (RCLASS_M_TBL(mod) == RCLASS_M_TBL(arg))
+ if (mod == arg)
return Qtrue;
mod = RCLASS_SUPER(mod);
}
/* not mod < arg; check if mod > arg */
while (arg) {
- if (RCLASS_M_TBL(arg) == RCLASS_M_TBL(start))
+ if (arg == start)
return Qfalse;
arg = RCLASS_SUPER(arg);
}
@@ -1343,10 +1381,7 @@
static VALUE
rb_module_s_alloc(VALUE klass)
{
- VALUE mod = rb_module_new();
-
- RBASIC(mod)->klass = klass;
- return mod;
+ return rb_module_new();
}
static VALUE
@@ -1378,7 +1413,7 @@
* a.meth2 #=> "bye"
*/
-static VALUE
+ VALUE
rb_mod_initialize(VALUE module)
{
extern VALUE rb_mod_module_exec(int argc, VALUE *argv, VALUE mod);
@@ -1404,9 +1439,6 @@
{
VALUE super;
- if (RCLASS_SUPER(klass) != 0) {
- rb_raise(rb_eTypeError, "already initialized class");
- }
if (argc == 0) {
super = rb_cObject;
}
@@ -1415,11 +1447,7 @@
rb_check_inheritable(super);
}
RCLASS_SUPER(klass) = super;
-#if WITH_OBJC
- class_setSuperclass(RCLASS(klass)->ocklass, RCLASS(super)->ocklass);
- rb_objc_install_primitives(RCLASS(klass)->ocklass, RCLASS(super)->ocklass);
-#endif
- rb_make_metaclass(klass, RBASIC(super)->klass);
+ rb_objc_install_primitives((Class)klass, (Class)super);
rb_class_inherited(super, klass);
rb_mod_initialize(klass);
@@ -1443,26 +1471,13 @@
if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_raise(rb_eTypeError, "can't create instance of singleton class");
}
obj = rb_funcall(klass, ID_ALLOCATOR, 0, 0);
-#if !WITH_OBJC
- if (rb_obj_class(obj) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "wrong instance allocation");
- }
-#endif
return obj;
}
-static VALUE
-rb_class_allocate_instance(VALUE klass)
-{
- NEWOBJ(obj, struct RObject);
- OBJSETUP(obj, klass, T_OBJECT);
- return (VALUE)obj;
-}
-
/*
* call-seq:
* class.new(args, ...) => obj
@@ -1478,56 +1493,25 @@
VALUE
rb_class_new_instance(int argc, VALUE *argv, VALUE klass)
{
- VALUE obj;
+ VALUE obj, init_obj, p;
-#if WITH_OBJC
- if (FL_TEST(klass, RCLASS_OBJC_IMPORTED)) {
- static SEL sel_new = 0;
- if (sel_new == 0)
- sel_new = sel_registerName("new");
- obj = (VALUE)objc_msgSend((id)RCLASS_OCID(klass), sel_new);
- return obj;
- }
-#endif
obj = rb_obj_alloc(klass);
- rb_obj_call_init(obj, argc, argv);
+ init_obj = rb_obj_call_init(obj, argc, argv);
+ if (init_obj != Qnil) {
+ p = CLASS_OF(init_obj);
+ while (p != 0) {
+ if (p == klass)
+ return init_obj;
+ p = RCLASS_SUPER(p);
+ }
+ }
+
return obj;
}
/*
* call-seq:
- * class.superclass -> a_super_class or nil
- *
- * Returns the superclass of <i>class</i>, or <code>nil</code>.
- *
- * File.superclass #=> IO
- * IO.superclass #=> Object
- * Object.superclass #=> BasicObject
- * BasicObject.superclass #=> nil
- *
- */
-
-static VALUE
-rb_class_superclass(VALUE klass)
-{
- VALUE super = RCLASS_SUPER(klass);
-
- if (!super) {
- if (klass == rb_cBasicObject) return Qnil;
- rb_raise(rb_eTypeError, "uninitialized class");
- }
- while (TYPE(super) == T_ICLASS) {
- super = RCLASS_SUPER(super);
- }
- if (!super) {
- return Qnil;
- }
- return super;
-}
-
-/*
- * call-seq:
* attr_reader(symbol, ...) => nil
* attr(symbol, ...) => nil
*
@@ -1713,28 +1697,21 @@
static VALUE
rb_obj_methods(int argc, VALUE *argv, VALUE obj)
{
- retry:
- if (argc == 0) {
- VALUE args[1];
- VALUE ary;
+ VALUE recur, objc_methods;
+ VALUE args[2];
- args[0] = Qtrue;
- ary = rb_class_instance_methods(1, args, CLASS_OF(obj));
-#if WITH_OBJC
- rb_objc_methods(ary, RCLASS(CLASS_OF(obj))->ocklass);
-#endif
- return ary;
+ if (argc == 0) {
+ recur = Qtrue;
+ objc_methods = Qfalse;
}
else {
- VALUE recur;
-
- rb_scan_args(argc, argv, "1", &recur);
- if (RTEST(recur)) {
- argc = 0;
- goto retry;
- }
- return rb_obj_singleton_methods(argc, argv, obj);
+ rb_scan_args(argc, argv, "02", &recur, &objc_methods);
}
+
+ args[0] = recur;
+ args[1] = objc_methods;
+
+ return rb_class_instance_methods(2, args, CLASS_OF(obj));
}
/*
@@ -2347,26 +2324,23 @@
{
ID id = rb_intern(name);
extern st_table *rb_class_tbl;
-#if WITH_OBJC
VALUE obj = rb_objc_create_class(name, super);
-#else
- VALUE obj = rb_class_boot(super);
-
- rb_name_class(obj, id);
-#endif
st_add_direct(rb_class_tbl, id, obj);
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
return obj;
}
-#if WITH_OBJC
static VALUE
-rb_obj_is_pure(VALUE recv)
+rb_obj_is_native(VALUE recv)
{
- return rb_objc_is_non_native(recv) ? Qtrue : Qfalse;
+ return NATIVE(recv) ? Qtrue : Qfalse;
}
-#endif
+static VALUE
+rb_class_is_meta(VALUE klass)
+{
+ return RCLASS_META(klass) ? Qtrue : Qfalse;
+}
/*
* Document-class: Class
@@ -2450,39 +2424,25 @@
void
Init_Object(void)
{
- VALUE metaclass;
-
-#if WITH_OBJC
- rb_cBasicObject = rb_objc_import_class((Class)objc_getClass("NSObject"));
-#else
- rb_cBasicObject = boot_defclass("BasicObject", 0);
-#endif
- rb_cObject = boot_defclass("Object", rb_cBasicObject);
+ rb_cNSObject = rb_cObject = (VALUE)objc_getClass("NSObject");
+ rb_const_set(rb_cObject, rb_intern("Object"), rb_cNSObject);
+ rb_cBasicObject = rb_cObject; // TODO
rb_cModule = boot_defclass("Module", rb_cObject);
rb_cClass = boot_defclass("Class", rb_cModule);
+ RCLASS_SUPER(*(Class *)rb_cNSObject) = rb_cClass;
- metaclass = rb_make_metaclass(rb_cBasicObject, rb_cClass);
- metaclass = rb_make_metaclass(rb_cObject, metaclass);
- metaclass = rb_make_metaclass(rb_cModule, metaclass);
- metaclass = rb_make_metaclass(rb_cClass, metaclass);
-
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
- rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
- rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
- rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);
- rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0);
- rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1);
+ rb_define_method(rb_cNSObject, "==", rb_obj_equal, 1);
+ rb_define_method(rb_cNSObject, "equal?", rb_obj_equal, 1);
+ rb_define_method(rb_cNSObject, "!", rb_obj_not, 0);
+ rb_define_method(rb_cNSObject, "!=", rb_obj_not_equal, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy, 1);
rb_mKernel = rb_define_module("Kernel");
-#if WITH_OBJC
- rb_include_module(rb_cBasicObject, rb_mKernel);
-#else
rb_include_module(rb_cObject, rb_mKernel);
-#endif
rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
@@ -2496,10 +2456,8 @@
rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
- rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
- rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
- rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
- rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
+ rb_define_method(rb_cNSObject, "clone", rb_obj_clone, 0);
+ rb_define_method(rb_cNSObject, "dup", rb_nsobj_dup, 0);
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
@@ -2526,9 +2484,7 @@
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
-#if WITH_OBJC
- rb_define_method(rb_mKernel, "__pure__?", rb_obj_is_pure, 0);
-#endif
+ rb_define_method(rb_mKernel, "__native__?", rb_obj_is_native, 0);
rb_define_global_function("sprintf", rb_f_sprintf, -1); /* in sprintf.c */
rb_define_global_function("format", rb_f_sprintf, -1); /* in sprintf.c */
@@ -2568,10 +2524,8 @@
rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1); /* in class.c */
rb_define_method(rb_cModule, "name", rb_mod_name, 0); /* in variable.c */
rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0); /* in class.c */
-#if WITH_OBJC
- rb_define_method(rb_cModule, "objc_ancestors", rb_mod_objc_ancestors, 0); /* in objc.m */
rb_define_private_method(rb_cModule, "ib_outlet", rb_mod_objc_ib_outlet, -1); /* in objc.m */
-#endif
+ rb_define_method(rb_cClass, "__meta__?", rb_class_is_meta, 0);
rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
@@ -2608,7 +2562,6 @@
rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
- rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
rb_undef_method(rb_cClass, "extend_object");
rb_undef_method(rb_cClass, "append_features");
Modified: MacRuby/trunk/parse.y
===================================================================
--- MacRuby/trunk/parse.y 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/parse.y 2008-08-21 06:13:14 UTC (rev 459)
@@ -31,6 +31,7 @@
#define YYREALLOC(ptr, size) rb_parser_realloc(parser, ptr, size)
#define YYCALLOC(nelem, size) rb_parser_calloc(parser, nelem, size)
#define YYFREE(ptr) rb_parser_free(parser, ptr)
+static inline void *orig_malloc(size_t l) { return malloc(l); }
#define malloc YYMALLOC
#define realloc YYREALLOC
#define calloc YYCALLOC
@@ -8699,7 +8700,7 @@
p != NULL;
p = p->nd_next, flip = !flip) {
if (flip) {
- strlcat(buf, rb_id2name(SYM2ID(p->nd_head->nd_lit)),
+ strlcat(buf, rb_sym2name(p->nd_head->nd_lit),
sizeof buf);
strlcat(buf, ":", sizeof buf);
}
@@ -9118,12 +9119,11 @@
#if WITH_OBJC
CFMutableDictionaryRef sym_id;
CFMutableDictionaryRef id_str;
- VALUE *op_sym;
#else
st_table *sym_id;
st_table *id_str;
+#endif
VALUE op_sym[tLAST_TOKEN];
-#endif
} global_symbols = {tLAST_TOKEN >> ID_SCOPE_SHIFT};
static const struct st_hash_type symhash = {
@@ -9164,10 +9164,9 @@
0, NULL, NULL);
GC_ROOT(&global_symbols.sym_id);
global_symbols.id_str = CFDictionaryCreateMutable(NULL,
- 0, NULL, &kCFTypeDictionaryValueCallBacks);
+ 0, NULL, NULL);
GC_ROOT(&global_symbols.id_str);
- global_symbols.op_sym = xmalloc(sizeof(VALUE) * tLAST_TOKEN);
- GC_ROOT(&global_symbols.op_sym);
+ rb_cSymbol = rb_objc_create_class("Symbol", (VALUE)objc_getClass("NSString"));
#else
global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
global_symbols.id_str = st_init_numtable_with_size(1000);
@@ -9331,6 +9330,23 @@
return *m ? Qfalse : Qtrue;
}
+#if WITH_OBJC
+static inline VALUE
+rsymbol_new(const char *name, const int len, ID id)
+{
+ VALUE sym;
+
+ sym = (VALUE)orig_malloc(sizeof(struct RSymbol));
+ RSYMBOL(sym)->str = orig_malloc(len + 1);
+ RSYMBOL(sym)->klass = rb_cSymbol;
+ strcpy(RSYMBOL(sym)->str, name);
+ RSYMBOL(sym)->len = len;
+ RSYMBOL(sym)->id = id;
+
+ return sym;
+}
+#endif
+
ID
rb_intern3(const char *name, long len, rb_encoding *enc)
{
@@ -9364,6 +9380,17 @@
e = m + len;
}
SEL name_hash = sel_registerName(name);
+ if (name_hash == sel_ignored) {
+ if (strcmp(name, "retain") == 0) {
+ name_hash = (SEL)0x1000;
+ }
+ else if (strcmp(name, "release") == 0) {
+ name_hash = (SEL)0x2000;
+ }
+ else {
+ assert(1==0);
+ }
+ }
id = (ID)CFDictionaryGetValue((CFDictionaryRef)global_symbols.sym_id,
(const void *)name_hash);
if (id != 0)
@@ -9464,8 +9491,7 @@
new_id:
id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
id_register:
- str = rb_enc_str_new(name, len, enc);
- OBJ_FREEZE(str);
+ str = rsymbol_new(name, len, id);
#if WITH_OBJC
CFDictionarySetValue(global_symbols.sym_id, (const void *)name_hash,
(const void *)id);
@@ -9498,21 +9524,23 @@
ID
rb_intern_str(VALUE str)
{
- rb_encoding *enc;
ID id;
#if WITH_OBJC
+ const char *s = RSTRING_PTR(str);
+ id = rb_intern3(s, strlen(s), NULL);
+#else
+ rb_encoding *enc;
enc = rb_enc_get(str);
-#else
if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
enc = rb_usascii_encoding();
}
else {
enc = rb_enc_get(str);
}
-#endif
id = rb_intern3(RSTRING_PTR(str), RSTRING_LEN(str), enc);
RB_GC_GUARD(str);
+#endif
return id;
}
@@ -9528,9 +9556,13 @@
if (op_tbl[i].token == id) {
VALUE str = global_symbols.op_sym[i];
if (!str) {
+#if WITH_OBJC
+ str = rsymbol_new(op_tbl[i].name, strlen(op_tbl[i].name), op_tbl[i].token);
+#else
str = rb_usascii_str_new2(op_tbl[i].name);
OBJ_FREEZE(str);
- GC_WB(&global_symbols.op_sym[i], str);
+#endif
+ global_symbols.op_sym[i] = str;
}
return str;
}
@@ -9581,6 +9613,7 @@
return 0;
}
+#if !WITH_OBJC
const char *
rb_id2name(ID id)
{
@@ -9589,13 +9622,16 @@
if (!str) return 0;
return RSTRING_PTR(str);
}
+#endif
+#if !WITH_OBJC
static int
symbols_i(VALUE sym, ID value, VALUE ary)
{
rb_ary_push(ary, ID2SYM(value));
return ST_CONTINUE;
}
+#endif
/*
* call-seq:
@@ -9617,9 +9653,17 @@
rb_sym_all_symbols(void)
{
#if WITH_OBJC
- VALUE ary = rb_ary_new();
- CFDictionaryApplyFunction((CFDictionaryRef)global_symbols.sym_id,
- (CFDictionaryApplierFunction)symbols_i, (void *)ary);
+ const void **values;
+ long count;
+ VALUE ary;
+
+ ary = rb_ary_new();
+ count = CFDictionaryGetCount(global_symbols.id_str);
+ if (count == 0)
+ return ary;
+ values = alloca(sizeof(void *) * count);
+ CFDictionaryGetKeysAndValues(global_symbols.id_str, NULL, values);
+ CFArrayReplaceValues((CFMutableArrayRef)ary, CFRangeMake(0, 0), values, count);
#else
VALUE ary = rb_ary_new2(global_symbols.sym_id->num_entries);
Modified: MacRuby/trunk/proc.c
===================================================================
--- MacRuby/trunk/proc.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/proc.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -757,7 +757,7 @@
}
while (rclass != klass &&
- (FL_TEST(rclass, FL_SINGLETON) || TYPE(rclass) == T_ICLASS)) {
+ (RCLASS_SINGLETON(rclass) || TYPE(rclass) == T_ICLASS)) {
rclass = RCLASS_SUPER(rclass);
}
if (TYPE(klass) == T_ICLASS)
@@ -770,7 +770,9 @@
data->body = body;
data->rclass = rclass;
data->oid = oid;
+#if !WITH_OBJC
OBJ_INFECT(method, klass);
+#endif
return method;
}
@@ -877,7 +879,9 @@
data->body = orig->body;
data->rclass = orig->rclass;
data->oid = orig->oid;
+#if !WITH_OBJC
OBJ_INFECT(method, obj);
+#endif
return method;
}
@@ -1080,7 +1084,7 @@
struct METHOD *method = (struct METHOD *)DATA_PTR(body);
VALUE rclass = method->rclass;
if (rclass != mod) {
- if (FL_TEST(rclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(rclass)) {
rb_raise(rb_eTypeError,
"can't bind singleton method to a different class");
}
@@ -1299,7 +1303,7 @@
Data_Get_Struct(method, struct METHOD, data);
if (data->rclass != CLASS_OF(recv)) {
- if (FL_TEST(data->rclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(data->rclass)) {
rb_raise(rb_eTypeError,
"singleton method called for a different object");
}
@@ -1435,7 +1439,7 @@
rb_str_buf_cat2(str, s);
rb_str_buf_cat2(str, ": ");
- if (FL_TEST(data->oclass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(data->oclass)) {
VALUE v = rb_iv_get(data->oclass, "__attached__");
if (data->recv == Qundef) {
Modified: MacRuby/trunk/process.c
===================================================================
--- MacRuby/trunk/process.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/process.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -3279,7 +3279,7 @@
switch (TYPE(rtype)) {
case T_SYMBOL:
- name = rb_id2name(SYM2ID(rtype));
+ name = rb_sym2name(rtype);
break;
default:
@@ -3312,7 +3312,7 @@
switch (TYPE(rval)) {
case T_SYMBOL:
- name = rb_id2name(SYM2ID(rval));
+ name = rb_sym2name(rval);
break;
default:
Modified: MacRuby/trunk/re.c
===================================================================
--- MacRuby/trunk/re.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/re.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1040,7 +1040,7 @@
return NUM2INT(backref);
case T_SYMBOL:
- name = rb_id2name(SYM2ID(backref));
+ name = rb_sym2name(backref);
break;
case T_STRING:
@@ -1383,7 +1383,7 @@
if (!reverse) {
range += RSTRING_LEN(str);
}
- MEMZERO(®s, struct re_registers, 1);
+ MEMZERO(pregs, struct re_registers, 1);
result = onig_search(RREGEXP(re)->ptr,
(UChar*)cstr,
((UChar*)cstr + clen),
@@ -1728,7 +1728,7 @@
switch (TYPE(idx)) {
case T_SYMBOL:
- p = rb_id2name(SYM2ID(idx));
+ p = rb_sym2name(idx);
goto name_to_backref;
break;
case T_STRING:
Modified: MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb
===================================================================
--- MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/sample-macruby/OutlineView/DataSource.rb 2008-08-21 06:13:14 UTC (rev 459)
@@ -14,10 +14,7 @@
def outlineView outlineView, objectValueForTableColumn:tableColumn, byItem:item
if item
- # relativePath returns an ASCII-8BIT file name
- s = item.relativePath.dup
- s.force_encoding('utf-8')
- s
+ s = item.relativePath
else
'/'
end
Modified: MacRuby/trunk/signal.c
===================================================================
--- MacRuby/trunk/signal.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/signal.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -247,7 +247,7 @@
}
}
else {
- signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
+ signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
if (strncmp(signm, "SIG", 3) == 0) signm += 3;
signo = signm2signo(signm);
if (!signo) {
@@ -337,7 +337,7 @@
break;
case T_SYMBOL:
- s = rb_id2name(SYM2ID(argv[0]));
+ s = rb_sym2name(argv[0]);
if (!s) rb_raise(rb_eArgError, "bad signal");
goto str_signal;
@@ -797,7 +797,7 @@
break;
case T_SYMBOL:
- s = rb_id2name(SYM2ID(vsig));
+ s = rb_sym2name(vsig);
if (!s) rb_raise(rb_eArgError, "bad signal");
goto str_signal;
Modified: MacRuby/trunk/st.c
===================================================================
--- MacRuby/trunk/st.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/st.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -9,6 +9,7 @@
#include "ruby/config.h"
#include "ruby/defines.h"
#include "ruby/st.h"
+#include "ruby/ruby.h"
#endif
#include <stdio.h>
@@ -173,7 +174,7 @@
tbl->num_entries = 0;
tbl->entries_packed = type == &type_numhash && size/2 <= MAX_PACKED_NUMHASH;
tbl->num_bins = size;
- tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+ GC_WB(&tbl->bins, (st_table_entry **)Calloc(size, sizeof(st_table_entry*)));
tbl->head = 0;
return tbl;
@@ -472,8 +473,8 @@
}
*new_table = *old_table;
- new_table->bins = (st_table_entry**)
- Calloc((unsigned)num_bins, sizeof(st_table_entry*));
+ GC_WB(&new_table->bins, (st_table_entry**)
+ Calloc((unsigned)num_bins, sizeof(st_table_entry*)));
if (new_table->bins == 0) {
free(new_table);
@@ -497,7 +498,7 @@
*entry = *ptr;
hash_val = entry->hash % num_bins;
entry->next = new_table->bins[hash_val];
- new_table->bins[hash_val] = entry;
+ GC_WB(&new_table->bins[hash_val], entry);
entry->back = prev;
*tail = prev = entry;
tail = &entry->fore;
Modified: MacRuby/trunk/string.c
===================================================================
--- MacRuby/trunk/string.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/string.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -1,19 +1,18 @@
-/**********************************************************************
+/*
+ * MacRuby implementation of Ruby 1.9's string.c.
+ *
+ * This file is covered by the Ruby license. See COPYING for more details.
+ *
+ * Copyright (C) 2007-2008, Apple Inc. All rights reserved.
+ * Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ */
- string.c -
-
- $Author: nobu $
- created at: Mon Aug 9 17:12:58 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
#include "ruby/ruby.h"
#include "ruby/re.h"
#include "ruby/encoding.h"
+#include "id.h"
#define BEG(no) regs->beg[no]
#define END(no) regs->end[no]
@@ -26,78 +25,11 @@
#endif
VALUE rb_cString;
-#if WITH_OBJC
VALUE rb_cCFString;
-VALUE rb_cStringRuby;
-#endif
+VALUE rb_cNSString;
+VALUE rb_cNSMutableString;
VALUE rb_cSymbol;
-#if !WITH_OBJC
-#define STR_TMPLOCK FL_USER7
-#define STR_NOEMBED FL_USER1
-#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
-#define STR_ASSOC FL_USER3
-#define STR_SHARED_P(s) FL_ALL(s, STR_NOEMBED|ELTS_SHARED)
-#define STR_ASSOC_P(s) FL_ALL(s, STR_NOEMBED|STR_ASSOC)
-#define STR_NOCAPA (STR_NOEMBED|ELTS_SHARED|STR_ASSOC)
-#define STR_NOCAPA_P(s) (FL_TEST(s,STR_NOEMBED) && FL_ANY(s,ELTS_SHARED|STR_ASSOC))
-#define STR_UNSET_NOCAPA(s) do {\
- if (FL_TEST(s,STR_NOEMBED)) FL_UNSET(s,(ELTS_SHARED|STR_ASSOC));\
-} while (0)
-
-
-#define STR_SET_NOEMBED(str) do {\
- FL_SET(str, STR_NOEMBED);\
- STR_SET_EMBED_LEN(str, 0);\
-} while (0)
-#define STR_SET_EMBED(str) FL_UNSET(str, STR_NOEMBED)
-#define STR_EMBED_P(str) (!FL_TEST(str, STR_NOEMBED))
-#define STR_SET_EMBED_LEN(str, n) do { \
- long tmp_n = (n);\
- RBASIC(str)->flags &= ~RSTRING_EMBED_LEN_MASK;\
- RBASIC(str)->flags |= (tmp_n) << RSTRING_EMBED_LEN_SHIFT;\
-} while (0)
-
-#define STR_SET_LEN(str, n) do { \
- if (STR_EMBED_P(str)) {\
- STR_SET_EMBED_LEN(str, n);\
- }\
- else {\
- RSTRING(str)->as.heap.len = (n);\
- }\
-} while (0)
-
-#define STR_DEC_LEN(str) do {\
- if (STR_EMBED_P(str)) {\
- long n = RSTRING_BYTELEN(str);\
- n--;\
- STR_SET_EMBED_LEN(str, n);\
- }\
- else {\
- RSTRING(str)->as.heap.len--;\
- }\
-} while (0)
-
-#define RESIZE_CAPA(str,capacity) do {\
- if (STR_EMBED_P(str)) {\
- if ((capacity) > RSTRING_EMBED_LEN_MAX) {\
- char *tmp = ALLOC_N(char, capacity+1);\
- memcpy(tmp, RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str));\
- GC_WB(&RSTRING(str)->as.heap.ptr, tmp); \
- RSTRING(str)->as.heap.len = RSTRING_BYTELEN(str);\
- STR_SET_NOEMBED(str);\
- RSTRING(str)->as.heap.aux.capa = (capacity);\
- }\
- }\
- else {\
- REALLOC_N(RSTRING(str)->as.heap.ptr, char, (capacity)+1);\
- if (!STR_NOCAPA_P(str))\
- RSTRING(str)->as.heap.aux.capa = (capacity);\
- }\
-} while (0)
-
-#else
-
static void *rb_str_cfdata_key;
static inline void
@@ -213,253 +145,15 @@
{
return rb_objc_str_is_bytestring(str) ? Qtrue : Qfalse;
}
-#endif
-#if WITH_OBJC
-/* TODO */
-# define is_ascii_string(str) (1)
-# define is_broken_string(str) (0)
-# define STR_ENC_GET(str) (NULL)
-#else
-# define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
-# define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
-# define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
-#endif
+#define is_ascii_string(str) (1)
+#define is_broken_string(str) (0)
+#define STR_ENC_GET(str) (NULL)
+#define str_mod_check(x,y,z)
-#if !WITH_OBJC
-static int
-single_byte_optimizable(VALUE str)
-{
- rb_encoding *enc = STR_ENC_GET(str);
-
- if (rb_enc_mbmaxlen(enc) == 1)
- return 1;
-
- /* Conservative. It may be ENC_CODERANGE_UNKNOWN. */
- if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
- return 1;
-
- /* Conservative. Possibly single byte.
- * "\xa1" in Shift_JIS for example. */
- return 0;
-}
-#endif
-
VALUE rb_fs;
-#if !WITH_OBJC
-static inline const char *
-search_nonascii(const char *p, const char *e)
-{
-#if SIZEOF_VALUE == 8
-# define NONASCII_MASK 0x8080808080808080LL
-#elif SIZEOF_VALUE == 4
-# define NONASCII_MASK 0x80808080UL
-#endif
-#ifdef NONASCII_MASK
- if (sizeof(long) * 2 < e - p) {
- const unsigned long *s, *t;
- const VALUE lowbits = sizeof(unsigned long) - 1;
- s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
- while (p < (const char *)s) {
- if (!ISASCII(*p))
- return p;
- p++;
- }
- t = (const unsigned long*)(~lowbits & (VALUE)e);
- while (s < t) {
- if (*s & NONASCII_MASK) {
- t = s;
- break;
- }
- s++;
- }
- p = (const char *)t;
- }
-#endif
- while (p < e) {
- if (!ISASCII(*p))
- return p;
- p++;
- }
- return NULL;
-}
-
-static int
-coderange_scan(const char *p, long len, rb_encoding *enc)
-{
- const char *e = p + len;
-
- if (rb_enc_to_index(enc) == 0) {
- /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
- p = search_nonascii(p, e);
- return p ? ENC_CODERANGE_VALID : ENC_CODERANGE_7BIT;
- }
-
- if (rb_enc_asciicompat(enc)) {
- p = search_nonascii(p, e);
- if (!p) {
- return ENC_CODERANGE_7BIT;
- }
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(ret)) {
- return ENC_CODERANGE_BROKEN;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- if (p < e) {
- p = search_nonascii(p, e);
- if (!p) {
- return ENC_CODERANGE_VALID;
- }
- }
- }
- if (e < p) {
- return ENC_CODERANGE_BROKEN;
- }
- return ENC_CODERANGE_VALID;
- }
-
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
-
- if (!MBCLEN_CHARFOUND_P(ret)) {
- return ENC_CODERANGE_BROKEN;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- if (e < p) {
- return ENC_CODERANGE_BROKEN;
- }
- return ENC_CODERANGE_VALID;
-}
-
-long
-rb_str_coderange_scan_restartable(const char *s, const char *e, rb_encoding *enc, int *cr)
-{
- const char *p = s;
-
- if (*cr == ENC_CODERANGE_BROKEN)
- return e - s;
-
- if (rb_enc_to_index(enc) == 0) {
- /* enc is ASCII-8BIT. ASCII-8BIT string never be broken. */
- p = search_nonascii(p, e);
- *cr = (!p && *cr != ENC_CODERANGE_VALID) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
- return e - s;
- }
- else if (rb_enc_asciicompat(enc)) {
- p = search_nonascii(p, e);
- if (!p) {
- if (*cr != ENC_CODERANGE_VALID) *cr = ENC_CODERANGE_7BIT;
- return e - s;
- }
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(ret)) {
- *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
- return p - s;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- if (p < e) {
- p = search_nonascii(p, e);
- if (!p) {
- *cr = ENC_CODERANGE_VALID;
- return e - s;
- }
- }
- }
- *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID;
- return p - s;
- }
- else {
- while (p < e) {
- int ret = rb_enc_precise_mbclen(p, e, enc);
- if (!MBCLEN_CHARFOUND_P(ret)) {
- *cr = MBCLEN_INVALID_P(ret) ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_UNKNOWN;
- return p - s;
- }
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- *cr = e < p ? ENC_CODERANGE_BROKEN: ENC_CODERANGE_VALID;
- return p - s;
- }
-}
-
-static void
-rb_enc_cr_str_copy_for_substr(VALUE dest, VALUE src)
-{
- /* this function is designed for copying encoding and coderange
- * from src to new string "dest" which is made from the part of src.
- */
- rb_enc_copy(dest, src);
- switch (ENC_CODERANGE(src)) {
- case ENC_CODERANGE_7BIT:
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- break;
- case ENC_CODERANGE_VALID:
- if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
- search_nonascii(RSTRING_BYTEPTR(dest), RSTRING_END(dest)))
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
- else
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- break;
- default:
- if (RSTRING_BYTELEN(dest) == 0) {
- if (!rb_enc_asciicompat(STR_ENC_GET(src)))
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_VALID);
- else
- ENC_CODERANGE_SET(dest, ENC_CODERANGE_7BIT);
- }
- break;
- }
- }
-
-static void
-rb_enc_cr_str_exact_copy(VALUE dest, VALUE src)
-{
- rb_enc_copy(dest, src);
- ENC_CODERANGE_SET(dest, ENC_CODERANGE(src));
-}
-
-int
-rb_enc_str_coderange(VALUE str)
-{
- int cr = ENC_CODERANGE(str);
-
- if (cr == ENC_CODERANGE_UNKNOWN) {
- rb_encoding *enc = STR_ENC_GET(str);
- cr = coderange_scan(RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str), enc);
- ENC_CODERANGE_SET(str, cr);
- }
- return cr;
-}
-
-int
-rb_enc_str_asciionly_p(VALUE str)
-{
- rb_encoding *enc = STR_ENC_GET(str);
-
- if (!rb_enc_asciicompat(enc))
- return Qfalse;
- else if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
- return Qtrue;
- return Qfalse;
-}
-#endif
-
static inline void
-str_mod_check(VALUE s, const char *p, long len)
-{
-#if !WITH_OBJC
- /* TODO */
- if (RSTRING_BYTEPTR(s) != p || RSTRING_BYTELEN(s) != len){
- rb_raise(rb_eRuntimeError, "string modified");
- }
-#endif
-}
-
-static inline void
str_frozen_check(VALUE s)
{
if (OBJ_FROZEN(s)) {
@@ -470,33 +164,19 @@
static VALUE
str_alloc(VALUE klass)
{
-#if WITH_OBJC
VALUE str;
str = (VALUE)CFStringCreateMutable(NULL, 0);
if (klass != 0
- && klass != rb_cString
- && klass != rb_cStringRuby
+ && klass != rb_cNSString
+ && klass != rb_cNSMutableString
&& klass != rb_cSymbol)
- *(Class *)str = RCLASS_OCID(klass);
+ *(Class *)str = (Class)klass;
CFMakeCollectable((CFTypeRef)str);
-#else
- NEWOBJ(str, struct RString);
- OBJSETUP(str, klass, T_STRING);
- if (klass == rb_cSymbol) {
- /* need to be registered in table */
- RBASIC(str)->klass = rb_cString;
- }
- str->as.heap.ptr = 0;
- str->as.heap.len = 0;
- str->as.heap.aux.capa = 0;
-#endif
-
return (VALUE)str;
}
-#if WITH_OBJC
static void
rb_objc_str_set_bytestring(VALUE str, const char *dataptr, long datalen)
{
@@ -511,7 +191,6 @@
rb_str_cfdata_set(str, data);
CFMakeCollectable(data);
}
-#endif
static VALUE
str_new(VALUE klass, const char *ptr, long len)
@@ -523,7 +202,6 @@
}
str = str_alloc(klass);
-#if WITH_OBJC
bool need_padding = len > 0;
if (ptr != NULL && len > 0) {
long slen;
@@ -561,18 +239,7 @@
rb_gc_malloc_increase(32 + (sizeof(UniChar) * len));
if (need_padding)
CFStringPad((CFMutableStringRef)str, CFSTR(" "), len, 0);
-#else
- if (len > RSTRING_EMBED_LEN_MAX) {
- RSTRING(str)->as.heap.aux.capa = len;
- GC_WB(&RSTRING(str)->as.heap.ptr, ALLOC_N(char,len+1));
- STR_SET_NOEMBED(str);
- }
- if (ptr) {
- memcpy(RSTRING_BYTEPTR(str), ptr, len);
- }
- STR_SET_LEN(str, len);
- RSTRING_BYTEPTR(str)[len] = '\0';
-#endif
+
return str;
}
@@ -587,7 +254,6 @@
{
VALUE str = str_new(rb_cString, ptr, len);
- //ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
return str;
}
@@ -596,8 +262,6 @@
{
VALUE str = str_new(rb_cString, ptr, len);
- // TODO we should pass the real encoding
- //rb_enc_associate(str, enc);
return str;
}
@@ -637,112 +301,9 @@
return str;
}
-#if !WITH_OBJC
static VALUE
-str_replace_shared(VALUE str2, VALUE str)
-{
- if (RSTRING_BYTELEN(str) <= RSTRING_EMBED_LEN_MAX) {
- STR_SET_EMBED(str2);
- memcpy(RSTRING_BYTEPTR(str2), RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str)+1);
- STR_SET_EMBED_LEN(str2, RSTRING_BYTELEN(str));
- }
- else {
- FL_SET(str2, STR_NOEMBED);
- RSTRING(str2)->as.heap.len = RSTRING_BYTELEN(str);
- RSTRING(str2)->as.heap.ptr = RSTRING_BYTEPTR(str);
- RSTRING(str2)->as.heap.aux.shared = str;
- FL_SET(str2, ELTS_SHARED);
- }
- rb_enc_cr_str_exact_copy(str2, str);
-
- return str2;
-}
-
-static VALUE
-str_new_shared(VALUE klass, VALUE str)
-{
- return str_replace_shared(str_alloc(klass), str);
-}
-
-static VALUE
str_new3(VALUE klass, VALUE str)
{
- return str_new_shared(klass, str);
-}
-
-VALUE
-rb_str_new3(VALUE str)
-{
- VALUE str2 = str_new3(rb_obj_class(str), str);
-
- OBJ_INFECT(str2, str);
- return str2;
-}
-
-static VALUE
-str_new4(VALUE klass, VALUE str)
-{
- VALUE str2;
-
- str2 = str_alloc(klass);
- STR_SET_NOEMBED(str2);
- RSTRING(str2)->as.heap.len = RSTRING_BYTELEN(str);
- RSTRING(str2)->as.heap.ptr = RSTRING_BYTEPTR(str);
- if (STR_SHARED_P(str)) {
- FL_SET(str2, ELTS_SHARED);
- RSTRING(str2)->as.heap.aux.shared = RSTRING(str)->as.heap.aux.shared;
- }
- else {
- FL_SET(str, ELTS_SHARED);
- RSTRING(str)->as.heap.aux.shared = str2;
- }
- rb_enc_cr_str_exact_copy(str2, str);
- OBJ_INFECT(str2, str);
- return str2;
-}
-
-VALUE
-rb_str_new4(VALUE orig)
-{
- VALUE klass, str;
-
- if (OBJ_FROZEN(orig)) return orig;
- klass = rb_obj_class(orig);
- if (STR_SHARED_P(orig) && (str = RSTRING(orig)->as.heap.aux.shared)) {
- long ofs;
- ofs = RSTRING_BYTELEN(str) - RSTRING_BYTELEN(orig);
- if ((ofs > 0) || (klass != RBASIC(str)->klass) ||
- (!OBJ_TAINTED(str) && OBJ_TAINTED(orig))) {
- str = str_new3(klass, str);
- RSTRING(str)->as.heap.ptr += ofs;
- RSTRING(str)->as.heap.len -= ofs;
- }
- rb_enc_cr_str_exact_copy(str, orig);
- OBJ_INFECT(str, orig);
- }
- else if (STR_EMBED_P(orig)) {
- str = str_new(klass, RSTRING_BYTEPTR(orig), RSTRING_BYTELEN(orig));
- rb_enc_cr_str_exact_copy(str, orig);
- OBJ_INFECT(str, orig);
- }
- else if (STR_ASSOC_P(orig)) {
- VALUE assoc = RSTRING(orig)->as.heap.aux.shared;
- FL_UNSET(orig, STR_ASSOC);
- str = str_new4(klass, orig);
- FL_SET(str, STR_ASSOC);
- RSTRING(str)->as.heap.aux.shared = assoc;
- }
- else {
- str = str_new4(klass, orig);
- }
- OBJ_FREEZE(str);
- return str;
-}
-#else
-
-static VALUE
-str_new3(VALUE klass, VALUE str)
-{
return rb_str_dup(str);
}
@@ -751,7 +312,6 @@
{
VALUE str2 = str_new3(rb_obj_class(str), str);
- // TODO OBJ_INFECT(str2, str);
return str2;
}
@@ -760,7 +320,6 @@
{
return rb_str_new3(orig);
}
-#endif
VALUE
rb_str_new5(VALUE obj, const char *ptr, long len)
@@ -775,16 +334,6 @@
{
VALUE str = str_alloc(rb_cString);
-#if !WITH_OBJC
- if (capa < STR_BUF_MIN_SIZE) {
- capa = STR_BUF_MIN_SIZE;
- }
- FL_SET(str, STR_NOEMBED);
- RSTRING(str)->as.heap.aux.capa = capa;
- GC_WB(&RSTRING(str)->as.heap.ptr, ALLOC_N(char, capa+1));
- RSTRING(str)->as.heap.ptr[0] = '\0';
-#endif
-
return str;
}
@@ -806,16 +355,6 @@
return str_new(0, 0, len);
}
-void
-rb_str_free(VALUE str)
-{
-#if !WITH_OBJC
- if (!STR_EMBED_P(str) && !STR_SHARED_P(str)) {
- xfree(RSTRING(str)->as.heap.ptr);
- }
-#endif
-}
-
VALUE
rb_str_to_str(VALUE str)
{
@@ -825,46 +364,8 @@
void
rb_str_shared_replace(VALUE str, VALUE str2)
{
-#if WITH_OBJC
rb_str_modify(str);
CFStringReplaceAll((CFMutableStringRef)str, (CFStringRef)str2);
-#else
- rb_encoding *enc;
- int cr;
- if (str == str2) return;
- enc = STR_ENC_GET(str2);
- cr = ENC_CODERANGE(str2);
- rb_str_modify(str);
- if (OBJ_TAINTED(str2)) OBJ_TAINT(str);
- if (RSTRING_BYTELEN(str2) <= RSTRING_EMBED_LEN_MAX) {
- STR_SET_EMBED(str);
- memcpy(RSTRING_BYTEPTR(str), RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2)+1);
- STR_SET_EMBED_LEN(str, RSTRING_BYTELEN(str2));
- rb_enc_associate(str, enc);
- ENC_CODERANGE_SET(str, cr);
- return;
- }
- if (!STR_SHARED_P(str) && !STR_EMBED_P(str)) {
- xfree(RSTRING_BYTEPTR(str));
- }
- STR_SET_NOEMBED(str);
- STR_UNSET_NOCAPA(str);
- RSTRING(str)->as.heap.ptr = RSTRING_BYTEPTR(str2);
- RSTRING(str)->as.heap.len = RSTRING_BYTELEN(str2);
- if (STR_NOCAPA_P(str2)) {
- FL_SET(str, RBASIC(str2)->flags & STR_NOCAPA);
- RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared;
- }
- else {
- RSTRING(str)->as.heap.aux.capa = RSTRING(str2)->as.heap.aux.capa;
- }
- RSTRING(str2)->as.heap.ptr = 0; /* abandon str2 */
- RSTRING(str2)->as.heap.len = 0;
- RSTRING(str2)->as.heap.aux.capa = 0;
- STR_UNSET_NOCAPA(str2);
- rb_enc_associate(str, enc);
- ENC_CODERANGE_SET(str, cr);
-#endif
}
static ID id_to_s;
@@ -889,18 +390,31 @@
VALUE
rb_str_dup(VALUE str)
{
- VALUE dup = str_alloc(rb_obj_class(str));
- rb_str_replace(dup, str);
-#if WITH_OBJC
- {
- void *data = rb_str_cfdata2(str);
- if (data != NULL)
- rb_str_cfdata_set(dup, data);
- }
-#endif
+ VALUE dup;
+ void *data;
+
+ dup = (VALUE)CFStringCreateMutableCopy(NULL, 0, (CFStringRef)str);
+
+ data = rb_str_cfdata2(str);
+ if (data != NULL)
+ rb_str_cfdata_set(dup, data);
+
+ if (OBJ_TAINTED(str))
+ OBJ_TAINT(dup);
+
+ CFMakeCollectable((CFTypeRef)dup);
+
return dup;
}
+static VALUE
+rb_str_clone(VALUE str)
+{
+ VALUE clone = rb_str_dup(str);
+ if (OBJ_FROZEN(str))
+ OBJ_FREEZE(clone);
+ return clone;
+}
/*
* call-seq:
@@ -914,149 +428,18 @@
{
VALUE orig;
+ str = (VALUE)objc_msgSend((id)str, selInit);
+
if (argc > 0 && rb_scan_args(argc, argv, "01", &orig) == 1)
rb_str_replace(str, orig);
return str;
}
-#if !WITH_OBJC
-long
-rb_enc_strlen(const char *p, const char *e, rb_encoding *enc)
-{
- long c;
- const char *q;
-
- if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc);
- }
- else if (rb_enc_asciicompat(enc)) {
- c = 0;
- while (p < e) {
- if (ISASCII(*p)) {
- q = search_nonascii(p, e);
- if (!q)
- return c + (e - p);
- c += q - p;
- p = q;
- }
- p += rb_enc_mbclen(p, e, enc);
- c++;
- }
- return c;
- }
-
- for (c=0; p<e; c++) {
- p += rb_enc_mbclen(p, e, enc);
- }
- return c;
-}
-
-long
-rb_enc_strlen_cr(const char *p, const char *e, rb_encoding *enc, int *cr)
-{
- long c;
- const char *q;
- int ret;
-
- *cr = 0;
- if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- return (e - p + rb_enc_mbminlen(enc) - 1) / rb_enc_mbminlen(enc);
- }
- else if (rb_enc_asciicompat(enc)) {
- c = 0;
- while (p < e) {
- if (ISASCII(*p)) {
- q = search_nonascii(p, e);
- if (!q) {
- return c + (e - p);
- }
- c += q - p;
- p = q;
- }
- ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_CHARFOUND_P(ret)) {
- *cr |= ENC_CODERANGE_VALID;
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else {
- *cr = ENC_CODERANGE_BROKEN;
- p++;
- }
- c++;
- }
- if (!*cr) *cr = ENC_CODERANGE_7BIT;
- return c;
- }
-
- for (c=0; p<e; c++) {
- ret = rb_enc_precise_mbclen(p, e, enc);
- if (MBCLEN_CHARFOUND_P(ret)) {
- *cr |= ENC_CODERANGE_VALID;
- p += MBCLEN_CHARFOUND_LEN(ret);
- }
- else {
- *cr = ENC_CODERANGE_BROKEN;
- p++;
- }
- }
- if (!*cr) *cr = ENC_CODERANGE_7BIT;
- return c;
-}
-#endif
-
static long
str_strlen(VALUE str, rb_encoding *enc)
{
-#if WITH_OBJC
/* TODO should use CFStringGetMaximumSizeForEncoding too */
return RSTRING_LEN(str);
-#else
- const char *p, *e;
- int n, cr;
-
- if (single_byte_optimizable(str)) return RSTRING_BYTELEN(str);
- if (!enc) enc = STR_ENC_GET(str);
- p = RSTRING_BYTEPTR(str);
- e = RSTRING_END(str);
-#ifdef NONASCII_MASK
- if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
- enc == rb_utf8_encoding()) {
- long len = 0;
- if (sizeof(long) * 2 < e - p) {
- const unsigned long *s, *t;
- const VALUE lowbits = sizeof(unsigned long) - 1;
- s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
- t = (const unsigned long*)(~lowbits & (VALUE)e);
- for (len=0; p<(const char *)s; p++) {
- if (((*p)&0xC0) != 0x80) len++;
- }
- while (s < t) {
- unsigned long d = *s;
- d = ~d | (d<<1);
- d &= NONASCII_MASK;
- d >>= 7;
- d += (d>>8);
- d += (d>>16);
-#if NONASCII_MASK == 0x8080808080808080UL
- d = d + (d>>32);
-#endif
- len += (long)(d&0xF);
- s++;
- }
- p = (const char *)t;
- }
- for (; p<e; p++) {
- if (((*p)&0xC0) != 0x80) len++;
- }
- return len;
- }
-#endif
- n = rb_enc_strlen_cr(p, e, enc, &cr);
- if (cr) {
- ENC_CODERANGE_SET(str, cr);
- }
- return n;
-#endif
}
/*
@@ -1120,29 +503,11 @@
VALUE
rb_str_plus(VALUE str1, VALUE str2)
{
-#if WITH_OBJC
VALUE str3 = rb_str_new(0, 0);
rb_str_buf_append(str3, str1);
rb_str_buf_append(str3, str2);
if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
OBJ_TAINT(str3);
-#else
- VALUE str3;
- rb_encoding *enc;
-
- StringValue(str2);
- enc = rb_enc_check(str1, str2);
- str3 = rb_str_new(0, RSTRING_BYTELEN(str1)+RSTRING_BYTELEN(str2));
- memcpy(RSTRING_BYTEPTR(str3), RSTRING_BYTEPTR(str1), RSTRING_BYTELEN(str1));
- memcpy(RSTRING_BYTEPTR(str3) + RSTRING_BYTELEN(str1),
- RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2));
- RSTRING_BYTEPTR(str3)[RSTRING_BYTELEN(str3)] = '\0';
-
- if (OBJ_TAINTED(str1) || OBJ_TAINTED(str2))
- OBJ_TAINT(str3);
- ENCODING_CODERANGE_SET(str3, rb_enc_to_index(enc),
- ENC_CODERANGE_AND(ENC_CODERANGE(str1), ENC_CODERANGE(str2)));
-#endif
return str3;
}
@@ -1171,24 +536,9 @@
rb_raise(rb_eArgError, "argument too big");
}
-#if WITH_OBJC
str2 = rb_str_new(NULL, 0);
CFStringPad((CFMutableStringRef)str2, (CFStringRef)str,
len * n, 0);
-#else
- str2 = rb_str_new5(str, 0, len *= n);
- if (len) {
- memcpy(RSTRING_BYTEPTR(str2), RSTRING_BYTEPTR(str), n);
- while (n <= len/2) {
- memcpy(RSTRING_BYTEPTR(str2) + n, RSTRING_BYTEPTR(str2), n);
- n *= 2;
- }
- memcpy(RSTRING_BYTEPTR(str2) + n, RSTRING_BYTEPTR(str2), len-n);
- }
- RSTRING_BYTEPTR(str2)[RSTRING_BYTELEN(str2)] = '\0';
- OBJ_INFECT(str2, str);
- rb_enc_cr_str_copy_for_substr(str2, str);
-#endif
return str2;
}
@@ -1221,49 +571,14 @@
static inline void
str_modifiable(VALUE str)
{
-#if WITH_OBJC
bool __CFStringIsMutable(void *);
if (!__CFStringIsMutable((void *)str))
rb_raise(rb_eRuntimeError, "can't modify immutable string");
-#else
- if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "can't modify string; temporarily locked");
- }
-#endif
if (OBJ_FROZEN(str)) rb_error_frozen("string");
if (!OBJ_TAINTED(str) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
}
-#if !WITH_OBJC
-static int
-str_independent(VALUE str)
-{
- str_modifiable(str);
- if (!STR_SHARED_P(str)) return 1;
- if (STR_EMBED_P(str)) return 1;
- return 0;
-}
-
-static void
-str_make_independent(VALUE str)
-{
- char *ptr;
- long len = RSTRING_BYTELEN(str);
-
- ptr = ALLOC_N(char, len+1);
- if (RSTRING_BYTEPTR(str)) {
- memcpy(ptr, RSTRING_BYTEPTR(str), len);
- }
- STR_SET_NOEMBED(str);
- ptr[len] = 0;
- GC_WB(&RSTRING(str)->as.heap.ptr, ptr);
- RSTRING(str)->as.heap.len = len;
- RSTRING(str)->as.heap.aux.capa = len;
- STR_UNSET_NOCAPA(str);
-}
-#endif
-
void
rb_str_modify(VALUE str)
{
@@ -1281,43 +596,11 @@
{
/* sanity check */
if (OBJ_FROZEN(str)) rb_error_frozen("string");
-#if !WITH_OBJC
- if (STR_ASSOC_P(str)) {
- /* already associated */
- rb_ary_concat(RSTRING(str)->as.heap.aux.shared, add);
- }
- else {
- if (STR_SHARED_P(str)) {
- VALUE assoc = RSTRING(str)->as.heap.aux.shared;
- str_make_independent(str);
- if (STR_ASSOC_P(assoc)) {
- assoc = RSTRING(assoc)->as.heap.aux.shared;
- rb_ary_concat(assoc, add);
- add = assoc;
- }
- }
- else if (STR_EMBED_P(str)) {
- str_make_independent(str);
- }
- else if (RSTRING(str)->as.heap.aux.capa != RSTRING_BYTELEN(str)) {
- RESIZE_CAPA(str, RSTRING_BYTELEN(str));
- }
- FL_SET(str, STR_ASSOC);
- RBASIC(add)->klass = 0;
- RSTRING(str)->as.heap.aux.shared = add;
- }
-#endif
}
VALUE
rb_str_associated(VALUE str)
{
-#if !WITH_OBJC
- if (STR_SHARED_P(str)) str = RSTRING(str)->as.heap.aux.shared;
- if (STR_ASSOC_P(str)) {
- return RSTRING(str)->as.heap.aux.shared;
- }
-#endif
return Qfalse;
}
@@ -1338,7 +621,6 @@
return (char *)RSTRING_PTR(rb_string_value(ptr));
}
-#if WITH_OBJC
const char *
rb_str_cstr(VALUE ptr)
{
@@ -1346,6 +628,7 @@
const char *cptr;
data = (CFDataRef)rb_str_cfdata2(ptr);
+ cptr = NULL;
if (data == NULL) {
cptr = CFStringGetCStringPtr((CFStringRef)ptr, 0);
if (cptr == NULL) {
@@ -1368,22 +651,12 @@
? CFStringGetLength((CFStringRef)ptr)
: CFDataGetLength(data);
}
-#endif
char *
rb_string_value_cstr(volatile VALUE *ptr)
{
-#if WITH_OBJC
VALUE str = rb_string_value(ptr);
return (char *)rb_str_cstr(str);
-#else
- char *s = RSTRING_BYTEPTR(str);
-
- if (!s || RSTRING_BYTELEN(str) != strlen(s)) {
- rb_raise(rb_eArgError, "string contains null byte");
- }
- return s;
-#endif
}
VALUE
@@ -1410,143 +683,16 @@
return rb_check_string_type(str);
}
-#if !WITH_OBJC
-char*
-rb_enc_nth(const char *p, const char *e, int nth, rb_encoding *enc)
-{
- if (rb_enc_mbmaxlen(enc) == 1) {
- p += nth;
- }
- else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- p += nth * rb_enc_mbmaxlen(enc);
- }
- else if (rb_enc_asciicompat(enc)) {
- const char *p2, *e2;
- int n;
-
- while (p < e && 0 < nth) {
- e2 = p + nth;
- if (e < e2)
- return (char *)e;
- if (ISASCII(*p)) {
- p2 = search_nonascii(p, e2);
- if (!p2)
- return (char *)e2;
- nth -= p2 - p;
- p = p2;
- }
- n = rb_enc_mbclen(p, e, enc);
- p += n;
- nth--;
- }
- if (nth != 0)
- return (char *)e;
- return (char *)p;
- }
- else {
- while (p<e && nth--) {
- p += rb_enc_mbclen(p, e, enc);
- }
- }
- if (p > e) p = e;
- return (char*)p;
-}
-
-static char*
-str_nth(const char *p, const char *e, int nth, rb_encoding *enc, int singlebyte)
-{
- if (singlebyte)
- p += nth;
- else {
- p = rb_enc_nth(p, e, nth, enc);
- }
- if (!p) return 0;
- if (p > e) p = e;
- return (char *)p;
-}
-
-/* char offset to byte offset */
-static int
-str_offset(const char *p, const char *e, int nth, rb_encoding *enc, int singlebyte)
-{
- const char *pp = str_nth(p, e, nth, enc, singlebyte);
- if (!pp) return e - p;
- return pp - p;
-}
-
-#ifdef NONASCII_MASK
-static char *
-str_utf8_nth(const char *p, const char *e, int nth)
-{
- if (sizeof(long) * 2 < nth) {
- const unsigned long *s, *t;
- const VALUE lowbits = sizeof(unsigned long) - 1;
- s = (const unsigned long*)(~lowbits & ((VALUE)p + lowbits));
- t = (const unsigned long*)(~lowbits & (VALUE)e);
- for (; p<(const char *)s && 0<nth; p++) {
- if (((*p)&0xC0) != 0x80) nth--;
- }
- while (s < t) {
- unsigned long d = *s++;
- d = ~d | (d<<1);
- d &= NONASCII_MASK;
- d >>= 7;
- d += (d>>8);
- d += (d>>16);
-#if NONASCII_MASK == 0x8080808080808080UL
- d += (d>>32);
-#endif
- nth -= (long)(d&0xF);
- if (nth < 8) {
- t = s;
- break;
- }
- }
- p = (char *)t;
- }
- if (0 < nth) {
- while (p < e) {
- if (((*p)&0xC0) != 0x80) {
- nth--;
- if (nth < 0)
- break;
- }
- p++;
- }
- }
- return (char *)p;
-}
-
-static int
-str_utf8_offset(const char *p, const char *e, int nth)
-{
- const char *pp = str_utf8_nth(p, e, nth);
- if (!pp) return e - p;
- return pp - p;
-}
-#endif /* NONASCII_MASK */
-#endif /* WITH_OBJC */
-
/* byte offset to char offset */
long
rb_str_sublen(VALUE str, long pos)
{
-#if WITH_OBJC
return pos;
-#else
- if (single_byte_optimizable(str) || pos < 0)
- return pos;
- else {
- char *p = RSTRING_BYTEPTR(str);
- return rb_enc_strlen(p, p + pos, STR_ENC_GET(str));
- }
-#endif
}
VALUE
rb_str_subseq(VALUE str, long beg, long len)
{
-#if WITH_OBJC
CFDataRef data;
CFMutableStringRef substr;
long n;
@@ -1602,157 +748,38 @@
}
CFMakeCollectable(substr);
return (VALUE)substr;
-#else
- VALUE str2 = rb_str_new5(str, RSTRING_BYTEPTR(str)+beg, len);
-
- rb_enc_cr_str_copy_for_substr(str2, str);
- OBJ_INFECT(str2, str);
-
- return str2;
-#endif
}
VALUE
rb_str_substr(VALUE str, long beg, long len)
{
-#if WITH_OBJC
return rb_str_subseq(str, beg, len);
-#else
- rb_encoding *enc = STR_ENC_GET(str);
- VALUE str2;
- char *p, *s = RSTRING_BYTEPTR(str), *e = s + RSTRING_BYTELEN(str);
- int singlebyte = single_byte_optimizable(str);
-
- if (len < 0) return Qnil;
- if (!RSTRING_BYTELEN(str)) {
- len = 0;
- }
- if (beg < 0) {
- if (len > -beg) len = -beg;
- if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_BYTELEN(str) / 8) {
- beg = -beg;
- while (beg-- > len && (e = rb_enc_prev_char(s, e, enc)) != 0);
- p = e;
- if (!p) return Qnil;
- while (len-- > 0 && (p = rb_enc_prev_char(s, p, enc)) != 0);
- if (!p) return Qnil;
- len = e - p;
- goto sub;
- }
- else {
- beg += str_strlen(str, enc);
- if (beg < 0) return Qnil;
- }
- }
- else if (beg > 0 && beg > str_strlen(str, enc)) {
- return Qnil;
- }
- if (len == 0) {
- p = 0;
- }
-#ifdef NONASCII_MASK
- else if (ENC_CODERANGE(str) == ENC_CODERANGE_VALID &&
- enc == rb_utf8_encoding()) {
- p = str_utf8_nth(s, e, beg);
- len = str_utf8_offset(p, e, len);
- }
-#endif
- else if ((p = str_nth(s, e, beg, enc, singlebyte)) == e) {
- len = 0;
- }
- else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- if (len * rb_enc_mbmaxlen(enc) > e - p)
- len = e - p;
- else
- len *= rb_enc_mbmaxlen(enc);
- }
- else {
- len = str_offset(p, e, len, enc, singlebyte);
- }
- sub:
- if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_BYTELEN(str)) {
- str2 = rb_str_new4(str);
- str2 = str_new3(rb_obj_class(str2), str2);
- RSTRING(str2)->as.heap.ptr += RSTRING(str2)->as.heap.len - len;
- RSTRING(str2)->as.heap.len = len;
- }
- else {
- str2 = rb_str_new5(str, p, len);
- rb_enc_cr_str_copy_for_substr(str2, str);
- OBJ_INFECT(str2, str);
- }
-
- return str2;
-#endif
}
-#if !WITH_OBJC
VALUE
-rb_str_freeze(VALUE str)
-{
- if (STR_ASSOC_P(str)) {
- VALUE ary = RSTRING(str)->as.heap.aux.shared;
- OBJ_FREEZE(ary);
- }
- return rb_obj_freeze(str);
-}
-#endif
-
-VALUE
rb_str_dup_frozen(VALUE str)
{
-#if WITH_OBJC
str = rb_str_dup(str);
rb_str_freeze(str);
return str;
-#else
- if (STR_SHARED_P(str) && RSTRING(str)->as.heap.aux.shared) {
- VALUE shared = RSTRING(str)->as.heap.aux.shared;
- if (RSTRING_BYTELEN(shared) == RSTRING_BYTELEN(str)) {
- OBJ_FREEZE(shared);
- return shared;
- }
- }
- if (OBJ_FROZEN(str)) return str;
- str = rb_str_dup(str);
- OBJ_FREEZE(str);
- return str;
-#endif
}
VALUE
rb_str_locktmp(VALUE str)
{
-#if !WITH_OBJC
- if (FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal locking already locked string");
- }
- FL_SET(str, STR_TMPLOCK);
-#endif
return str;
}
VALUE
rb_str_unlocktmp(VALUE str)
{
-#if !WITH_OBJC
- if (!FL_TEST(str, STR_TMPLOCK)) {
- rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
- }
- FL_UNSET(str, STR_TMPLOCK);
-#endif
return str;
}
void
rb_str_set_len(VALUE str, long len)
{
-#if WITH_OBJC
rb_str_resize(str, len);
-#else
- STR_SET_LEN(str, len);
- RSTRING_BYTEPTR(str)[len] = '\0';
-#endif
}
VALUE
@@ -1765,7 +792,6 @@
}
rb_str_modify(str);
-#if WITH_OBJC
slen = RSTRING_LEN(str);
if (slen != len) {
void *cfdata;
@@ -1776,44 +802,9 @@
if (cfdata != NULL)
CFDataSetLength((CFMutableDataRef)cfdata, len);
}
-#else
- slen = RSTRING_BYTELEN(str);
- if (len != slen) {
- if (STR_EMBED_P(str)) {
- char *ptr;
- if (len <= RSTRING_EMBED_LEN_MAX) {
- STR_SET_EMBED_LEN(str, len);
- RSTRING(str)->as.ary[len] = '\0';
- return str;
- }
- ptr = ALLOC_N(char,len+1);
- MEMCPY(ptr, RSTRING(str)->as.ary, char, slen);
- GC_WB(&RSTRING(str)->as.heap.ptr, ptr);
- STR_SET_NOEMBED(str);
- }
- else if (len <= RSTRING_EMBED_LEN_MAX) {
- char *ptr = RSTRING(str)->as.heap.ptr;
- STR_SET_EMBED(str);
- if (slen > 0) MEMCPY(RSTRING(str)->as.ary, ptr, char, len);
- RSTRING(str)->as.ary[len] = '\0';
- STR_SET_EMBED_LEN(str, len);
- xfree(ptr);
- return str;
- }
- else if (slen < len || slen - len > 1024) {
- REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1);
- }
- if (!STR_NOCAPA_P(str)) {
- RSTRING(str)->as.heap.aux.capa = len;
- }
- RSTRING(str)->as.heap.len = len;
- RSTRING(str)->as.heap.ptr[len] = '\0'; /* sentinel */
- }
-#endif
return str;
}
-#if WITH_OBJC
static void
rb_objc_str_cat(VALUE str, const char *ptr, long len, int cfstring_encoding)
{
@@ -1845,43 +836,12 @@
}
}
}
-#endif
VALUE
rb_str_buf_cat(VALUE str, const char *ptr, long len)
{
-#if WITH_OBJC
rb_objc_str_cat(str, ptr, len, kCFStringEncodingASCII);
-#else
- long capa, total;
- if (len == 0) return str;
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
- rb_str_modify(str);
- if (STR_ASSOC_P(str)) {
- FL_UNSET(str, STR_ASSOC);
- capa = RSTRING(str)->as.heap.aux.capa = RSTRING_BYTELEN(str);
- }
- else if (STR_EMBED_P(str)) {
- capa = RSTRING_EMBED_LEN_MAX;
- }
- else {
- capa = RSTRING(str)->as.heap.aux.capa;
- }
- total = RSTRING_BYTELEN(str)+len;
- if (capa <= total) {
- while (total > capa) {
- capa = (capa + 1) * 2;
- }
- RESIZE_CAPA(str, capa);
- }
- memcpy(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), ptr, len);
- STR_SET_LEN(str, total);
- RSTRING_BYTEPTR(str)[total] = '\0'; /* sentinel */
-#endif
-
return str;
}
@@ -1897,17 +857,6 @@
if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
-#if !WITH_OBJC
- if (STR_ASSOC_P(str)) {
- rb_str_modify(str);
- if (STR_EMBED_P(str)) str_make_independent(str);
- REALLOC_N(RSTRING(str)->as.heap.ptr, char, RSTRING(str)->as.heap.len+len);
- memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len, ptr, len);
- RSTRING(str)->as.heap.len += len;
- RSTRING(str)->as.heap.ptr[RSTRING(str)->as.heap.len] = '\0'; /* sentinel */
- return str;
- }
-#endif
return rb_str_buf_cat(str, ptr, len);
}
@@ -1918,173 +867,23 @@
return rb_str_cat(str, ptr, strlen(ptr));
}
-#if !WITH_OBJC
-static VALUE
-rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
- int ptr_encindex, int ptr_cr, int *ptr_cr_ret)
-{
- long capa, total, off = -1;
-
- int str_encindex = ENCODING_GET(str);
- int res_encindex;
- int str_cr, res_cr;
- int str_a8 = ENCODING_IS_ASCII8BIT(str);
- int ptr_a8 = ptr_encindex == 0;
-
- str_cr = ENC_CODERANGE(str);
-
- if (str_encindex == ptr_encindex) {
- if (str_cr == ENC_CODERANGE_UNKNOWN ||
- (ptr_a8 && str_cr != ENC_CODERANGE_7BIT)) {
- ptr_cr = ENC_CODERANGE_UNKNOWN;
- }
- else if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
- ptr_cr = coderange_scan(ptr, len, rb_enc_from_index(ptr_encindex));
- }
- }
- else {
- rb_encoding *str_enc = rb_enc_from_index(str_encindex);
- rb_encoding *ptr_enc = rb_enc_from_index(ptr_encindex);
- if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
- if (len == 0)
- return str;
- if (RSTRING_BYTELEN(str) == 0) {
- rb_str_buf_cat(str, ptr, len);
- ENCODING_CODERANGE_SET(str, ptr_encindex, ptr_cr);
- return str;
- }
- goto incompatible;
- }
- if (ptr_cr == ENC_CODERANGE_UNKNOWN) {
- ptr_cr = coderange_scan(ptr, len, ptr_enc);
- }
- if (str_cr == ENC_CODERANGE_UNKNOWN) {
- if (str_a8 || ptr_cr != ENC_CODERANGE_7BIT) {
- str_cr = rb_enc_str_coderange(str);
- }
- }
- }
- if (ptr_cr_ret)
- *ptr_cr_ret = ptr_cr;
-
- if (str_encindex != ptr_encindex &&
- str_cr != ENC_CODERANGE_7BIT &&
- ptr_cr != ENC_CODERANGE_7BIT) {
- incompatible:
- rb_raise(rb_eArgError, "append incompatible encoding strings: %s and %s",
- rb_enc_name(rb_enc_from_index(str_encindex)),
- rb_enc_name(rb_enc_from_index(ptr_encindex)));
- }
-
- if (str_cr == ENC_CODERANGE_UNKNOWN) {
- res_encindex = str_encindex;
- res_cr = ENC_CODERANGE_UNKNOWN;
- }
- else if (str_cr == ENC_CODERANGE_7BIT) {
- if (ptr_cr == ENC_CODERANGE_7BIT) {
- res_encindex = !str_a8 ? str_encindex : ptr_encindex;
- res_cr = ENC_CODERANGE_7BIT;
- }
- else {
- res_encindex = ptr_encindex;
- res_cr = ptr_cr;
- }
- }
- else if (str_cr == ENC_CODERANGE_VALID) {
- res_encindex = str_encindex;
- res_cr = str_cr;
- }
- else { /* str_cr == ENC_CODERANGE_BROKEN */
- res_encindex = str_encindex;
- res_cr = str_cr;
- if (0 < len) res_cr = ENC_CODERANGE_UNKNOWN;
- }
-
- if (len < 0) {
- rb_raise(rb_eArgError, "negative string size (or size too big)");
- }
- if (ptr >= RSTRING_BYTEPTR(str) && ptr <= RSTRING_END(str)) {
- off = ptr - RSTRING_BYTEPTR(str);
- }
- rb_str_modify(str);
- if (len == 0) {
- ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
- return str;
- }
- if (STR_ASSOC_P(str)) {
- FL_UNSET(str, STR_ASSOC);
- capa = RSTRING(str)->as.heap.aux.capa = RSTRING_BYTELEN(str);
- }
- else if (STR_EMBED_P(str)) {
- capa = RSTRING_EMBED_LEN_MAX;
- }
- else {
- capa = RSTRING(str)->as.heap.aux.capa;
- }
- total = RSTRING_BYTELEN(str)+len;
- if (capa <= total) {
- while (total > capa) {
- capa = (capa + 1) * 2;
- }
- RESIZE_CAPA(str, capa);
- }
- if (off != -1) {
- ptr = RSTRING_BYTEPTR(str) + off;
- }
- memcpy(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), ptr, len);
- STR_SET_LEN(str, total);
- RSTRING_BYTEPTR(str)[total] = '\0'; // sentinel
-
- ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
- return str;
-}
-#endif
-
VALUE
rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *ptr_enc)
{
-#if WITH_OBJC
rb_objc_str_cat(str, ptr, len, kCFStringEncodingUTF8);
return str;
-#else
- return rb_enc_cr_str_buf_cat(str, ptr, len,
- rb_enc_to_index(ptr_enc), ENC_CODERANGE_UNKNOWN, NULL);
-#endif
}
VALUE
rb_str_buf_cat_ascii(VALUE str, const char *ptr)
{
-#if WITH_OBJC
rb_objc_str_cat(str, ptr, strlen(ptr), kCFStringEncodingASCII);
return str;
-#else
- /* ptr must reference NUL terminated ASCII string. */
- int encindex = ENCODING_GET(str);
- rb_encoding *enc = rb_enc_from_index(encindex);
- if (rb_enc_asciicompat(enc)) {
- return rb_enc_cr_str_buf_cat(str, ptr, strlen(ptr),
- encindex, ENC_CODERANGE_7BIT, 0);
- }
- else {
- char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc));
- while (*ptr) {
- int c = (unsigned char)*ptr;
- int len = rb_enc_codelen(c, enc);
- rb_enc_mbcput(c, buf, enc);
- rb_enc_cr_str_buf_cat(str, buf, len,
- encindex, ENC_CODERANGE_VALID, 0);
- ptr++;
- }
- return str;
- }
-#endif
}
VALUE
rb_str_buf_append(VALUE str, VALUE str2)
{
-#if WITH_OBJC
CFMutableDataRef mdata;
CFDataRef data;
long str2len;
@@ -2112,18 +911,7 @@
}
}
rb_gc_malloc_increase(sizeof(UniChar) * str2len);
-#else
- int str2_cr;
- str2_cr = ENC_CODERANGE(str2);
-
- rb_enc_cr_str_buf_cat(str, RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2),
- ENCODING_GET(str2), str2_cr, &str2_cr);
-
- OBJ_INFECT(str, str2);
- ENC_CODERANGE_SET(str2, str2_cr);
-#endif
-
return str;
}
@@ -2131,27 +919,6 @@
rb_str_append(VALUE str, VALUE str2)
{
StringValue(str2);
-#if !WITH_OBJC
- if (RSTRING_BYTELEN(str2) > 0 && STR_ASSOC_P(str)) {
- rb_encoding *enc;
- int cr, cr2;
-
- long len = RSTRING_BYTELEN(str)+RSTRING_BYTELEN(str2);
- enc = rb_enc_check(str, str2);
- cr = ENC_CODERANGE(str);
- if ((cr2 = ENC_CODERANGE(str2)) > cr) cr = cr2;
- rb_str_modify(str);
- REALLOC_N(RSTRING(str)->as.heap.ptr, char, len+1);
- GC_WB(&RSTRING(str)->as.heap.ptr, RSTRING(str)->as.heap.ptr);
- memcpy(RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len,
- RSTRING_BYTEPTR(str2), RSTRING_BYTELEN(str2)+1);
- RSTRING(str)->as.heap.len = len;
- rb_enc_associate(str, enc);
- ENC_CODERANGE_SET(str, cr);
- OBJ_INFECT(str, str2);
- return str;
- }
-#endif
return rb_str_buf_append(str, str2);
}
@@ -2176,7 +943,6 @@
rb_str_concat(VALUE str1, VALUE str2)
{
if (FIXNUM_P(str2)) {
-#if WITH_OBJC
int c = FIX2INT(str2);
char buf[2];
@@ -2186,172 +952,14 @@
CFStringAppendCString((CFMutableStringRef)str1, buf,
kCFStringEncodingUTF8);
rb_gc_malloc_increase(sizeof(UniChar));
-#else
- rb_encoding *enc = STR_ENC_GET(str1);
- int c = FIX2INT(str2);
- int pos = RSTRING_BYTELEN(str1);
- int len = rb_enc_codelen(c, enc);
- int cr = ENC_CODERANGE(str1);
-
- rb_str_resize(str1, pos+len);
- rb_enc_mbcput(c, RSTRING_BYTEPTR(str1)+pos, enc);
- ENC_CODERANGE_SET(str1, cr);
-#endif
return str1;
}
return rb_str_append(str1, str2);
}
-#if !WITH_OBJC
-
-typedef unsigned int ub4; /* unsigned 4-byte quantities */
-typedef unsigned char ub1; /* unsigned 1-byte quantities */
-
-#define hashsize(n) ((ub4)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-
-/*
---------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-For every delta with one or two bits set, and the deltas of all three
- high bits or all three low bits, whether the original value of a,b,c
- is almost all zero or is uniformly distributed,
-* If mix() is run forward or backward, at least 32 bits in a,b,c
- have at least 1/4 probability of changing.
-* If mix() is run forward, every bit of c will change between 1/3 and
- 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
-mix() was built out of 36 single-cycle latency instructions in a
- structure that could supported 2x parallelism, like so:
- a -= b;
- a -= c; x = (c>>13);
- b -= c; a ^= x;
- b -= a; x = (a<<8);
- c -= a; b ^= x;
- c -= b; x = (b>>13);
- ...
- Unfortunately, superscalar Pentiums and Sparcs can't take advantage
- of that parallelism. They've also turned some of those single-cycle
- latency instructions into multi-cycle latency instructions. Still,
- this is the fastest good hash I could find. There were about 2^^68
- to choose from. I only looked at a billion or so.
---------------------------------------------------------------------
-*/
-#define mix(a,b,c) \
-{ \
- a -= b; a -= c; a ^= (c>>13); \
- b -= c; b -= a; b ^= (a<<8); \
- c -= a; c -= b; c ^= (b>>13); \
- a -= b; a -= c; a ^= (c>>12); \
- b -= c; b -= a; b ^= (a<<16); \
- c -= a; c -= b; c ^= (b>>5); \
- a -= b; a -= c; a ^= (c>>3); \
- b -= c; b -= a; b ^= (a<<10); \
- c -= a; c -= b; c ^= (b>>15); \
-}
-
-/*
---------------------------------------------------------------------
-hash() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- initval : can be any 4-byte value
-Returns a 32-bit value. Every bit of the key affects every bit of
-the return value. Every 1-bit and 2-bit delta achieves avalanche.
-About 6*len+35 instructions.
-
-The best hash table sizes are powers of 2. There is no need to do
-mod a prime (mod is sooo slow!). If you need less than 32 bits,
-use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
-
-By Bob Jenkins, 1996. bob_jenkins at burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial. It's free.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^^32 is
-acceptable. Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-static ub4
-hash(const ub1 *k, ub4 length, ub4 initval)
- /* k: the key */
- /* length: the length of the key */
- /* initval: the previous hash, or an arbitrary value */
-{
- register ub4 a,b,c,len;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = initval; /* the previous hash value */
-
- /*---------------------------------------- handle most of the key */
- while (len >= 12) {
- a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
- b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
- c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
-
- /*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((ub4)k[10]<<24);
- case 10: c+=((ub4)k[9]<<16);
- case 9 : c+=((ub4)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((ub4)k[7]<<24);
- case 7 : b+=((ub4)k[6]<<16);
- case 6 : b+=((ub4)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((ub4)k[3]<<24);
- case 3 : a+=((ub4)k[2]<<16);
- case 2 : a+=((ub4)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
- /*-------------------------------------------- report the result */
- return c;
-}
-
int
rb_memhash(const void *ptr, long len)
{
- return hash(ptr, len, 0);
-}
-
-int
-rb_str_hash(VALUE str)
-{
- return hash((const void *)RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str), 0);
-}
-
-int
-rb_str_hash_cmp(VALUE str1, VALUE str2)
-{
- int len;
-
- if (!rb_str_comparable(str1, str2)) return 1;
- if (RSTRING_BYTELEN(str1) == (len = RSTRING_BYTELEN(str2)) &&
- memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len) == 0) {
- return 0;
- }
- return 1;
-}
-
-#else
-
-int
-rb_memhash(const void *ptr, long len)
-{
CFDataRef data;
int code;
@@ -2373,83 +981,21 @@
return CFEqual((CFTypeRef)str1, (CFTypeRef)str2) ? 0 : 1;
}
-#endif
-
-/*
- * call-seq:
- * str.hash => fixnum
- *
- * Return a hash based on the string's length and content.
- */
-
-static VALUE
-rb_str_hash_m(VALUE str)
-{
- int hval = rb_str_hash(str);
- return INT2FIX(hval);
-}
-
#define lesser(a,b) (((a)>(b))?(b):(a))
int
rb_str_comparable(VALUE str1, VALUE str2)
{
-#if WITH_OBJC
return Qtrue;
-#else
- int idx1 = ENCODING_GET(str1);
- int idx2 = ENCODING_GET(str2);
- int rc1, rc2;
-
- if (idx1 == idx2) return Qtrue;
- rc1 = rb_enc_str_coderange(str1);
- rc2 = rb_enc_str_coderange(str2);
- if (rc1 == ENC_CODERANGE_7BIT) {
- if (rc2 == ENC_CODERANGE_7BIT) return Qtrue;
- if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
- return Qtrue;
- }
- if (rc2 == ENC_CODERANGE_7BIT) {
- if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
- return Qtrue;
- }
- return Qfalse;
-#endif
}
int
rb_str_cmp(VALUE str1, VALUE str2)
{
-#if WITH_OBJC
return CFStringCompare((CFStringRef)str1, (CFStringRef)str2, 0);
-#else
- long len;
- int retval;
- rb_encoding *enc;
-
- enc = rb_enc_compatible(str1, str2);
- len = lesser(RSTRING_BYTELEN(str1), RSTRING_BYTELEN(str2));
- retval = memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len);
- if (retval == 0) {
- if (RSTRING_BYTELEN(str1) == RSTRING_BYTELEN(str2)) {
- if (!enc) {
- if (ENCODING_GET(str1) - ENCODING_GET(str2) > 0)
- return 1;
- return -1;
- }
- return 0;
- }
- if (RSTRING_BYTELEN(str1) > RSTRING_BYTELEN(str2)) return 1;
- return -1;
- }
- if (retval > 0) return 1;
- return -1;
-#endif
}
-#if WITH_OBJC
bool rb_objc_str_is_pure(VALUE);
-#endif
/*
* call-seq:
@@ -2472,7 +1018,6 @@
}
return rb_equal(str2, str1);
}
-#if WITH_OBJC
len = RSTRING_LEN(str1);
if (len != RSTRING_LEN(str2))
return Qfalse;
@@ -2488,13 +1033,6 @@
}
if (CFEqual((CFTypeRef)str1, (CFTypeRef)str2))
return Qtrue;
-#else
- if (!rb_str_comparable(str1, str2)) return Qfalse;
- if (RSTRING_BYTELEN(str1) == (len = RSTRING_BYTELEN(str2)) &&
- memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2), len) == 0) {
- return Qtrue;
- }
-#endif
return Qfalse;
}
@@ -2512,15 +1050,8 @@
if (TYPE(str2) != T_STRING || RSTRING_BYTELEN(str1) != RSTRING_BYTELEN(str2))
return Qfalse;
-#if WITH_OBJC
if (CFEqual((CFTypeRef)str1, (CFTypeRef)str2))
return Qtrue;
-#else
- if (!rb_str_comparable(str1, str2)) return Qfalse;
- if (memcmp(RSTRING_BYTEPTR(str1), RSTRING_BYTEPTR(str2),
- lesser(RSTRING_BYTELEN(str1), RSTRING_BYTELEN(str2))) == 0)
- return Qtrue;
-#endif
return Qfalse;
}
@@ -2591,46 +1122,13 @@
static VALUE
rb_str_casecmp(VALUE str1, VALUE str2)
{
-#if WITH_OBJC
return INT2FIX(CFStringCompare((CFStringRef)str1, (CFStringRef)str2,
kCFCompareCaseInsensitive));
-#else
- long len;
- rb_encoding *enc;
- char *p1, *p1end, *p2, *p2end;
-
- StringValue(str2);
- enc = rb_enc_compatible(str1, str2);
- if (!enc) {
- return Qnil;
- }
-
- p1 = RSTRING_BYTEPTR(str1); p1end = RSTRING_END(str1);
- p2 = RSTRING_BYTEPTR(str2); p2end = RSTRING_END(str2);
- while (p1 < p1end && p2 < p2end) {
- int c1 = rb_enc_codepoint(p1, p1end, enc);
- int c2 = rb_enc_codepoint(p2, p2end, enc);
-
- if (c1 != c2) {
- c1 = rb_enc_toupper(c1, enc);
- c2 = rb_enc_toupper(c2, enc);
- if (c1 > c2) return INT2FIX(1);
- if (c1 < c2) return INT2FIX(-1);
- }
- len = rb_enc_codelen(c1, enc);
- p1 += len;
- p2 += len;
- }
- if (RSTRING_BYTELEN(str1) == RSTRING_BYTELEN(str2)) return INT2FIX(0);
- if (RSTRING_BYTELEN(str1) > RSTRING_BYTELEN(str2)) return INT2FIX(1);
- return INT2FIX(-1);
-#endif
}
static long
rb_str_index(VALUE str, VALUE sub, long offset)
{
-#if WITH_OBJC
CFRange r;
return (CFStringFindWithOptions((CFStringRef)str,
(CFStringRef)sub,
@@ -2638,45 +1136,6 @@
0,
&r))
? r.location : -1;
-#else
- long pos;
- char *s, *sptr;
- long len, slen;
- rb_encoding *enc;
-
- enc = rb_enc_check(str, sub);
- if (is_broken_string(sub)) {
- return -1;
- }
- len = str_strlen(str, enc);
- slen = str_strlen(sub, enc);
- if (offset < 0) {
- offset += len;
- if (offset < 0) return -1;
- }
- if (len - offset < slen) return -1;
- s = RSTRING_BYTEPTR(str);
- if (offset) {
- offset = str_offset(s, RSTRING_END(str), offset, enc, single_byte_optimizable(str));
- s += offset;
- }
- if (slen == 0) return offset;
- /* need proceed one character at a time */
- sptr = RSTRING_BYTEPTR(sub);
- slen = RSTRING_BYTELEN(sub);
- len = RSTRING_BYTELEN(str) - offset;
- for (;;) {
- char *t;
- pos = rb_memsearch(sptr, slen, s, len);
- if (pos < 0) return pos;
- t = rb_enc_right_char_head(s, s+pos, enc);
- if (t == s) break;
- if ((len -= t - s) <= 0) return -1;
- offset += t - s;
- s = t;
- }
- return pos + offset;
-#endif
}
/*
@@ -2752,7 +1211,6 @@
static long
rb_str_rindex(VALUE str, VALUE sub, long pos)
{
-#if WITH_OBJC
CFRange r;
long sublen, strlen;
sublen = RSTRING_LEN(sub);
@@ -2768,41 +1226,6 @@
kCFCompareBackwards,
&r))
? r.location : -1;
-#else
- long len, slen;
- char *s, *sbeg, *e, *t;
- rb_encoding *enc;
- int singlebyte = single_byte_optimizable(str);
-
- enc = rb_enc_check(str, sub);
- if (is_broken_string(sub)) {
- return -1;
- }
- len = str_strlen(str, enc);
- slen = str_strlen(sub, enc);
- /* substring longer than string */
- if (len < slen) return -1;
- if (len - pos < slen) {
- pos = len - slen;
- }
- if (len == 0) {
- return pos;
- }
- sbeg = RSTRING_BYTEPTR(str);
- e = RSTRING_END(str);
- t = RSTRING_BYTEPTR(sub);
- slen = RSTRING_BYTELEN(sub);
- for (;;) {
- s = str_nth(sbeg, e, pos, enc, singlebyte);
- if (!s) return -1;
- if (memcmp(s, t, slen) == 0) {
- return pos;
- }
- if (pos == 0) break;
- pos--;
- }
- return -1;
-#endif
}
@@ -2957,146 +1380,7 @@
return result;
}
-enum neighbor_char {
- NEIGHBOR_NOT_CHAR,
- NEIGHBOR_FOUND,
- NEIGHBOR_WRAPPED
-};
-
-#if !WITH_OBJC
-static enum neighbor_char
-enc_succ_char(char *p, int len, rb_encoding *enc)
-{
- int i, l;
- while (1) {
- for (i = len-1; 0 <= i && (unsigned char)p[i] == 0xff; i--)
- p[i] = '\0';
- if (i < 0)
- return NEIGHBOR_WRAPPED;
- ++((unsigned char*)p)[i];
- l = rb_enc_precise_mbclen(p, p+len, enc);
- if (MBCLEN_CHARFOUND_P(l)) {
- l = MBCLEN_CHARFOUND_LEN(l);
- if (l == len) {
- return NEIGHBOR_FOUND;
- }
- else {
- memset(p+l, 0xff, len-l);
- }
- }
- if (MBCLEN_INVALID_P(l) && i < len-1) {
- int len2, l2;
- for (len2 = len-1; 0 < len2; len2--) {
- l2 = rb_enc_precise_mbclen(p, p+len2, enc);
- if (!MBCLEN_INVALID_P(l2))
- break;
- }
- memset(p+len2+1, 0xff, len-(len2+1));
- }
- }
-}
-
-static enum neighbor_char
-enc_pred_char(char *p, int len, rb_encoding *enc)
-{
- int i, l;
- while (1) {
- for (i = len-1; 0 <= i && (unsigned char)p[i] == 0; i--)
- p[i] = '\xff';
- if (i < 0)
- return NEIGHBOR_WRAPPED;
- --((unsigned char*)p)[i];
- l = rb_enc_precise_mbclen(p, p+len, enc);
- if (MBCLEN_CHARFOUND_P(l)) {
- l = MBCLEN_CHARFOUND_LEN(l);
- if (l == len) {
- return NEIGHBOR_FOUND;
- }
- else {
- memset(p+l, 0, len-l);
- }
- }
- if (MBCLEN_INVALID_P(l) && i < len-1) {
- int len2, l2;
- for (len2 = len-1; 0 < len2; len2--) {
- l2 = rb_enc_precise_mbclen(p, p+len2, enc);
- if (!MBCLEN_INVALID_P(l2))
- break;
- }
- memset(p+len2+1, 0, len-(len2+1));
- }
- }
-}
-#endif
-
/*
- overwrite +p+ by succeeding letter in +enc+ and returns
- NEIGHBOR_FOUND or NEIGHBOR_WRAPPED.
- When NEIGHBOR_WRAPPED, carried-out letter is stored into carry.
- assuming each ranges are successive, and mbclen
- never change in each ranges.
- NEIGHBOR_NOT_CHAR is returned if invalid character or the range has only one
- character.
- */
-#if !WITH_OBJC
-static enum neighbor_char
-enc_succ_alnum_char(char *p, int len, rb_encoding *enc, char *carry)
-{
- enum neighbor_char ret;
- int c;
- int ctype;
- int range;
- char save[ONIGENC_CODE_TO_MBC_MAXLEN];
-
- c = rb_enc_mbc_to_codepoint(p, p+len, enc);
- if (rb_enc_isctype(c, ONIGENC_CTYPE_DIGIT, enc))
- ctype = ONIGENC_CTYPE_DIGIT;
- else if (rb_enc_isctype(c, ONIGENC_CTYPE_ALPHA, enc))
- ctype = ONIGENC_CTYPE_ALPHA;
- else
- return NEIGHBOR_NOT_CHAR;
-
- MEMCPY(save, p, char, len);
- ret = enc_succ_char(p, len, enc);
- if (ret == NEIGHBOR_FOUND) {
- c = rb_enc_mbc_to_codepoint(p, p+len, enc);
- if (rb_enc_isctype(c, ctype, enc))
- return NEIGHBOR_FOUND;
- }
- MEMCPY(p, save, char, len);
- range = 1;
- while (1) {
- MEMCPY(save, p, char, len);
- ret = enc_pred_char(p, len, enc);
- if (ret == NEIGHBOR_FOUND) {
- c = rb_enc_mbc_to_codepoint(p, p+len, enc);
- if (!rb_enc_isctype(c, ctype, enc)) {
- MEMCPY(p, save, char, len);
- break;
- }
- }
- else {
- MEMCPY(p, save, char, len);
- break;
- }
- range++;
- }
- if (range == 1) {
- return NEIGHBOR_NOT_CHAR;
- }
-
- if (ctype != ONIGENC_CTYPE_DIGIT) {
- MEMCPY(carry, p, char, len);
- return NEIGHBOR_WRAPPED;
- }
-
- MEMCPY(carry, p, char, len);
- enc_succ_char(carry, len, enc);
- return NEIGHBOR_WRAPPED;
-}
-#endif
-
-/*
* call-seq:
* str.succ => new_str
* str.next => new_str
@@ -3124,7 +1408,6 @@
VALUE
rb_str_succ(VALUE orig)
{
-#if WITH_OBJC
UniChar *buf;
UniChar carry;
long i, len;
@@ -3186,79 +1469,6 @@
CFMakeCollectable(newstr);
return (VALUE)newstr;
-#else
- rb_encoding *enc;
- VALUE str;
- char *sbeg, *s, *e;
- int c = -1;
- long l;
- char carry[ONIGENC_CODE_TO_MBC_MAXLEN] = "\1";
- int carry_pos = 0, carry_len = 1;
-
- str = rb_str_new5(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
-#if !WITH_OBJC
- rb_enc_cr_str_copy_for_substr(str, orig);
- OBJ_INFECT(str, orig);
-#endif
- if (RSTRING_LEN(str) == 0) return str;
-
- enc = STR_ENC_GET(orig);
- sbeg = RSTRING_BYTEPTR(str);
- s = e = sbeg + RSTRING_BYTELEN(str);
-
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
- enum neighbor_char neighbor;
- if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
- neighbor = enc_succ_alnum_char(s, l, enc, carry);
- if (neighbor == NEIGHBOR_NOT_CHAR)
- continue;
- if (neighbor == NEIGHBOR_FOUND) {
- RSTRING_SYNC(str);
- return str;
- }
- c = 1;
- carry_pos = s - sbeg;
- carry_len = l;
- }
- if (c == -1) { /* str contains no alnum */
- s = e;
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
- enum neighbor_char neighbor;
- if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
- neighbor = enc_succ_char(s, l, enc);
- if (neighbor == NEIGHBOR_FOUND) {
- RSTRING_SYNC(str);
- return str;
- }
- if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
- /* wrapped to \0...\0. search next valid char. */
- enc_succ_char(s, l, enc);
- }
- if (!rb_enc_asciicompat(enc)) {
- MEMCPY(carry, s, char, l);
- carry_len = l;
- }
- carry_pos = s - sbeg;
- }
- }
-#if WITH_OBJC
- CFMutableDataRef data = (CFMutableDataRef)rb_str_cfdata(str);
- CFDataSetLength(data, RSTRING_BYTELEN(str) + carry_len);
- s = (char *)CFDataGetMutableBytePtr(data);
- memmove(s + carry_len, s, RSTRING_BYTELEN(str) - carry_pos);
- memmove(s, carry, carry_len);
- RSTRING_SYNC(str);
-#else
- RESIZE_CAPA(str, RSTRING_BYTELEN(str) + carry_len);
- s = RSTRING_BYTEPTR(str) + carry_pos;
- memmove(s + carry_len, s, RSTRING_BYTELEN(str) - carry_pos);
- memmove(s, carry, carry_len);
- STR_SET_LEN(str, RSTRING_BYTELEN(str) + carry_len);
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- rb_enc_str_coderange(str);
-#endif
- return str;
-#endif
}
@@ -3308,15 +1518,11 @@
VALUE current, after_end;
ID succ;
int n, excl;
-#if !WITH_OBJC
- rb_encoding *enc;
-#endif
rb_scan_args(argc, argv, "11", &end, &exclusive);
excl = RTEST(exclusive);
succ = rb_intern("succ");
StringValue(end);
-#if WITH_OBJC
if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
UniChar c = CFStringGetCharacterAtIndex((CFStringRef)beg, 0);
UniChar e = CFStringGetCharacterAtIndex((CFStringRef)end, 0);
@@ -3336,22 +1542,6 @@
break;
}
return beg;
-#else
- enc = rb_enc_check(beg, end);
- if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 &&
- is_ascii_string(beg) && is_ascii_string(end)) {
- char c = RSTRING_PTR(beg)[0];
- char e = RSTRING_PTR(end)[0];
-
- if (c > e || (excl && c == e)) return beg;
- for (;;) {
- rb_yield(rb_enc_str_new(&c, 1, enc));
- if (!excl && c == e) break;
- c++;
- if (excl && c == e) break;
- }
- return beg;
-#endif
}
n = rb_str_cmp(beg, end);
if (n > 0 || (excl && n == 0)) return beg;
@@ -3492,54 +1682,20 @@
rb_str_splice_0(VALUE str, long beg, long len, VALUE val)
{
rb_str_modify(str);
-#if WITH_OBJC
CFStringReplace((CFMutableStringRef)str, CFRangeMake(beg, len),
(CFStringRef)val);
-#else
- if (len < RSTRING_BYTELEN(val)) {
- /* expand string */
- RESIZE_CAPA(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(val) - len + 1);
- }
-
- if (RSTRING_BYTELEN(val) != len) {
- memmove(RSTRING_BYTEPTR(str) + beg + RSTRING_BYTELEN(val),
- RSTRING_BYTEPTR(str) + beg + len,
- RSTRING_BYTELEN(str) - (beg + len));
- }
- if (RSTRING_BYTELEN(val) < beg && len < 0) {
- MEMZERO(RSTRING_BYTEPTR(str) + RSTRING_BYTELEN(str), char, -len);
- }
- if (RSTRING_BYTELEN(val) > 0) {
- memmove(RSTRING_BYTEPTR(str)+beg, RSTRING_BYTEPTR(val), RSTRING_BYTELEN(val));
- }
- STR_SET_LEN(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(val) - len);
- if (RSTRING_BYTEPTR(str)) {
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- }
- OBJ_INFECT(str, val);
-#endif
}
static void
rb_str_splice(VALUE str, long beg, long len, VALUE val)
{
long slen;
-#if !WITH_OBJC
- char *p, *e;
- rb_encoding *enc;
- int singlebyte = single_byte_optimizable(str);
-#endif
if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
StringValue(val);
rb_str_modify(str);
-#if WITH_OBJC
slen = CFStringGetLength((CFStringRef)str);
-#else
- enc = rb_enc_check(str, val);
- slen = str_strlen(str, enc);
-#endif
if (slen < beg) {
out_of_range:
@@ -3554,19 +1710,7 @@
if (slen < len || slen < beg + len) {
len = slen - beg;
}
-#if WITH_OBJC
rb_str_splice_0(str, beg, len, val);
-#else
- p = str_nth(RSTRING_BYTEPTR(str), RSTRING_END(str), beg, enc, singlebyte);
- if (!p) p = RSTRING_END(str);
- e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
- if (!e) e = RSTRING_END(str);
- /* error check */
- beg = p - RSTRING_BYTEPTR(str); /* physical position */
- len = e - p; /* physical length */
- rb_str_splice_0(str, beg, len, val);
- rb_enc_associate(str, enc);
-#endif
}
void
@@ -3580,9 +1724,6 @@
{
VALUE match;
long start, end, len;
-#if !WITH_OBJC
- rb_encoding *enc;
-#endif
struct re_registers *regs;
if (rb_reg_search(re, str, 0, 0) < 0) {
@@ -3608,13 +1749,7 @@
end = END(nth);
len = end - start;
StringValue(val);
-#if !WITH_OBJC
- enc = rb_enc_check(str, val);
-#endif
rb_str_splice_0(str, start, len, val);
-#if !WITH_OBJC
- rb_enc_associate(str, enc);
-#endif
}
static VALUE
@@ -3835,18 +1970,11 @@
pat = get_pat(argv[0], 1);
if (rb_reg_search(pat, str, 0, 0) >= 0) {
-#if !WITH_OBJC
- rb_encoding *enc;
- int cr = ENC_CODERANGE(str);
-#endif
match = rb_backref_get();
regs = RMATCH_REGS(match);
if (iter || !NIL_P(hash)) {
-#if !WITH_OBJC
- char *p = RSTRING_BYTEPTR(str); long len = RSTRING_BYTELEN(str);
-#endif
if (iter) {
rb_match_busy(match);
@@ -3856,56 +1984,18 @@
repl = rb_hash_aref(hash, rb_str_subseq(str, BEG(0), END(0) - BEG(0)));
repl = rb_obj_as_string(repl);
}
-#if !WITH_OBJC
- str_mod_check(str, p, len);
-#endif
str_frozen_check(str);
if (iter) rb_backref_set(match);
}
else {
repl = rb_reg_regsub(repl, str, regs, pat);
}
-#if !WITH_OBJC
- enc = rb_enc_compatible(str, repl);
- if (!enc) {
- rb_encoding *str_enc = STR_ENC_GET(str);
- if (coderange_scan(RSTRING_BYTEPTR(str), BEG(0), str_enc) != ENC_CODERANGE_7BIT ||
- coderange_scan(RSTRING_BYTEPTR(str)+END(0),
- RSTRING_BYTELEN(str)-END(0), str_enc) != ENC_CODERANGE_7BIT) {
- rb_raise(rb_eArgError, "character encodings differ: %s and %s",
- rb_enc_name(str_enc),
- rb_enc_name(STR_ENC_GET(repl)));
- }
- enc = STR_ENC_GET(repl);
- }
-#endif
+
rb_str_modify(str);
-#if WITH_OBJC
RSTRING_SYNC(str);
rb_str_splice_0(str, BEG(0), END(0) - BEG(0), repl);
if (OBJ_TAINTED(repl)) tainted = 1;
-#else
- rb_enc_associate(str, enc);
- if (OBJ_TAINTED(repl)) tainted = 1;
- if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
- int cr2 = ENC_CODERANGE(repl);
- if (cr2 == ENC_CODERANGE_UNKNOWN || cr2 > cr) cr = cr2;
- }
- plen = END(0) - BEG(0);
- if (RSTRING_BYTELEN(repl) > plen) {
- RESIZE_CAPA(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(repl) - plen);
- }
- if (RSTRING_BYTELEN(repl) != plen) {
- memmove(RSTRING_BYTEPTR(str) + BEG(0) + RSTRING_BYTELEN(repl),
- RSTRING_BYTEPTR(str) + BEG(0) + plen,
- RSTRING_BYTELEN(str) - BEG(0) - plen);
- }
- memcpy(RSTRING_BYTEPTR(str) + BEG(0),
- RSTRING_BYTEPTR(repl), RSTRING_BYTELEN(repl));
- STR_SET_LEN(str, RSTRING_BYTELEN(str) + RSTRING_BYTELEN(repl) - plen);
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- ENC_CODERANGE_SET(str, cr);
-#endif
+
if (tainted) OBJ_TAINT(str);
return str;
@@ -3990,20 +2080,11 @@
return rb_str_dup(str);
}
-#if WITH_OBJC
dest = rb_str_new5(str, NULL, 0);
slen = RSTRING_LEN(str);
sp = RSTRING_PTR(str);
cp = sp;
str_enc = NULL;
-#else
- blen = RSTRING_BYTELEN(str) + 30; /* len + margin */
- dest = rb_str_buf_new(blen);
- sp = RSTRING_BYTEPTR(str);
- slen = RSTRING_BYTELEN(str);
- cp = sp;
- str_enc = STR_ENC_GET(str);
-#endif
do {
n++;
@@ -4045,11 +2126,7 @@
* in order to prevent infinite loops.
*/
if (slen <= END(0)) break;
-#if WITH_OBJC
len = 1;
-#else
- len = rb_enc_mbclen(sp+END(0), sp+slen, str_enc);
-#endif
rb_enc_str_buf_cat(dest, sp+END(0), len, str_enc);
offset = END(0) + len;
}
@@ -4061,7 +2138,6 @@
rb_enc_str_buf_cat(dest, cp, slen - offset, str_enc);
}
rb_backref_set(match);
-#if WITH_OBJC
if (bang) {
rb_str_modify(str);
RSTRING_SYNC(str);
@@ -4073,17 +2149,6 @@
tainted = 1;
str = dest;
}
-#else
- if (bang) {
- rb_str_shared_replace(str, dest);
- }
- else {
- RBASIC(dest)->klass = rb_obj_class(str);
- RBASIC(dest)->isa = RCLASS_OCID(RBASIC(dest)->klass);
- OBJ_INFECT(dest, str);
- str = dest;
- }
-#endif
if (tainted) OBJ_TAINT(str);
return str;
@@ -4161,7 +2226,6 @@
rb_str_replace(VALUE str, VALUE str2)
{
if (str == str2) return str;
-#if WITH_OBJC
rb_str_modify(str);
CFDataRef data = (CFDataRef)rb_str_cfdata2(str2);
if (data != NULL) {
@@ -4176,31 +2240,6 @@
rb_gc_malloc_increase(CFStringGetLength((CFStringRef)str2) * sizeof(UniChar));
if (OBJ_TAINTED(str2))
OBJ_TAINT(str);
-#else
- StringValue(str2);
- len = RSTRING_BYTELEN(str2);
- if (STR_ASSOC_P(str2)) {
- str2 = rb_str_new4(str2);
- }
- if (STR_SHARED_P(str2)) {
- if (str_independent(str) && !STR_EMBED_P(str)) {
- xfree(RSTRING_BYTEPTR(str));
- }
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.len = len;
- RSTRING(str)->as.heap.ptr = RSTRING_BYTEPTR(str2);
- FL_SET(str, ELTS_SHARED);
- FL_UNSET(str, STR_ASSOC);
- RSTRING(str)->as.heap.aux.shared = RSTRING(str2)->as.heap.aux.shared;
- }
- else {
- rb_str_modify(str);
- str_replace_shared(str, rb_str_new4(str2));
- }
-
- OBJ_INFECT(str, str2);
- rb_enc_cr_str_exact_copy(str, str2);
-#endif
return str;
}
@@ -4217,20 +2256,9 @@
static VALUE
rb_str_clear(VALUE str)
{
-#if WITH_OBJC
rb_str_modify(str);
CFStringDelete((CFMutableStringRef)str,
CFRangeMake(0, CFStringGetLength((CFStringRef)str)));
-#else
- /* rb_str_modify() */ /* no need for str_make_independent */
- if (str_independent(str) && !STR_EMBED_P(str)) {
- free(RSTRING_BYTEPTR(str));
- }
- STR_SET_EMBED(str);
- STR_SET_EMBED_LEN(str, 0);
- RSTRING_BYTEPTR(str)[0] = 0;
- ENC_CODERANGE_CLEAR(str);
-#endif
return str;
}
@@ -4291,9 +2319,7 @@
pos += n;
RSTRING_BYTEPTR(str)[pos] = byte;
-#if WITH_OBJC
RSTRING_SYNC(str);
-#endif
return value;
}
@@ -4309,7 +2335,6 @@
static VALUE
rb_str_reverse_bang(VALUE str)
{
-#if WITH_OBJC
CFIndex i, n;
UniChar *buffer;
@@ -4326,26 +2351,7 @@
}
CFStringDelete((CFMutableStringRef)str, CFRangeMake(0, n));
CFStringAppendCharacters((CFMutableStringRef)str, (const UniChar *)buffer, n);
-#else
- char *s, *e, c;
- if (RSTRING_BYTELEN(str) > 1) {
- rb_str_modify(str);
- s = RSTRING_BYTEPTR(str);
- e = RSTRING_END(str) - 1;
-
- if (single_byte_optimizable(str)) {
- while (s < e) {
- c = *s;
- *s++ = *e;
- *e-- = c;
- }
- }
- else {
- rb_str_shared_replace(str, rb_str_reverse(str));
- }
- }
-#endif
return str;
}
@@ -4361,43 +2367,9 @@
static VALUE
rb_str_reverse(VALUE str)
{
-#if WITH_OBJC
VALUE obj = rb_str_dup(str);
rb_str_reverse_bang(obj);
return obj;
-#else
- rb_encoding *enc;
- VALUE obj;
- char *s, *e, *p;
-
- if (RSTRING_BYTELEN(str) <= 1) return rb_str_dup(str);
- enc = STR_ENC_GET(str);
- obj = rb_str_new5(str, 0, RSTRING_BYTELEN(str));
- s = RSTRING_BYTEPTR(str); e = RSTRING_END(str);
- p = RSTRING_END(obj);
-
- if (RSTRING_BYTELEN(str) > 1) {
- if (single_byte_optimizable(str)) {
- while (s < e) {
- *--p = *s++;
- }
- }
- else {
- while (s < e) {
- int clen = rb_enc_mbclen(s, e, enc);
-
- p -= clen;
- memcpy(p, s, clen);
- s += clen;
- }
- }
- }
- STR_SET_LEN(obj, RSTRING_BYTELEN(str));
- OBJ_INFECT(obj, str);
- rb_enc_cr_str_copy_for_substr(obj, str);
-
- return obj;
-#endif
}
/*
@@ -4498,11 +2470,7 @@
static VALUE
rb_str_to_s(VALUE str)
{
-#if WITH_OBJC
if (!rb_objc_str_is_pure(str)) {
-#else
- if (rb_obj_class(str) != rb_cString) {
-#endif
VALUE dup = str_alloc(rb_cString);
rb_str_replace(dup, str);
return dup;
@@ -4513,18 +2481,10 @@
static void
str_cat_char(VALUE str, int c, rb_encoding *enc)
{
-#if WITH_OBJC
char buf[2];
buf[0] = (char)c;
buf[1] = '\0';
CFStringAppendCString((CFMutableStringRef)str, buf, kCFStringEncodingUTF8);
-#else
- char s[16];
- int n = rb_enc_codelen(c, enc);
-
- rb_enc_mbcput(c, s, enc);
- rb_enc_str_buf_cat(str, s, n, enc);
-#endif
}
static void
@@ -4553,7 +2513,6 @@
const char *p, *pend;
VALUE result;
-#if WITH_OBJC
if (rb_objc_str_is_bytestring(str)) {
p = (const char *)RSTRING_BYTEPTR(str);
pend = (const char *)RSTRING_END(str);
@@ -4564,46 +2523,21 @@
}
if (p == NULL)
return rb_str_new2("\"\"");
-#else
- p = RSTRING_BYTEPTR(str); pend = RSTRING_END(str);
-#endif
result = rb_str_buf_new2("");
-#if !WITH_OBJC
- if (!rb_enc_asciicompat(enc)) enc = rb_usascii_encoding();
- rb_enc_associate(result, enc);
-#endif
str_cat_char(result, '"', enc);
while (p < pend) {
int c;
int n;
int cc;
-#if WITH_OBJC
c = *p;
n = 1;
-#else
- n = rb_enc_precise_mbclen(p, pend, enc);
- if (!MBCLEN_CHARFOUND_P(n)) {
- p++;
- n = 1;
- goto escape_codepoint;
- }
- n = MBCLEN_CHARFOUND_LEN(n);
- c = rb_enc_codepoint(p, pend, enc);
- n = rb_enc_codelen(c, enc);
-#endif
-
p += n;
if (c == '"'|| c == '\\' ||
(c == '#' &&
p < pend &&
-#if WITH_OBJC
((cc = *p),
-#else
- MBCLEN_CHARFOUND_P(rb_enc_precise_mbclen(p,pend,enc)) &&
- (cc = rb_enc_codepoint(p,pend,enc),
-#endif
(cc == '$' || cc == '@' || cc == '{')))) {
prefix_escape(result, c, enc);
}
@@ -4639,9 +2573,6 @@
char *s;
const char *q;
-#if !WITH_OBJC
- escape_codepoint:
-#endif
for (q = p-n; q < p; q++) {
s = buf;
sprintf(buf, "\\x%02X", *q & 0377);
@@ -4652,8 +2583,8 @@
}
}
str_cat_char(result, '"', enc);
+ RSTRING_SYNC(result);
- OBJ_INFECT(result, str);
return result;
}
@@ -4677,7 +2608,6 @@
VALUE result;
len = 2; /* "" */
-#if WITH_OBJC
if (rb_objc_str_is_bytestring(str)) {
p = RSTRING_BYTEPTR(str);
pend = RSTRING_END(str);
@@ -4686,9 +2616,6 @@
p = RSTRING_PTR(str);
pend = p + RSTRING_LEN(str);
}
-#else
- p = RSTRING_BYTEPTR(str); pend = p + RSTRING_BYTELEN(str);
-#endif
while (p < pend) {
unsigned char c = *p++;
switch (c) {
@@ -4778,16 +2705,11 @@
*q++ = '"';
if (!rb_enc_asciicompat(enc0)) {
sprintf(q, ".force_encoding(\"%s\")", rb_enc_name(enc0));
-#if !WITH_OBJC
- enc0 = rb_ascii8bit_encoding();
-#endif
+
}
- OBJ_INFECT(result, str);
/* result from dump is ASCII */
-#if !WITH_OBJC
- rb_enc_associate(result, enc0);
-#endif
+
RSTRING_SYNC(result);
return result;
}
@@ -4805,7 +2727,6 @@
static VALUE
rb_str_upcase_bang(VALUE str)
{
-#if WITH_OBJC
CFHashCode h;
rb_str_modify(str);
h = CFHash((CFTypeRef)str);
@@ -4813,30 +2734,6 @@
if (h == CFHash((CFTypeRef)str))
return Qnil;
return str;
-#else
- rb_encoding *enc;
- char *s, *send;
- int modify = 0;
- int cr = ENC_CODERANGE(str);
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
-
- if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
- modify = 1;
- }
- s += rb_enc_codelen(c, enc);
- }
-
- ENC_CODERANGE_SET(str, cr);
- if (modify) return str;
- return Qnil;
-#endif
}
@@ -4873,7 +2770,6 @@
static VALUE
rb_str_downcase_bang(VALUE str)
{
-#if WITH_OBJC
CFHashCode h;
rb_str_modify(str);
h = CFHash((CFTypeRef)str);
@@ -4881,30 +2777,6 @@
if (h == CFHash((CFTypeRef)str))
return Qnil;
return str;
-#else
- rb_encoding *enc;
- char *s, *send;
- int modify = 0;
- int cr = ENC_CODERANGE(str);
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
-
- if (rb_enc_isupper(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
- modify = 1;
- }
- s += rb_enc_codelen(c, enc);
- }
-
- ENC_CODERANGE_SET(str, cr);
- if (modify) return str;
- return Qnil;
-#endif
}
@@ -4946,7 +2818,6 @@
static VALUE
rb_str_capitalize_bang(VALUE str)
{
-#if WITH_OBJC
CFStringRef tmp;
long i, n;
bool changed;
@@ -4975,37 +2846,6 @@
CFStringReplaceAll((CFMutableStringRef)str, tmp);
CFRelease(tmp);
return str;
-#else
- rb_encoding *enc;
- char *s, *send;
- int modify = 0;
- int c;
- int cr = ENC_CODERANGE(str);
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- if (RSTRING_BYTELEN(str) == 0 || !RSTRING_BYTEPTR(str)) return Qnil;
- s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
-
- c = rb_enc_codepoint(s, send, enc);
- if (rb_enc_islower(c, enc)) {
- rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
- modify = 1;
- }
- s += rb_enc_codelen(c, enc);
- while (s < send) {
- c = rb_enc_codepoint(s, send, enc);
- if (rb_enc_isupper(c, enc)) {
- rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
- modify = 1;
- }
- s += rb_enc_codelen(c, enc);
- }
-
- ENC_CODERANGE_SET(str, cr);
- if (modify) return str;
- return Qnil;
-#endif
}
@@ -5043,7 +2883,6 @@
static VALUE
rb_str_swapcase_bang(VALUE str)
{
-#if WITH_OBJC
CFIndex i, n;
UniChar *buffer;
bool changed;
@@ -5076,35 +2915,6 @@
CFStringDelete((CFMutableStringRef)str, CFRangeMake(0, n));
CFStringAppendCharacters((CFMutableStringRef)str, (const UniChar *)buffer, n);
return str;
-#else
- rb_encoding *enc;
- char *s, *send;
- int modify = 0;
- int cr = ENC_CODERANGE(str);
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
-
- if (rb_enc_isupper(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
- modify = 1;
- }
- else if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
- modify = 1;
- }
- s += rb_enc_codelen(c, enc);
- }
-
- ENC_CODERANGE_SET(str, cr);
- if (modify) return str;
- return Qnil;
-#endif
}
@@ -5128,51 +2938,6 @@
return str;
}
-#if !WITH_OBJC
-typedef unsigned char *USTR;
-
-struct tr {
- int gen, now, max;
- char *p, *pend;
-};
-
-static int
-trnext(struct tr *t, rb_encoding *enc)
-{
- for (;;) {
- if (!t->gen) {
- if (t->p == t->pend) return -1;
- if (t->p < t->pend - 1 && *t->p == '\\') {
- t->p++;
- }
- t->now = rb_enc_codepoint(t->p, t->pend, enc);
- t->p += rb_enc_codelen(t->now, enc);
- if (t->p < t->pend - 1 && *t->p == '-') {
- t->p++;
- if (t->p < t->pend) {
- int c = rb_enc_codepoint(t->p, t->pend, enc);
- t->p += rb_enc_codelen(c, enc);
- if (t->now > c) continue;
- t->gen = 1;
- t->max = c;
- }
- }
- return t->now;
- }
- else if (++t->now < t->max) {
- return t->now;
- }
- else {
- t->gen = 0;
- return t->max;
- }
- }
-}
-
-static VALUE rb_str_delete_bang(int,VALUE*,VALUE);
-#endif
-
-#if WITH_OBJC
typedef void str_charset_find_cb
(CFRange *, const CFRange *, CFStringRef, UniChar, void *);
@@ -5480,12 +3245,10 @@
}
_ctx->changed = true;
}
-#endif
static VALUE
tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
{
-#if WITH_OBJC
struct tr_trans_cb_ctx _ctx;
StringValue(src);
@@ -5516,205 +3279,6 @@
CFRelease(_ctx.opt);
return _ctx.changed ? str : Qnil;
-#else
- SIGNED_VALUE trans[256];
- rb_encoding *enc, *e1, *e2;
- struct tr trsrc, trrepl;
- int cflag = 0;
- int c, last = 0, modify = 0, i;
- char *s, *send;
- VALUE hash = 0;
-
- StringValue(src);
- StringValue(repl);
- if (RSTRING_BYTELEN(str) == 0 || !RSTRING_BYTEPTR(str)) return Qnil;
- trsrc.p = RSTRING_BYTEPTR(src); trsrc.pend = trsrc.p + RSTRING_BYTELEN(src);
- if (RSTRING_BYTELEN(src) >= 2 && RSTRING_BYTEPTR(src)[0] == '^') {
- cflag++;
- trsrc.p++;
- }
- if (RSTRING_BYTELEN(repl) == 0) {
- return rb_str_delete_bang(1, &src, str);
- }
- e1 = rb_enc_check(str, src);
- e2 = rb_enc_check(str, repl);
- if (e1 == e2) {
- enc = e1;
- }
- else {
- enc = rb_enc_check(src, repl);
- }
- trrepl.p = RSTRING_BYTEPTR(repl);
- trrepl.pend = trrepl.p + RSTRING_BYTELEN(repl);
- trsrc.gen = trrepl.gen = 0;
- trsrc.now = trrepl.now = 0;
- trsrc.max = trrepl.max = 0;
-
- if (cflag) {
- for (i=0; i<256; i++) {
- trans[i] = 1;
- }
- while ((c = trnext(&trsrc, enc)) >= 0) {
- if (c < 256) {
- trans[c] = -1;
- }
- else {
- if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, INT2NUM(c), Qtrue);
- }
- }
- while ((c = trnext(&trrepl, enc)) >= 0)
- /* retrieve last replacer */;
- last = trrepl.now;
- for (i=0; i<256; i++) {
- if (trans[i] >= 0) {
- trans[i] = last;
- }
- }
- }
- else {
- int r;
-
- for (i=0; i<256; i++) {
- trans[i] = -1;
- }
- while ((c = trnext(&trsrc, enc)) >= 0) {
- r = trnext(&trrepl, enc);
- if (r == -1) r = trrepl.now;
- if (c < 256) {
- trans[c] = INT2NUM(r);
- }
- else {
- if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, INT2NUM(c), INT2NUM(r));
- }
- }
- }
-
- rb_str_modify(str);
- s = RSTRING_BYTEPTR(str); send = RSTRING_END(str);
- if (sflag) {
- int clen, tlen, max = RSTRING_BYTELEN(str);
- int offset, save = -1;
- char *buf = ALLOC_N(char, max), *t = buf;
- VALUE v;
-
- if (cflag) tlen = rb_enc_codelen(last, enc);
- while (s < send) {
- c = rb_enc_codepoint(s, send, enc);
- tlen = clen = rb_enc_codelen(c, enc);
-
- s += clen;
- if (c < 256) {
- v = trans[c] >= 0 ? trans[c] : Qnil;
- }
- else {
- v = hash ? rb_hash_aref(hash, INT2NUM(c)) : Qnil;
- }
- if (!NIL_P(v)) {
- if (!cflag) {
- c = NUM2INT(v);
- if (save == c) continue;
- save = c;
- tlen = rb_enc_codelen(c, enc);
- modify = 1;
- }
- else {
- save = c = last;
- modify = 1;
- }
- }
- else {
- save = -1;
- }
- while (t - buf + tlen >= max) {
- offset = t - buf;
- max *= 2;
- REALLOC_N(buf, char, max);
- t = buf + offset;
- }
- rb_enc_mbcput(c, t, enc);
- t += tlen;
- }
- *t = '\0';
- GC_WB(&RSTRING(str)->as.heap.ptr, buf);
- RSTRING(str)->as.heap.len = t - buf;
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.aux.capa = max;
- }
- else if (rb_enc_mbmaxlen(enc) == 1) {
- while (s < send) {
- c = (unsigned char)*s;
- if (trans[c] >= 0) {
- if (!cflag) {
- c = FIX2INT(trans[c]);
- *s = c;
- modify = 1;
- }
- else {
- *s = last;
- modify = 1;
- }
- }
- s++;
- }
- }
- else {
- int clen, tlen, max = RSTRING_BYTELEN(str) * 1.2;
- int offset;
- char *buf = ALLOC_N(char, max), *t = buf;
- VALUE v;
-
- if (cflag) tlen = rb_enc_codelen(last, enc);
- while (s < send) {
- c = rb_enc_codepoint(s, send, enc);
- tlen = clen = rb_enc_codelen(c, enc);
-
- if (c < 256) {
- v = trans[c] >= 0 ? trans[c] : Qnil;
- }
- else {
- v = hash ? rb_hash_aref(hash, INT2NUM(c)) : Qnil;
- }
- if (!NIL_P(v)) {
- if (!cflag) {
- c = NUM2INT(v);
- tlen = rb_enc_codelen(c, enc);
- modify = 1;
- }
- else {
- c = last;
- modify = 1;
- }
- }
- while (t - buf + tlen >= max) {
- offset = t - buf;
- max *= 2;
- REALLOC_N(buf, char, max);
- t = buf + offset;
- }
- if (s != t) rb_enc_mbcput(c, t, enc);
- s += clen;
- t += tlen;
- }
- if (!STR_EMBED_P(str)) {
- xfree(RSTRING(str)->as.heap.ptr);
- }
- *t = '\0';
- GC_WB(&RSTRING(str)->as.heap.ptr, buf);
- RSTRING(str)->as.heap.len = t - buf;
- STR_SET_NOEMBED(str);
- RSTRING(str)->as.heap.aux.capa = max;
- }
-
- if (modify) {
-#if !WITH_OBJC
- rb_enc_associate(str, enc);
-#endif
- return str;
- }
- return Qnil;
-#endif
}
/*
@@ -5758,84 +3322,6 @@
return str;
}
-#if !WITH_OBJC
-static void
-tr_setup_table(VALUE str, char stable[256], int first,
- VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
-{
- char buf[256];
- struct tr tr;
- int c, l;
- VALUE table = 0, ptable = 0;
- int i, cflag = 0;
-
- tr.p = RSTRING_BYTEPTR(str); tr.pend = tr.p + RSTRING_BYTELEN(str);
- tr.gen = tr.now = tr.max = 0;
-
- if (RSTRING_BYTELEN(str) > 1 && rb_enc_ascget(tr.p, tr.pend, &l, enc) == '^') {
- cflag = 1;
- tr.p += l;
- }
- if (first) {
- for (i=0; i<256; i++) {
- stable[i] = 1;
- }
- }
- for (i=0; i<256; i++) {
- buf[i] = cflag;
- }
-
- while ((c = trnext(&tr, enc)) >= 0) {
- if (c < 256) {
- buf[c & 0xff] = !cflag;
- }
- else {
- VALUE key = INT2NUM(c);
-
- if (!table) {
- table = rb_hash_new();
- if (cflag) {
- ptable = *ctablep;
- *ctablep = table;
- }
- else {
- ptable = *tablep;
- *tablep = table;
- }
- }
- if (!ptable || !NIL_P(rb_hash_aref(ptable, key))) {
- rb_hash_aset(table, key, Qtrue);
- }
- }
- }
- for (i=0; i<256; i++) {
- stable[i] = stable[i] && buf[i];
- }
-}
-
-
-static int
-tr_find(int c, char table[256], VALUE del, VALUE nodel)
-{
- if (c < 256) {
- return table[c] ? Qtrue : Qfalse;
- }
- else {
- VALUE v = INT2NUM(c);
-
- if (!del || NIL_P(rb_hash_lookup(del, v))) {
- return Qfalse;
- }
- if (nodel && NIL_P(rb_hash_lookup(nodel, v)))
- return Qfalse;
- return Qtrue;
- }
-}
-
-#else
-
-#endif
-
/*
* call-seq:
* str.delete!([other_str]+) => str or nil
@@ -5844,7 +3330,6 @@
* <code>nil</code> if <i>str</i> was not modified.
*/
-#if WITH_OBJC
static void
rb_str_delete_bang_cb(CFRange *search_range, const CFRange *result_range,
CFStringRef str, UniChar character, void *ctx)
@@ -5855,12 +3340,10 @@
search_range->location = result_range->location;
*(bool *)ctx = true;
}
-#endif
static VALUE
rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
{
-#if WITH_OBJC
bool changed;
if (argc < 1)
rb_raise(rb_eArgError, "wrong number of arguments");
@@ -5871,50 +3354,6 @@
if (!changed)
return Qnil;
return str;
-#else
- char squeez[256];
- rb_encoding *enc = 0;
- char *s, *send, *t;
- VALUE del = 0, nodel = 0;
- int modify = 0;
- int i;
- int cr = ENC_CODERANGE(str);
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- enc = rb_enc_check(str, s);
- tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
- }
-
- rb_str_modify(str);
- s = t = RSTRING_BYTEPTR(str);
- if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
- send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
-
- if (tr_find(c, squeez, del, nodel)) {
- modify = 1;
- }
- else {
- if (t != s) rb_enc_mbcput(c, t, enc);
- t += clen;
- }
- s += clen;
- }
- *t = '\0';
- STR_SET_LEN(str, t - RSTRING_BYTEPTR(str));
-
- ENC_CODERANGE_SET(str, cr);
- if (modify) return str;
- return Qnil;
-#endif
}
/*
@@ -5948,7 +3387,6 @@
* <code>nil</code> if no changes were made.
*/
-#if WITH_OBJC
static void
rb_str_squeeze_bang_cb(CFRange *search_range, const CFRange *result_range,
CFStringRef str, UniChar character, void *ctx)
@@ -5963,12 +3401,10 @@
*(bool *)ctx = true;
}
}
-#endif
static VALUE
rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
{
-#if WITH_OBJC
bool changed;
VALUE all_chars;
if (argc == 0) {
@@ -5983,52 +3419,6 @@
if (!changed)
return Qnil;
return str;
-#else
- char squeez[256];
- rb_encoding *enc = 0;
- VALUE del = 0, nodel = 0;
- char *s, *send, *t;
- int save, modify = 0;
- int i;
-
- if (argc == 0) {
- enc = STR_ENC_GET(str);
- }
- else {
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- enc = rb_enc_check(str, s);
- tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
- }
- }
-
- rb_str_modify(str);
- s = t = RSTRING_BYTEPTR(str);
- if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
- send = RSTRING_END(str);
- save = -1;
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
-
- if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
- if (t != s) rb_enc_mbcput(c, t, enc);
- save = c;
- t += clen;
- }
- s += clen;
- }
- *t = '\0';
- if (t - RSTRING_BYTEPTR(str) != RSTRING_BYTELEN(str)) {
- STR_SET_LEN(str, t - RSTRING_BYTEPTR(str));
- modify = 1;
- }
-
- if (modify) return str;
- return Qnil;
-#endif
}
@@ -6109,19 +3499,16 @@
* a.count "ej-m" #=> 4
*/
-#if WITH_OBJC
static void
rb_str_count_cb(CFRange *search_range, const CFRange *result_range,
CFStringRef str, UniChar character, void *ctx)
{
(*(int *)ctx) += result_range->length;
}
-#endif
static VALUE
rb_str_count(int argc, VALUE *argv, VALUE str)
{
-#if WITH_OBJC
int count;
if (argc < 1)
rb_raise(rb_eArgError, "wrong number of arguments");
@@ -6129,42 +3516,8 @@
str_charset_find((CFStringRef)str, argv, argc, false,
rb_str_count_cb, &count);
return INT2NUM(count);
-#else
- char table[256];
- rb_encoding *enc = 0;
- VALUE del = 0, nodel = 0;
- char *s, *send;
- int i;
-
- if (argc < 1) {
- rb_raise(rb_eArgError, "wrong number of arguments");
- }
- for (i=0; i<argc; i++) {
- VALUE s = argv[i];
-
- StringValue(s);
- enc = rb_enc_check(str, s);
- tr_setup_table(s, table,i==0, &del, &nodel, enc);
- }
-
- s = RSTRING_BYTEPTR(str);
- if (!s || RSTRING_BYTELEN(str) == 0) return INT2FIX(0);
- send = RSTRING_END(str);
- i = 0;
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
-
- if (tr_find(c, table, del, nodel)) {
- i++;
- }
- s += clen;
- }
- return INT2NUM(i);
-#endif
}
-
/*
* call-seq:
* str.split(pattern=$;, [limit]) => anArray
@@ -6220,9 +3573,6 @@
VALUE result, tmp;
long clen;
-#if !WITH_OBJC
- cstr = RSTRING_PTR(str);
-#endif
clen = RSTRING_LEN(str);
if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
@@ -6248,35 +3598,11 @@
else {
fs_set:
if (TYPE(spat) == T_STRING) {
-#if WITH_OBJC
spat_string = Qtrue;
if (RSTRING_LEN(spat) == 1
&& CFStringGetCharacterAtIndex((CFStringRef)spat, 0) == ' ') {
awk_split = Qtrue;
}
-#else
- const char *spat_cstr;
- long spat_clen;
- rb_encoding *enc2 = STR_ENC_GET(spat);
-
- spat_cstr = RSTRING_PTR(spat);
- spat_clen = RSTRING_LEN(spat);
- if (rb_enc_mbminlen(enc2) == 1) {
- if (spat_clen == 1 && spat_cstr[0] == ' '){
- awk_split = Qtrue;
- }
- }
- else {
- int l;
- if (rb_enc_ascget(spat_cstr, spat_cstr+spat_clen, &l, enc2) == ' ' &&
- spat_clen == l) {
- awk_split = Qtrue;
- }
- }
- if (!awk_split) {
- spat = rb_reg_regcomp(rb_reg_quote(spat));
- }
-#endif
}
else {
spat = get_pat(spat, 1);
@@ -6284,7 +3610,6 @@
}
beg = 0;
-#if WITH_OBJC
if (awk_split || spat_string) {
CFRange search_range;
CFCharacterSetRef charset = NULL;
@@ -6338,41 +3663,6 @@
}
while ((limit == Qnil || --lim > 1));
beg = search_range.location;
-#else
- if (awk_split) {
- const char *ptr = cstr;
- const char *eptr = cstr+clen;
- const char *bptr = ptr;
- int skip = 1;
- int c;
-
- end = beg;
- while (ptr < eptr) {
- c = rb_enc_codepoint(ptr, eptr, enc);
- ptr += rb_enc_mbclen(ptr, eptr, enc);
- if (skip) {
- if (rb_enc_isspace(c, enc)) {
- beg = ptr - bptr;
- }
- else {
- end = ptr - bptr;
- skip = 0;
- if (!NIL_P(limit) && lim <= i) break;
- }
- }
- else {
- if (rb_enc_isspace(c, enc)) {
- rb_ary_push(result, rb_str_subseq(str, beg, end-beg));
- skip = 1;
- beg = ptr - bptr;
- if (!NIL_P(limit)) ++i;
- }
- else {
- end = ptr - bptr;
- }
- }
- }
-#endif
}
else {
long start = beg;
@@ -6383,34 +3673,18 @@
while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
regs = RMATCH_REGS(rb_backref_get());
if (start == end && BEG(0) == END(0)) {
-#if WITH_OBJC
if (0) {
-#else
- if (!cstr) {
- rb_ary_push(result, rb_str_new("", 0));
-#endif
break;
}
else if (last_null == 1) {
-#if WITH_OBJC
rb_ary_push(result, rb_str_subseq(str, beg, 1));
-#else
- rb_ary_push(result, rb_str_subseq(str, beg,
- rb_enc_mbclen(cstr+beg,
- cstr+clen,
- enc)));
-#endif
beg = start;
}
else {
if (start == clen)
start++;
else
-#if WITH_OBJC
start += 1;
-#else
- start += rb_enc_mbclen(cstr+start,cstr+clen,enc);
-#endif
last_null = 1;
continue;
}
@@ -6516,7 +3790,6 @@
static VALUE
rb_str_each_line(int argc, VALUE *argv, VALUE str)
{
-#if WITH_OBJC
VALUE rs;
long n;
CFStringRef substr;
@@ -6581,98 +3854,8 @@
#undef YIELD_SUBSTR
return str;
-#else
- rb_encoding *enc;
- VALUE rs;
- int newline;
- char *p, *pend, *s, *ptr;
- long len, rslen;
- VALUE line;
- int n;
-
- if (argc == 0) {
- rs = rb_rs;
- }
- else {
- rb_scan_args(argc, argv, "01", &rs);
- }
- RETURN_ENUMERATOR(str, argc, argv);
- if (NIL_P(rs)) {
- rb_yield(str);
- return str;
- }
- str = rb_str_new4(str);
- ptr = p = s = RSTRING_BYTEPTR(str);
- pend = p + RSTRING_BYTELEN(str);
- len = RSTRING_BYTELEN(str);
- StringValue(rs);
- if (rs == rb_default_rs) {
- enc = rb_enc_get(str);
- while (p < pend) {
- char *p0;
-
- p = memchr(p, '\n', pend - p);
- if (!p) break;
- p0 = rb_enc_left_char_head(s, p, enc);
- if (!rb_enc_is_newline(p0, pend, enc)) {
- p++;
- continue;
- }
- p = p0 + rb_enc_mbclen(p0, pend, enc);
- line = rb_str_new5(str, s, p - s);
- OBJ_INFECT(line, str);
- rb_enc_cr_str_copy_for_substr(line, str);
- rb_yield(line);
- str_mod_check(str, ptr, len);
- s = p;
- }
- goto finish;
- }
-
- enc = rb_enc_check(str, rs);
- rslen = RSTRING_BYTELEN(rs);
- if (rslen == 0) {
- newline = '\n';
- }
- else {
- newline = rb_enc_codepoint(RSTRING_BYTEPTR(rs), RSTRING_END(rs), enc);
- }
-
- while (p < pend) {
- int c = rb_enc_codepoint(p, pend, enc);
-
- n = rb_enc_codelen(c, enc);
- if (rslen == 0 && c == newline) {
- while (p < pend && rb_enc_codepoint(p, pend, enc) == newline) {
- p += n;
- }
- p -= n;
- }
- if (c == newline &&
- (rslen <= 1 || memcmp(RSTRING_BYTEPTR(rs), p, rslen) == 0)) {
- line = rb_str_new5(str, s, p - s + (rslen ? rslen : n));
- OBJ_INFECT(line, str);
- rb_enc_cr_str_copy_for_substr(line, str);
- rb_yield(line);
- str_mod_check(str, ptr, len);
- s = p + (rslen ? rslen : n);
- }
- p += n;
- }
-
- finish:
- if (s != pend) {
- line = rb_str_new5(str, s, pend - s);
- OBJ_INFECT(line, str);
- rb_enc_cr_str_copy_for_substr(line, str);
- rb_yield(line);
- }
-
- return str;
-#endif
}
-
/*
* Document-method: bytes
* call-seq:
@@ -6745,7 +3928,6 @@
static VALUE
rb_str_each_char(VALUE str)
{
-#if WITH_OBJC
CFStringInlineBuffer buf;
long i, n;
@@ -6762,44 +3944,8 @@
rb_yield(s);
}
return str;
-#else
- int i, len, n;
- const char *ptr;
- rb_encoding *enc;
-
- RETURN_ENUMERATOR(str, 0, 0);
- str = rb_str_new4(str);
- ptr = RSTRING_BYTEPTR(str);
- len = RSTRING_BYTELEN(str);
- enc = rb_enc_get(str);
- for (i = 0; i < len; i += n) {
- n = rb_enc_mbclen(ptr + i, ptr + len, enc);
- rb_yield(rb_str_subseq(str, i, n));
- }
- return str;
-#endif
}
-#if !WITH_OBJC
-static long
-chopped_length(VALUE str)
-{
- rb_encoding *enc = STR_ENC_GET(str);
- const char *p, *p2, *beg, *end;
-
- beg = RSTRING_BYTEPTR(str);
- end = beg + RSTRING_BYTELEN(str);
- if (beg > end) return 0;
- p = rb_enc_prev_char(beg, end, enc);
- if (!p) return 0;
- if (p > beg && rb_enc_codepoint(p, end, enc) == '\n') {
- p2 = rb_enc_prev_char(beg, p, enc);
- if (p2 && rb_enc_codepoint(p2, end, enc) == '\r') p = p2;
- }
- return p - beg;
-}
-#endif
-
/*
* call-seq:
* str.chop! => str or nil
@@ -6812,7 +3958,6 @@
static VALUE
rb_str_chop_bang(VALUE str)
{
-#if WITH_OBJC
long n;
const char *p;
CFRange r;
@@ -6832,17 +3977,6 @@
}
CFStringDelete((CFMutableStringRef)str, r);
return str;
-#else
- if (RSTRING_BYTELEN(str) > 0) {
- long len;
- rb_str_modify(str);
- len = chopped_length(str);
- STR_SET_LEN(str, len);
- RSTRING_BYTEPTR(str)[len] = '\0';
- return str;
- }
- return Qnil;
-#endif
}
@@ -6866,16 +4000,9 @@
static VALUE
rb_str_chop(VALUE str)
{
-#if WITH_OBJC
VALUE str2 = rb_str_dup(str);
rb_str_chop_bang(str2);
return str2;
-#else
- VALUE str2 = rb_str_new5(str, RSTRING_BYTEPTR(str), chopped_length(str));
- rb_enc_cr_str_copy_for_substr(str2, str);
- OBJ_INFECT(str2, str);
- return str2;
-#endif
}
@@ -6890,7 +4017,6 @@
static VALUE
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
{
-#if WITH_OBJC
VALUE rs;
long len, rslen;
CFRange range_result;
@@ -6934,99 +4060,6 @@
return Qnil;
CFStringDelete((CFMutableStringRef)str, range_result);
return str;
-#else
- rb_encoding *enc;
- VALUE rs;
- int newline;
- char *p, *pp, *e;
- long len, rslen;
-
- len = RSTRING_BYTELEN(str);
- if (len == 0) return Qnil;
- p = RSTRING_BYTEPTR(str);
- e = p + len;
- if (argc == 0) {
- rs = rb_rs;
- if (rs == rb_default_rs) {
- smart_chomp:
- rb_str_modify(str);
- enc = rb_enc_get(str);
- if (rb_enc_mbminlen(enc) > 1) {
- pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), enc);
- if (rb_enc_is_newline(pp, e, enc)) {
- e = pp;
- }
- pp = e - rb_enc_mbminlen(enc);
- if (pp >= p) {
- pp = rb_enc_left_char_head(p, pp, enc);
- if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
- e = pp;
- }
- }
- if (e == RSTRING_END(str)) {
- return Qnil;
- }
- len = e - RSTRING_BYTEPTR(str);
- STR_SET_LEN(str, len);
- }
- else {
- if (RSTRING_BYTEPTR(str)[len-1] == '\n') {
- STR_DEC_LEN(str);
- if (RSTRING_BYTELEN(str) > 0 &&
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)-1] == '\r') {
- STR_DEC_LEN(str);
- }
- }
- else if (RSTRING_BYTEPTR(str)[len-1] == '\r') {
- STR_DEC_LEN(str);
- }
- else {
- return Qnil;
- }
- }
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- return str;
- }
- }
- if (NIL_P(rs)) return Qnil;
- StringValue(rs);
- rslen = RSTRING_BYTELEN(rs);
- if (rslen == 0) {
- while (len>0 && p[len-1] == '\n') {
- len--;
- if (len>0 && p[len-1] == '\r')
- len--;
- }
- if (len < RSTRING_BYTELEN(str)) {
- rb_str_modify(str);
- STR_SET_LEN(str, len);
- RSTRING_BYTEPTR(str)[len] = '\0';
- return str;
- }
- return Qnil;
- }
- if (rslen > len) return Qnil;
- newline = RSTRING_BYTEPTR(rs)[rslen-1];
- if (rslen == 1 && newline == '\n')
- goto smart_chomp;
-
- enc = rb_enc_check(str, rs);
- if (is_broken_string(rs)) {
- return Qnil;
- }
- pp = e - rslen;
- if (p[len-1] == newline &&
- (rslen <= 1 ||
- memcmp(RSTRING_BYTEPTR(rs), pp, rslen) == 0)) {
- if (rb_enc_left_char_head(p, pp, enc) != pp)
- return Qnil;
- rb_str_modify(str);
- STR_SET_LEN(str, RSTRING_BYTELEN(str) - rslen);
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- return str;
- }
- return Qnil;
-#endif
}
@@ -7069,7 +4102,6 @@
* "hello".lstrip! #=> nil
*/
-#if WITH_OBJC
static VALUE
rb_str_strip_bang2(VALUE str, int direction)
{
@@ -7113,39 +4145,11 @@
return orig_n != n ? str : Qnil;
}
-#endif
static VALUE
rb_str_lstrip_bang(VALUE str)
{
-#if WITH_OBJC
return rb_str_strip_bang2(str, -1);
-#else
- rb_encoding *enc;
- char *s, *t, *e;
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- s = RSTRING_BYTEPTR(str);
- if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
- e = t = RSTRING_END(str);
- /* remove spaces at head */
- while (s < e) {
- int cc = rb_enc_codepoint(s, e, enc);
-
- if (!rb_enc_isspace(cc, enc)) break;
- s += rb_enc_codelen(cc, enc);
- }
-
- if (s > RSTRING_BYTEPTR(str)) {
- rb_str_modify(str);
- STR_SET_LEN(str, t-s);
- memmove(RSTRING_BYTEPTR(str), s, RSTRING_BYTELEN(str));
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- return str;
- }
- return Qnil;
-#endif
}
@@ -7184,39 +4188,7 @@
static VALUE
rb_str_rstrip_bang(VALUE str)
{
-#if WITH_OBJC
return rb_str_strip_bang2(str, 1);
-#else
- rb_encoding *enc;
- char *s, *t, *e;
- int space_seen = Qfalse;
-
- rb_str_modify(str);
- enc = STR_ENC_GET(str);
- s = RSTRING_BYTEPTR(str);
- if (!s || RSTRING_BYTELEN(str) == 0) return Qnil;
- t = e = RSTRING_END(str);
- while (s < e) {
- int cc = rb_enc_codepoint(s, e, enc);
-
- if (!cc || rb_enc_isspace(cc, enc)) {
- if (!space_seen) t = s;
- space_seen = Qtrue;
- }
- else {
- space_seen = Qfalse;
- }
- s += rb_enc_codelen(cc, enc);
- }
- if (!space_seen) t = s;
- if (t < e) {
- rb_str_modify(str);
- STR_SET_LEN(str, t-RSTRING_BYTEPTR(str));
- RSTRING_BYTEPTR(str)[RSTRING_BYTELEN(str)] = '\0';
- return str;
- }
- return Qnil;
-#endif
}
@@ -7251,15 +4223,7 @@
static VALUE
rb_str_strip_bang(VALUE str)
{
-#if WITH_OBJC
return rb_str_strip_bang2(str, 0);
-#else
- VALUE l = rb_str_lstrip_bang(str);
- VALUE r = rb_str_rstrip_bang(str);
-
- if (NIL_P(l) && NIL_P(r)) return Qnil;
- return str;
-#endif
}
@@ -7284,14 +4248,10 @@
static VALUE
scan_once(VALUE str, VALUE pat, long *start, long strlen, bool pat_is_string)
{
-#if !WITH_OBJC
- rb_encoding *enc;
-#endif
VALUE result, match;
struct re_registers *regs;
long i;
-#if WITH_OBJC
if (pat_is_string) {
/* XXX this is sometimes slower than the regexp search, especially for
* long pattern strings
@@ -7314,11 +4274,7 @@
}
return result;
}
-#endif
-#if !WITH_OBJC
- enc = STR_ENC_GET(str);
-#endif
if (rb_reg_search(pat, str, *start, 0) >= 0) {
match = rb_backref_get();
regs = RMATCH_REGS(match);
@@ -7326,12 +4282,6 @@
/*
* Always consume at least one character of the input string
*/
-#if !WITH_OBJC
- if (RSTRING_BYTELEN(str) > END(0))
- *start = END(0)+rb_enc_mbclen(RSTRING_BYTEPTR(str)+END(0),
- RSTRING_END(str), enc);
- else
-#endif
*start = END(0)+1;
}
else {
@@ -7409,9 +4359,6 @@
match = rb_backref_get();
rb_match_busy(match);
rb_yield(result);
-#if !WITH_OBJC
- str_mod_check(str, p, len);
-#endif
rb_backref_set(match); /* restore $~ value */
}
rb_backref_set(match);
@@ -7496,8 +4443,6 @@
if (s == NULL)
s = "";
result = rb_str_new2(crypt(s, RSTRING_BYTEPTR(salt)));
- OBJ_INFECT(result, str);
- OBJ_INFECT(result, salt);
return result;
}
@@ -7525,11 +4470,7 @@
VALUE
rb_str_intern(VALUE s)
{
-#if WITH_OBJC
VALUE str = s;
-#else
- VALUE str = RB_GC_GUARD(s);
-#endif
ID id;
if (OBJ_TAINTED(str) && rb_safe_level() >= 1) {
@@ -7551,16 +4492,9 @@
VALUE
rb_str_ord(VALUE s)
{
-#if WITH_OBJC
if (CFStringGetLength((CFStringRef)s) == 0)
rb_raise(rb_eArgError, "empty string");
return INT2NUM(CFStringGetCharacterAtIndex((CFStringRef)s, 0));
-#else
- int c;
-
- c = rb_enc_codepoint(RSTRING_BYTEPTR(s), RSTRING_END(s), STR_ENC_GET(s));
- return INT2NUM(c);
-#endif
}
/*
@@ -7624,7 +4558,6 @@
}
}
-#if WITH_OBJC
static inline void
rb_str_justify0(VALUE str, VALUE pad, long width, long padwidth, long index)
{
@@ -7641,12 +4574,10 @@
}
while (width > 0);
}
-#endif
static VALUE
rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
{
-#if WITH_OBJC
VALUE w, pad;
long n, width, padwidth;
@@ -7683,82 +4614,6 @@
}
return str;
-#else
- rb_encoding *enc;
- VALUE w;
- long width, len, flen = 1, fclen = 1;
- VALUE res;
- char *p, *f = " ";
- long n, llen, rlen;
- volatile VALUE pad;
- int singlebyte = 1;
-
- rb_scan_args(argc, argv, "11", &w, &pad);
- enc = STR_ENC_GET(str);
- width = NUM2LONG(w);
- if (argc == 2) {
- StringValue(pad);
- enc = rb_enc_check(str, pad);
- f = RSTRING_BYTEPTR(pad);
- flen = RSTRING_BYTELEN(pad);
- fclen = str_strlen(pad, enc);
- singlebyte = single_byte_optimizable(pad);
- if (flen == 0 || fclen == 0) {
- rb_raise(rb_eArgError, "zero width padding");
- }
- }
- len = str_strlen(str, enc);
- if (width < 0 || len >= width) return rb_str_dup(str);
- n = width - len;
- llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
- rlen = n - llen;
- res = rb_str_new5(str, 0, RSTRING_BYTELEN(str)+n*flen/fclen+2);
- p = RSTRING_BYTEPTR(res);
- while (llen) {
- if (flen <= 1) {
- *p++ = *f;
- llen--;
- }
- else if (llen > fclen) {
- memcpy(p,f,flen);
- p += flen;
- llen -= fclen;
- }
- else {
- char *fp = str_nth(f, f+flen, llen, enc, singlebyte);
- n = fp - f;
- memcpy(p,f,n);
- p+=n;
- break;
- }
- }
- memcpy(p, RSTRING_BYTEPTR(str), RSTRING_BYTELEN(str));
- p+=RSTRING_BYTELEN(str);
- while (rlen) {
- if (flen <= 1) {
- *p++ = *f;
- rlen--;
- }
- else if (rlen > fclen) {
- memcpy(p,f,flen);
- p += flen;
- rlen -= fclen;
- }
- else {
- char *fp = str_nth(f, f+flen, rlen, enc, singlebyte);
- n = fp - f;
- memcpy(p,f,n);
- p+=n;
- break;
- }
- }
- *p = '\0';
- STR_SET_LEN(res, p-RSTRING_BYTEPTR(res));
- OBJ_INFECT(res, str);
- if (!NIL_P(pad)) OBJ_INFECT(res, pad);
- rb_enc_associate(res, enc);
- return res;
-#endif
}
@@ -7935,15 +4790,8 @@
for (i=0; i<argc; i++) {
VALUE tmp = rb_check_string_type(argv[i]);
if (NIL_P(tmp)) continue;
-#if WITH_OBJC
if (CFStringHasPrefix((CFStringRef)str, (CFStringRef)tmp))
return Qtrue;
-#else
- rb_enc_check(str, tmp);
- if (RSTRING_BYTELEN(str) < RSTRING_BYTELEN(tmp)) continue;
- if (memcmp(RSTRING_BYTEPTR(str), RSTRING_BYTEPTR(tmp), RSTRING_BYTELEN(tmp)) == 0)
- return Qtrue;
-#endif
}
return Qfalse;
}
@@ -7959,27 +4807,12 @@
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
int i;
-#if !WITH_OBJC
- char *p, *s;
- rb_encoding *enc;
-#endif
for (i=0; i<argc; i++) {
VALUE tmp = rb_check_string_type(argv[i]);
if (NIL_P(tmp)) continue;
-#if WITH_OBJC
if (CFStringHasSuffix((CFStringRef)str, (CFStringRef)tmp))
return Qtrue;
-#else
- enc = rb_enc_check(str, tmp);
- if (RSTRING_BYTELEN(str) < RSTRING_BYTELEN(tmp)) continue;
- p = RSTRING_BYTEPTR(str);
- s = p + RSTRING_BYTELEN(str) - RSTRING_BYTELEN(tmp);
- if (rb_enc_left_char_head(p, s, enc) != s)
- continue;
- if (memcmp(s, RSTRING_BYTEPTR(tmp), RSTRING_BYTELEN(tmp)) == 0)
- return Qtrue;
-#endif
}
return Qfalse;
}
@@ -8005,8 +4838,7 @@
rb_str_force_encoding(VALUE str, VALUE enc)
{
str_modifiable(str);
-#if WITH_OBJC
-# if 0
+#if 0
CFDataRef data = rb_str_cfdata2(str);
if (data != NULL) {
CFStringRef substr;
@@ -8023,9 +4855,6 @@
rb_str_cfdata_set(str, NULL);
}
}
-# endif
-#else
- rb_enc_associate(str, rb_to_encoding(enc));
#endif
return str;
}
@@ -8044,13 +4873,7 @@
static VALUE
rb_str_valid_encoding_p(VALUE str)
{
-#if WITH_OBJC
rb_notimplement();
-#else
- int cr = rb_enc_str_coderange(str);
-
- return cr == ENC_CODERANGE_BROKEN ? Qfalse : Qtrue;
-#endif
}
/*
@@ -8066,16 +4889,9 @@
static VALUE
rb_str_is_ascii_only_p(VALUE str)
{
-#if WITH_OBJC
rb_notimplement();
-#else
- int cr = rb_enc_str_coderange(str);
-
- return cr == ENC_CODERANGE_7BIT ? Qtrue : Qfalse;
-#endif
}
-#if WITH_OBJC
static VALUE
rb_str_transform_bang(VALUE str, VALUE transform_name)
{
@@ -8104,8 +4920,6 @@
return str;
}
-#endif
-
/**********************************************************************
* Document-class: Symbol
*
@@ -8169,38 +4983,16 @@
static VALUE
sym_inspect(VALUE sym)
{
-#if WITH_OBJC
- ID id = SYM2ID(sym);
VALUE str;
- sym = rb_id2str(id);
+#if 0
if (!rb_enc_symname_p(RSTRING_PTR(sym), NULL)) {
sym = rb_str_inspect(sym);
}
- str = rb_str_new(":", 1);
+#endif
+ str = rb_str_new2(":");
rb_str_buf_append(str, sym);
return str;
-#else
- VALUE str, klass = Qundef;
- ID id = SYM2ID(sym);
- rb_encoding *enc;
-
- sym = rb_id2str(id);
- enc = STR_ENC_GET(sym);
- str = rb_enc_str_new(0, RSTRING_BYTELEN(sym)+1, enc);
- RSTRING_BYTEPTR(str)[0] = ':';
- memcpy(RSTRING_BYTEPTR(str)+1, RSTRING_BYTEPTR(sym), RSTRING_BYTELEN(sym));
- if (RSTRING_BYTELEN(sym) != strlen(RSTRING_BYTEPTR(sym)) ||
- !rb_enc_symname_p(RSTRING_BYTEPTR(sym), enc)) {
- str = rb_str_inspect(str);
- strncpy(RSTRING_BYTEPTR(str), ":\"", 2);
- }
- if (klass != Qundef) {
- rb_str_cat2(str, "/");
- rb_str_append(str, rb_inspect(klass));
- }
- return str;
-#endif
}
@@ -8218,9 +5010,7 @@
VALUE
rb_sym_to_s(VALUE sym)
{
- ID id = SYM2ID(sym);
-
- return str_new3(rb_cString, rb_id2str(id));
+ return rb_str_new2(RSYMBOL(sym)->str);
}
@@ -8267,92 +5057,6 @@
return rb_proc_new(sym_call, (VALUE)SYM2ID(sym));
}
-
-static VALUE
-sym_succ(VALUE sym)
-{
- return rb_str_intern(rb_str_succ(rb_sym_to_s(sym)));
-}
-
-static VALUE
-sym_cmp(VALUE sym, VALUE other)
-{
- if (!SYMBOL_P(other)) {
- return Qnil;
- }
- return rb_str_cmp_m(rb_sym_to_s(sym), rb_sym_to_s(other));
-}
-
-static VALUE
-sym_casecmp(VALUE sym, VALUE other)
-{
- if (!SYMBOL_P(other)) {
- return Qnil;
- }
- return rb_str_casecmp(rb_sym_to_s(sym), rb_sym_to_s(other));
-}
-
-static VALUE
-sym_match(VALUE sym, VALUE other)
-{
- return rb_str_match(rb_sym_to_s(sym), other);
-}
-
-static VALUE
-sym_eqq(VALUE sym, VALUE other)
-{
- if (sym == other) return Qtrue;
- return rb_str_equal(rb_sym_to_s(sym), other);
-}
-
-static VALUE
-sym_aref(int argc, VALUE *argv, VALUE sym)
-{
- return rb_str_aref_m(argc, argv, rb_sym_to_s(sym));
-}
-
-static VALUE
-sym_length(VALUE sym)
-{
- return rb_str_length(rb_id2str(SYM2ID(sym)));
-}
-
-static VALUE
-sym_empty(VALUE sym)
-{
- return rb_str_empty(rb_id2str(SYM2ID(sym)));
-}
-
-static VALUE
-sym_upcase(VALUE sym)
-{
- return rb_str_intern(rb_str_upcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_downcase(VALUE sym)
-{
- return rb_str_intern(rb_str_downcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_capitalize(VALUE sym)
-{
- return rb_str_intern(rb_str_capitalize(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_swapcase(VALUE sym)
-{
- return rb_str_intern(rb_str_swapcase(rb_id2str(SYM2ID(sym))));
-}
-
-static VALUE
-sym_encoding(VALUE sym)
-{
- return rb_obj_encoding(rb_id2str(SYM2ID(sym)));
-}
-
ID
rb_to_id(VALUE name)
{
@@ -8364,7 +5068,7 @@
tmp = rb_check_string_type(name);
if (NIL_P(tmp)) {
rb_raise(rb_eTypeError, "%s is not a symbol",
- RSTRING_BYTEPTR(rb_inspect(name)));
+ RSTRING_PTR(rb_inspect(name)));
}
name = tmp;
/* fall through */
@@ -8377,12 +5081,9 @@
return id;
}
-#if WITH_OBJC
-#define NSCFSTRING() (RCLASS_OCID(rb_cCFString))
-
#define PREPARE_RCV(x) \
Class old = *(Class *)x; \
- *(Class *)x = NSCFSTRING();
+ *(Class *)x = (Class)rb_cCFString;
#define RESTORE_RCV(x) \
*(Class *)x = old;
@@ -8390,7 +5091,7 @@
bool
rb_objc_str_is_pure(VALUE str)
{
- return *(Class *)str == NSCFSTRING();
+ return *(Class *)str == (Class)rb_cCFString;
}
static CFIndex
@@ -8472,9 +5173,6 @@
return flag;
}
-void
-rb_objc_install_string_primitives(Class klass)
-{
#define INSTALL_METHOD(selname, imp) \
do { \
SEL sel = sel_registerName(selname); \
@@ -8485,6 +5183,9 @@
} \
while(0)
+void
+rb_objc_install_string_primitives(Class klass)
+{
INSTALL_METHOD("length", imp_rb_str_length);
INSTALL_METHOD("characterAtIndex:", imp_rb_str_characterAtIndex);
INSTALL_METHOD("getCharacters:range:", imp_rb_str_getCharactersRange);
@@ -8495,11 +5196,51 @@
INSTALL_METHOD("_fastestEncodingInCFStringEncoding",
imp_rb_str_fastestEncodingInCFStringEncoding);
INSTALL_METHOD("isEqual:", imp_rb_str_isEqual);
+
+ rb_define_alloc_func((VALUE)klass, str_alloc);
+}
-#undef INSTALL_METHOD
+static CFIndex
+imp_rb_symbol_length(void *rcv, SEL sel)
+{
+ return RSYMBOL(rcv)->len;
}
-#endif
+static UniChar
+imp_rb_symbol_characterAtIndex(void *rcv, SEL sel, CFIndex idx)
+{
+ if (idx < 0 || idx > RSYMBOL(rcv)->len)
+ rb_bug("[Symbol characterAtIndex:] out of bounds");
+ return RSYMBOL(rcv)->str[idx];
+}
+
+static void
+imp_rb_symbol_getCharactersRange(void *rcv, SEL sel, UniChar *buffer,
+ CFRange range)
+{
+ int i;
+
+ if (range.location + range.length > RSYMBOL(rcv)->len)
+ rb_bug("[Symbol getCharacters:range:] out of bounds");
+
+ for (i = range.location; i < range.length; i++) {
+ *buffer = RSYMBOL(rcv)->str[i];
+ buffer++;
+ }
+}
+
+static void
+install_symbol_primitives(void)
+{
+ Class klass = (Class)rb_cSymbol;
+
+ INSTALL_METHOD("length", imp_rb_symbol_length);
+ INSTALL_METHOD("characterAtIndex:", imp_rb_symbol_characterAtIndex);
+ INSTALL_METHOD("getCharacters:range:", imp_rb_symbol_getCharactersRange);
+}
+
+#undef INSTALL_METHOD
+
/*
* A <code>String</code> object holds and manipulates an arbitrary sequence of
* bytes, typically representing characters. String objects may be created
@@ -8516,29 +5257,21 @@
void
Init_String(void)
{
-#if WITH_OBJC
- rb_cCFString = rb_objc_import_class((Class)objc_getClass("NSCFString"));
- rb_cString = rb_objc_import_class((Class)objc_getClass("NSString"));
- rb_cStringRuby =
- rb_objc_import_class((Class)objc_getClass("NSMutableString"));
- FL_UNSET(rb_cStringRuby, RCLASS_OBJC_IMPORTED);
- rb_const_set(rb_cObject, rb_intern("String"), rb_cStringRuby);
+ rb_cCFString = (VALUE)objc_getClass("NSCFString");
+ rb_cString = rb_cNSString = (VALUE)objc_getClass("NSString");
+ rb_cNSMutableString = (VALUE)objc_getClass("NSMutableString");
+ rb_const_set(rb_cObject, rb_intern("String"), rb_cNSMutableString);
+ rb_set_class_path(rb_cNSMutableString, rb_cObject, "NSMutableString");
rb_define_method(rb_cString, "__bytestring__?", rb_str_bytestring_m, 0);
-#else
- rb_cString = rb_define_class("String", rb_cObject);
-#endif
+
rb_include_module(rb_cString, rb_mComparable);
- rb_define_alloc_func(rb_cString, str_alloc);
+
rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
rb_define_method(rb_cString, "initialize", rb_str_init, -1);
rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
rb_define_method(rb_cString, "==", rb_str_equal, 1);
rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
-#if 1
- /* FIXME remove me once we use the objc dispatch for everything */
- rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
-#endif
rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
rb_define_method(rb_cString, "+", rb_str_plus, 1);
rb_define_method(rb_cString, "*", rb_str_times, 1);
@@ -8546,12 +5279,6 @@
rb_define_method(rb_cString, "[]", rb_str_aref_m, -1);
rb_define_method(rb_cString, "[]=", rb_str_aset_m, -1);
rb_define_method(rb_cString, "insert", rb_str_insert, 2);
-#if !WITH_OBJC
- /* This method cannot be defined because it exists in
- * NSString already.
- */
- rb_define_method(rb_cString, "length", rb_str_length, 0);
-#endif
rb_define_method(rb_cString, "size", rb_str_length, 0);
rb_define_method(rb_cString, "bytesize", rb_str_bytesize, 0);
rb_define_method(rb_cString, "empty?", rb_str_empty, 0);
@@ -8656,49 +5383,34 @@
rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);
rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);
-#if WITH_OBJC
rb_define_method(rb_cString, "transform", rb_str_transform, 1);
rb_define_method(rb_cString, "transform!", rb_str_transform_bang, 1);
-#endif
+ /* to return mutable copies */
+ rb_define_method(rb_cString, "dup", rb_str_dup, 0);
+ rb_define_method(rb_cString, "clone", rb_str_clone, 0);
+
id_to_s = rb_intern("to_s");
rb_fs = Qnil;
rb_define_variable("$;", &rb_fs);
rb_define_variable("$-F", &rb_fs);
- rb_cSymbol = rb_define_class("Symbol", rb_cObject);
- rb_include_module(rb_cSymbol, rb_mComparable);
+ /* rb_cSymbol is defined in parse.y because it's needed early */
+ rb_set_class_path(rb_cSymbol, rb_cObject, "Symbol");
rb_undef_alloc_func(rb_cSymbol);
rb_undef_method(CLASS_OF(rb_cSymbol), "new");
rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
rb_define_method(rb_cSymbol, "==", sym_equal, 1);
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
+ rb_define_method(rb_cSymbol, "description", sym_inspect, 0);
+ rb_define_method(rb_cSymbol, "dup", rb_obj_dup, 0);
+ rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0);
rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0);
rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
- rb_define_method(rb_cSymbol, "to_proc", sym_to_proc, 0);
- rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
- rb_define_method(rb_cSymbol, "next", sym_succ, 0);
- rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
- rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
- rb_define_method(rb_cSymbol, "=~", sym_match, 1);
- rb_define_method(rb_cSymbol, "===", sym_eqq, 1);
-
- rb_define_method(rb_cSymbol, "[]", sym_aref, -1);
- rb_define_method(rb_cSymbol, "slice", sym_aref, -1);
- rb_define_method(rb_cSymbol, "length", sym_length, 0);
- rb_define_method(rb_cSymbol, "size", sym_length, 0);
- rb_define_method(rb_cSymbol, "empty?", sym_empty, 0);
- rb_define_method(rb_cSymbol, "match", sym_match, 1);
-
- rb_define_method(rb_cSymbol, "upcase", sym_upcase, 0);
- rb_define_method(rb_cSymbol, "downcase", sym_downcase, 0);
- rb_define_method(rb_cSymbol, "capitalize", sym_capitalize, 0);
- rb_define_method(rb_cSymbol, "swapcase", sym_swapcase, 0);
-
- rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
+ install_symbol_primitives();
}
Modified: MacRuby/trunk/struct.c
===================================================================
--- MacRuby/trunk/struct.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/struct.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -181,7 +181,9 @@
OBJ_FREEZE(members);
if (NIL_P(name)) {
nstr = rb_class_new(klass);
+#if !WITH_OBJC
rb_make_metaclass(nstr, RBASIC(klass)->klass);
+#endif
rb_class_inherited(klass, nstr);
}
else {
Modified: MacRuby/trunk/thread.c
===================================================================
--- MacRuby/trunk/thread.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/thread.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -3102,7 +3102,7 @@
if (TYPE(klass) == T_ICLASS) {
klass = RBASIC(klass)->klass;
}
- else if (FL_TEST(klass, FL_SINGLETON)) {
+ else if (RCLASS_SINGLETON(klass)) {
klass = rb_iv_get(klass, "__attached__");
}
}
Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/variable.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -15,14 +15,53 @@
#include "ruby/node.h"
#include "ruby/st.h"
#include "ruby/util.h"
+#include "debug.h"
+#include "id.h"
void rb_vm_change_state(void);
st_table *rb_global_tbl;
st_table *rb_class_tbl;
+static ID autoload, classpath, tmp_classpath;
#if WITH_OBJC
-st_table *rb_objc_class_tbl;
+static const void *
+retain_cb(CFAllocatorRef allocator, const void *v)
+{
+ rb_objc_retain(v);
+ return v;
+}
+
+static void
+release_cb(CFAllocatorRef allocator, const void *v)
+{
+ rb_objc_release(v);
+}
+
+static void
+ivar_dict_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg)
+{
+ CFIndex i, count;
+ const void **keys;
+ const void **values;
+
+ count = CFDictionaryGetCount((CFDictionaryRef)hash);
+ if (count == 0)
+ return;
+
+ keys = (const void **)alloca(sizeof(void *) * count);
+ values = (const void **)alloca(sizeof(void *) * count);
+
+ CFDictionaryGetKeysAndValues((CFDictionaryRef)hash, keys, values);
+
+ for (i = 0; i < count; i++) {
+ if ((*func)(keys[i], values[i], farg) != ST_CONTINUE)
+ break;
+ }
+}
+
+static CFDictionaryValueCallBacks rb_cfdictionary_value_cb = {
+ 0, retain_cb, release_cb, NULL, NULL
+};
#endif
-static ID autoload, classpath, tmp_classpath;
void
Init_var_tables(void)
@@ -31,10 +70,6 @@
GC_ROOT(&rb_global_tbl);
rb_class_tbl = st_init_numtable();
GC_ROOT(&rb_class_tbl);
-#if WITH_OBJC
- rb_objc_class_tbl = st_init_numtable();
- GC_ROOT(&rb_objc_class_tbl);
-#endif
autoload = rb_intern("__autoload__");
classpath = rb_intern("__classpath__");
tmp_classpath = rb_intern("__tmp_classpath__");
@@ -56,8 +91,12 @@
path = rb_str_dup(rb_id2str(name));
while (fc) {
if (fc->track == rb_cObject) break;
+#if WITH_OBJC
+ if ((tmp = rb_attr_get(fc->track, classpath)) != Qnil) {
+#else
if (RCLASS_IV_TBL(fc->track) &&
st_lookup(RCLASS_IV_TBL(fc->track), classpath, &tmp)) {
+#endif
tmp = rb_str_dup(tmp);
rb_str_cat2(tmp, "::");
rb_str_append(tmp, path);
@@ -86,7 +125,13 @@
switch (TYPE(value)) {
case T_MODULE:
case T_CLASS:
+ {
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(value);
+ if (iv_dict == NULL) return ST_CONTINUE;
+#else
if (!RCLASS_IV_TBL(value)) return ST_CONTINUE;
+#endif
else {
struct fc_result arg;
struct fc_result *list;
@@ -102,13 +147,18 @@
arg.klass = res->klass;
arg.track = value;
arg.prev = res;
+#if WITH_OBJC
+ ivar_dict_foreach((VALUE)iv_dict, fc_i, (VALUE)&arg);
+#else
st_foreach(RCLASS_IV_TBL(value), fc_i, (st_data_t)&arg);
+#endif
if (arg.path) {
res->path = arg.path;
return ST_STOP;
}
}
break;
+ }
default:
break;
@@ -126,20 +176,43 @@
arg.klass = klass;
arg.track = rb_cObject;
arg.prev = 0;
+
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
+ if (iv_dict != NULL) {
+ ivar_dict_foreach((VALUE)iv_dict, fc_i, (VALUE)&arg);
+ }
+#else
if (RCLASS_IV_TBL(rb_cObject)) {
st_foreach_safe(RCLASS_IV_TBL(rb_cObject), fc_i, (st_data_t)&arg);
}
+#endif
if (arg.path == 0) {
st_foreach_safe(rb_class_tbl, fc_i, (st_data_t)&arg);
}
if (arg.path) {
+#if WITH_OBJC
+ iv_dict = rb_class_ivar_dict_or_create(klass);
+ CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)arg.path);
+ CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
+#else
if (!RCLASS_IV_TBL(klass)) {
GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
}
st_insert(RCLASS_IV_TBL(klass), classpath, arg.path);
st_delete(RCLASS_IV_TBL(klass), &tmp_classpath, 0);
+#endif
return arg.path;
}
+#if WITH_OBJC
+ if (!RCLASS_RUBY(klass)) {
+ VALUE name = rb_str_new2(class_getName((Class)klass));
+ iv_dict = rb_class_ivar_dict_or_create(klass);
+ CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)name);
+ CFDictionaryRemoveValue(iv_dict, (const void *)tmp_classpath);
+ return name;
+ }
+#endif
return Qnil;
}
@@ -149,6 +222,25 @@
VALUE path = Qnil;
if (!klass) klass = rb_cObject;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
+ if (iv_dict != NULL) {
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)classpath, (const void **)&path)) {
+
+ static ID classid = 0;
+ if (classid == 0)
+ classid = rb_intern("__classid__");
+
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)classid, (const void **)&path))
+ return find_class_path(klass);
+
+ path = rb_str_dup(path);
+ OBJ_FREEZE(path);
+ CFDictionarySetValue(iv_dict, (const void *)classpath, (const void *)path);
+ CFDictionaryRemoveValue(iv_dict, (const void *)classid);
+#else
if (RCLASS_IV_TBL(klass)) {
if (!st_lookup(RCLASS_IV_TBL(klass), classpath, &path)) {
ID classid = rb_intern("__classid__");
@@ -160,12 +252,11 @@
OBJ_FREEZE(path);
st_insert(RCLASS_IV_TBL(klass), classpath, path);
st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&classid, 0);
+#endif
}
-#if !WITH_OBJC
if (TYPE(path) != T_STRING) {
rb_bug("class path is not set properly");
}
-#endif
return path;
}
return find_class_path(klass);
@@ -193,8 +284,12 @@
VALUE path = classname(klass);
if (!NIL_P(path)) return path;
+#if WITH_OBJC
+ if ((path = rb_attr_get(klass, tmp_classpath)) != Qnil) {
+#else
if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
tmp_classpath, &path)) {
+#endif
return path;
}
else {
@@ -231,9 +326,6 @@
}
OBJ_FREEZE(str);
rb_ivar_set(klass, classpath, str);
-#if WITH_OBJC
- rb_objc_rename_class(klass, RSTRING_PTR(str));
-#endif
}
VALUE
@@ -313,10 +405,13 @@
struct trace_var *trace;
};
+#if !WITH_OBJC
+/* defined in vm_core.h, imported by debug.h */
struct global_entry {
struct global_variable *var;
ID id;
};
+#endif
static VALUE undef_getter(ID id);
static void undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
@@ -390,7 +485,7 @@
static void
val_setter(VALUE val, ID id, void *data, struct global_variable *var)
{
- var->data = (void*)val;
+ GC_WB(&var->data, (void*)val);
}
static void
@@ -786,8 +881,6 @@
#if WITH_OBJC
static CFMutableDictionaryRef generic_iv_dict = NULL;
-const void * rb_cfdictionary_retain_cb(CFAllocatorRef, const void *);
-void rb_cfdictionary_release_cb(CFAllocatorRef, const void *);
#else
static int special_generic_ivar = 0;
static st_table *generic_iv_tbl;
@@ -854,13 +947,7 @@
rb_error_frozen("object");
}
if (generic_iv_dict == NULL) {
- CFDictionaryValueCallBacks values_cb;
-
- memset(&values_cb, 0, sizeof(values_cb));
- values_cb.retain = rb_cfdictionary_retain_cb;
- values_cb.release = rb_cfdictionary_release_cb;
-
- generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
obj_dict = NULL;
}
else {
@@ -868,13 +955,7 @@
(CFDictionaryRef)generic_iv_dict, (const void *)obj);
}
if (obj_dict == NULL) {
- CFDictionaryValueCallBacks values_cb;
-
- memset(&values_cb, 0, sizeof(values_cb));
- values_cb.retain = rb_cfdictionary_retain_cb;
- values_cb.release = rb_cfdictionary_release_cb;
-
- obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &values_cb);
+ obj_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
CFDictionarySetValue(generic_iv_dict, (const void *)obj,
(const void *)obj_dict);
CFMakeCollectable(obj_dict);
@@ -1078,21 +1159,98 @@
#endif
}
+#if WITH_OBJC
+# define RCLASS_RUBY_IVAR_DICT(mod) (*(CFMutableDictionaryRef *)((void *)mod + class_getInstanceSize(*(Class *)RCLASS_SUPER(mod))))
+CFMutableDictionaryRef
+rb_class_ivar_dict(VALUE mod)
+{
+ CFMutableDictionaryRef dict;
+
+ if (RCLASS_RUBY(mod)) {
+ dict = RCLASS_RUBY_IVAR_DICT(mod);
+ }
+ else {
+ dict = NULL;
+ if (generic_iv_dict != NULL) {
+ CFDictionaryGetValueIfPresent(generic_iv_dict,
+ (const void *)mod, (const void **)&dict);
+ }
+ }
+ return dict;
+}
+
+void
+rb_class_ivar_set_dict(VALUE mod, CFMutableDictionaryRef dict)
+{
+ if (RCLASS_RUBY(mod)) {
+ CFMutableDictionaryRef old_dict = RCLASS_RUBY_IVAR_DICT(mod);
+ if (old_dict != dict) {
+ if (old_dict != NULL)
+ CFRelease(old_dict);
+ CFRetain(dict);
+ RCLASS_RUBY_IVAR_DICT(mod) = dict;
+ }
+ }
+ else {
+ if (generic_iv_dict == NULL) {
+ generic_iv_dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
+ }
+ CFDictionarySetValue(generic_iv_dict, (const void *)mod, (const void *)dict);
+ }
+}
+
+CFMutableDictionaryRef
+rb_class_ivar_dict_or_create(VALUE mod)
+{
+ CFMutableDictionaryRef dict;
+
+ dict = rb_class_ivar_dict(mod);
+ if (dict == NULL) {
+ dict = CFDictionaryCreateMutable(NULL, 0, NULL, &rb_cfdictionary_value_cb);
+ rb_class_ivar_set_dict(mod, dict);
+ CFMakeCollectable(dict);
+ }
+ return dict;
+}
+#endif
+
static VALUE
ivar_get(VALUE obj, ID id, int warn)
{
- VALUE val, *ptr;
+ VALUE val;
+#if !WITH_OBJC
+ VALUE *ptr;
struct st_table *iv_index_tbl;
long len;
st_data_t index;
-
-#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj))
- return generic_ivar_get(obj, id, warn);
#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ val = Qundef;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ break;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (!CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id,
+ (const void **)&val))
+ val = Qundef;
+ break;
+ }
+#else
len = ROBJECT_NUMIV(obj);
ptr = ROBJECT_IVPTR(obj);
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
@@ -1100,14 +1258,30 @@
if (!st_lookup(iv_index_tbl, id, &index)) break;
if (len <= index) break;
val = ptr[index];
+#endif
+
if (val != Qundef)
return val;
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL
+ && CFDictionaryGetValueIfPresent(
+ iv_dict, (const void *)id, (const void **)&val))
+ return val;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, &val))
return val;
+#endif
break;
+#if WITH_OBJC
+ case T_NATIVE:
+ return generic_ivar_get(obj, id, warn);
+#endif
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
return generic_ivar_get(obj, id, warn);
@@ -1134,23 +1308,90 @@
VALUE
rb_ivar_set(VALUE obj, ID id, VALUE val)
{
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
long i, len;
int ivar_extended;
+#endif
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
-#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj)) {
- rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
- generic_ivar_set(obj, id, val);
- return val;
- }
-#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i, len;
+ bool new_ivar;
+
+ len = RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars);
+ new_ivar = true;
+
+ if (len == 0) {
+ assert(ROBJECT(obj)->ivars.as.ary == NULL);
+ GC_WB(&ROBJECT(obj)->ivars.as.ary,
+ (struct rb_ivar_ary_entry *)xmalloc(
+ sizeof(struct rb_ivar_ary_entry)));
+ }
+ else {
+ assert(ROBJECT(obj)->ivars.as.ary != NULL);
+ for (i = 0; i < len; i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].value == Qundef) {
+ ROBJECT(obj)->ivars.as.ary[i].name = id;
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[i].value, val);
+ new_ivar = false;
+ break;
+ }
+ else if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[i].value, val);
+ new_ivar = false;
+ break;
+ }
+ }
+ }
+ if (new_ivar) {
+ if (len + 1 == RB_IVAR_ARY_MAX) {
+ CFMutableDictionaryRef tbl;
+ tbl = CFDictionaryCreateMutable(NULL, 0, NULL,
+ &rb_cfdictionary_value_cb);
+
+ for (i = 0; i < len; i++)
+ CFDictionarySetValue(tbl,
+ (const void *)ROBJECT(obj)->ivars.as.ary[i].name,
+ (const void *)ROBJECT(obj)->ivars.as.ary[i].value);
+
+ CFDictionarySetValue(tbl, (const void *)id,
+ (const void *)val);
+
+ xfree(ROBJECT(obj)->ivars.as.ary);
+ GC_WB(&ROBJECT(obj)->ivars.as.tbl, tbl);
+ CFMakeCollectable(tbl);
+ RB_IVAR_SET_TYPE(ROBJECT(obj)->ivars, RB_IVAR_TBL);
+ }
+ else {
+ if (len > 0) {
+ struct rb_ivar_ary_entry *ary;
+ ary = ROBJECT(obj)->ivars.as.ary;
+ REALLOC_N(ary, struct rb_ivar_ary_entry, len + 1);
+ GC_WB(&ROBJECT(obj)->ivars.as.ary, ary);
+ }
+ ROBJECT(obj)->ivars.as.ary[len].name = id;
+ GC_WB(&ROBJECT(obj)->ivars.as.ary[len].value, val);
+ RB_IVAR_ARY_SET_LEN(ROBJECT(obj)->ivars, len + 1);
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ CFDictionarySetValue(ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id, (const void *)val);
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) {
VALUE klass = rb_obj_class(obj);
@@ -1200,14 +1441,29 @@
}
}
GC_WB(&ROBJECT_IVPTR(obj)[index], val);
+#endif
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(obj);
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
+ break;
+ }
+#else
if (!RCLASS_IV_TBL(obj)) {
GC_WB(&RCLASS_IV_TBL(obj), st_init_numtable());
}
st_insert(RCLASS_IV_TBL(obj), id, val);
break;
+#endif
+#if WITH_OBJC
+ case T_NATIVE:
+ rb_objc_flag_set((const void *)obj, FL_EXIVAR, true);
+ generic_ivar_set(obj, id, val);
+ break;
+#endif
default:
generic_ivar_set(obj, id, val);
FL_SET(obj, FL_EXIVAR);
@@ -1220,28 +1476,63 @@
rb_ivar_defined(VALUE obj, ID id)
{
VALUE val;
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
-#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj)) {
- return generic_ivar_defined(obj, id);
- }
#endif
+
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ val = Qundef;
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ break;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id, NULL))
+ val = Qtrue;
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, id, &index)) break;
if (ROBJECT_NUMIV(obj) <= index) break;
val = ROBJECT_IVPTR(obj)[index];
+#endif
if (val != Qundef)
return Qtrue;
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, NULL))
+ return Qtrue;
+ break;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_lookup(RCLASS_IV_TBL(obj), id, 0))
return Qtrue;
break;
+#endif
+#if WITH_OBJC
+ case T_NATIVE:
+ return generic_ivar_defined(obj, id);
+#endif
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))
return generic_ivar_defined(obj, id);
@@ -1256,6 +1547,7 @@
st_data_t arg;
};
+#if !WITH_OBJC
static int
obj_ivar_i(ID key, VALUE index, struct obj_ivar_tag *data)
{
@@ -1284,23 +1576,53 @@
st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
}
+#endif
void rb_ivar_foreach(VALUE obj, int (*func)(ANYARGS), st_data_t arg)
{
-#if WITH_OBJC
- if (!rb_special_const_p(obj) && rb_objc_is_non_native(obj))
- goto generic;
-#endif
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if ((*func)(ROBJECT(obj)->ivars.as.ary[i].name,
+ ROBJECT(obj)->ivars.as.ary[i].value, arg)
+ != ST_CONTINUE)
+ break;
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ CFDictionaryApplyFunction(ROBJECT(obj)->ivars.as.tbl,
+ (CFDictionaryApplierFunction)func, (void *)arg);
+ break;
+ }
+#else
obj_ivar_each(obj, func, arg);
+#endif
return;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL)
+ ivar_dict_foreach((VALUE)iv_dict, func, arg);
+ }
+#else
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
}
+#endif
return;
+#if WITH_OBJC
+ case T_NATIVE:
+ goto generic;
+#endif
}
if (!FL_TEST(obj, FL_EXIVAR) && !rb_special_const_p(obj))
return;
@@ -1390,8 +1712,10 @@
{
VALUE val = Qnil;
ID id = rb_to_id(name);
+#if !WITH_OBJC
struct st_table *iv_index_tbl;
st_data_t index;
+#endif
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
@@ -1402,6 +1726,33 @@
switch (TYPE(obj)) {
case T_OBJECT:
+#if WITH_OBJC
+ switch (RB_IVAR_TYPE(ROBJECT(obj)->ivars)) {
+ case RB_IVAR_ARY:
+ {
+ int i;
+ for (i = 0; i < RB_IVAR_ARY_LEN(ROBJECT(obj)->ivars); i++) {
+ if (ROBJECT(obj)->ivars.as.ary[i].name == id) {
+ val = ROBJECT(obj)->ivars.as.ary[i].value;
+ ROBJECT(obj)->ivars.as.ary[i].value = Qundef;
+ return val;
+ }
+ }
+ break;
+ }
+
+ case RB_IVAR_TBL:
+ if (CFDictionaryGetValueIfPresent(
+ (CFDictionaryRef)ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id,
+ (const void **)val)) {
+ CFDictionaryRemoveValue(ROBJECT(obj)->ivars.as.tbl,
+ (const void *)id);
+ return val;
+ }
+ break;
+ }
+#else
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
if (!iv_index_tbl) break;
if (!st_lookup(iv_index_tbl, id, &index)) break;
@@ -1411,13 +1762,25 @@
ROBJECT_IVPTR(obj)[index] = Qundef;
return val;
}
+#endif
break;
case T_CLASS:
case T_MODULE:
+#if WITH_OBJC
+ {
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ return val;
+ }
+ break;
+ }
+#else
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t*)&id, &val)) {
return val;
}
break;
+#endif
default:
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
if (generic_ivar_remove(obj, id, &val)) {
@@ -1486,14 +1849,15 @@
return Qnil; /* not reached */
}
+#if WITH_OBJC
+static void *rb_mark_tbl = (void *)0x42;
+#endif
+
static struct st_table *
check_autoload_table(VALUE av)
{
Check_Type(av, T_DATA);
- if (
-#if !WITH_OBJC
- RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
-#endif
+ if (RDATA(av)->dmark != (RUBY_DATA_FUNC)rb_mark_tbl ||
RDATA(av)->dfree != (RUBY_DATA_FUNC)st_free_table) {
VALUE desc = rb_inspect(av);
rb_raise(rb_eTypeError, "wrong autoload table: %s", RSTRING_PTR(desc));
@@ -1514,21 +1878,29 @@
rb_raise(rb_eArgError, "empty file name");
}
+#if WITH_OBJC
+ if ((av = rb_attr_get(mod, id)) != Qnil && av != Qundef)
+#else
if ((tbl = RCLASS_IV_TBL(mod)) && st_lookup(tbl, id, &av) && av != Qundef)
+#endif
return;
rb_const_set(mod, id, Qundef);
+#if WITH_OBJC
+ if ((av = rb_attr_get(mod, autoload)) != Qnil) {
+#else
tbl = RCLASS_IV_TBL(mod);
if (st_lookup(tbl, autoload, &av)) {
+#endif
tbl = check_autoload_table(av);
}
else {
+ av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
#if WITH_OBJC
- av = Data_Wrap_Struct(0, NULL, st_free_table, 0);
+ rb_ivar_set(mod, autoload, av);
#else
- av = Data_Wrap_Struct(0, rb_mark_tbl, st_free_table, 0);
+ st_add_direct(tbl, autoload, av);
#endif
- st_add_direct(tbl, autoload, av);
DATA_PTR(av) = tbl = st_init_numtable();
}
fn = rb_str_new2(file);
@@ -1543,8 +1915,16 @@
VALUE val;
st_data_t load = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ assert(iv_dict != NULL);
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)autoload, (const void **)&val)) {
+#else
st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, 0);
if (st_lookup(RCLASS_IV_TBL(mod), autoload, &val)) {
+#endif
struct st_table *tbl = check_autoload_table(val);
st_delete(tbl, (st_data_t*)&id, &load);
@@ -1553,9 +1933,13 @@
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
+#if WITH_OBJC
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
rb_gc_force_recycle(val);
}
+#endif
}
}
@@ -1581,10 +1965,20 @@
struct st_table *tbl;
st_data_t load;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ assert(iv_dict != NULL);
+ if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict,
+ (const void *)autoload, (const void **)&val)
+ || (tbl = check_autoload_table(val)) == NULL
+ || !st_lookup(tbl, id, &load))
+ return Qnil;
+#else
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
!(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
return Qnil;
}
+#endif
file = ((NODE *)load)->nd_lit;
Check_Type(file, T_STRING);
if (RSTRING_LEN(file) == 0) {
@@ -1600,9 +1994,13 @@
DATA_PTR(val) = 0;
st_free_table(tbl);
id = autoload;
+#if WITH_OBJC
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
rb_gc_force_recycle(val);
}
+#endif
}
return Qnil;
}
@@ -1610,12 +2008,22 @@
VALUE
rb_autoload_p(VALUE mod, ID id)
{
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = (CFDictionaryRef)rb_class_ivar_dict(mod);
+ VALUE val;
+
+ if (iv_dict == NULL
+ || !CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)
+ || val != Qundef)
+ return Qnil;
+#else
struct st_table *tbl = RCLASS_IV_TBL(mod);
VALUE val;
if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
return Qnil;
}
+#endif
return autoload_file(mod, id);
}
@@ -1628,7 +2036,13 @@
tmp = klass;
retry:
while (RTEST(tmp)) {
+#if WITH_OBJC
+ CFDictionaryRef iv_dict;
+ while ((iv_dict = rb_class_ivar_dict(tmp)) != NULL
+ && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value)) {
+#else
while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) {
+#endif
if (value == Qundef) {
if (!RTEST(rb_autoload_load(tmp, id))) break;
continue;
@@ -1643,6 +2057,17 @@
return value;
}
if (!recurse && klass != rb_cObject) break;
+#if WITH_OBJC
+ VALUE inc_mods = rb_attr_get(tmp, idIncludedModules);
+ if (inc_mods != Qnil) {
+ int i, count = RARRAY_LEN(inc_mods);
+ for (i = 0; i < count; i++) {
+ iv_dict = rb_class_ivar_dict(RARRAY_AT(inc_mods, i));
+ if (CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&value))
+ return rb_objc_resolve_const_value(value, klass, id);
+ }
+ }
+#endif
tmp = RCLASS_SUPER(tmp);
}
if (!exclude && !mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
@@ -1659,11 +2084,8 @@
*/
{
Class k = (Class)objc_getClass(rb_id2name(id));
- if (k != NULL) {
- tmp = rb_objc_import_class(k);
- if (!NIL_P(tmp))
- return tmp;
- }
+ if (k != NULL)
+ return (VALUE)k;
}
#endif
@@ -1712,7 +2134,13 @@
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+#else
if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
+#endif
if (val == Qundef) {
autoload_delete(mod, id);
val = Qnil;
@@ -1746,9 +2174,15 @@
if (!tbl) {
tbl = st_init_numtable();
}
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL)
+ ivar_dict_foreach((VALUE)iv_dict, sv_i, (VALUE)tbl);
+#else
if (RCLASS_IV_TBL(mod)) {
st_foreach_safe(RCLASS_IV_TBL(mod), sv_i, (st_data_t)tbl);
}
+#endif
return tbl;
}
@@ -1831,7 +2265,13 @@
tmp = klass;
retry:
while (tmp) {
+#if WITH_OBJC
+ CFDictionaryRef iv_dict = rb_class_ivar_dict(tmp);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict,
+ (const void *)id, (const void **)&value)) {
+#else
if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) {
+#endif
if (value == Qundef && NIL_P(autoload_file(klass, id)))
return Qfalse;
return Qtrue;
@@ -1880,13 +2320,22 @@
rb_error_frozen("class");
}
}
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict_or_create(klass);
+#else
if (!RCLASS_IV_TBL(klass)) {
GC_WB(&RCLASS_IV_TBL(klass), st_init_numtable());
}
- else if (isconst) {
+ else
+#endif
+ if (isconst) {
VALUE value = Qfalse;
+#if WITH_OBJC
+ if (CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&value)) {
+#else
if (st_lookup(RCLASS_IV_TBL(klass), id, &value)) {
+#endif
if (value == Qundef)
autoload_delete(klass, id);
else
@@ -1894,10 +2343,15 @@
}
}
- if(isconst){
+ if (isconst) {
rb_vm_change_state();
}
+#if WITH_OBJC
+ DLOG("CONS", "%s::%s <- %p", class_getName((Class)klass), rb_id2name(id), (void *)val);
+ CFDictionarySetValue(iv_dict, (const void *)id, (const void *)val);
+#else
st_insert(RCLASS_IV_TBL(klass), id, val);
+#endif
}
void
@@ -1938,11 +2392,17 @@
return c;
}
+#if WITH_OBJC
+# define IV_LOOKUP(k,i,v) ((iv_dict = rb_class_ivar_dict(k)) != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)i, (const void **)(v)))
+#else
+# define IV_LOOKUP(k,i,v) (RCLASS_IV_TBL(k) && st_lookup(RCLASS_IV_TBL(k),(i),(v)))
+#endif
+
#define CVAR_LOOKUP(v,r) do {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
+ if (IV_LOOKUP(klass, id, v)) {\
r;\
}\
- if (FL_TEST(klass, FL_SINGLETON) ) {\
+ if (RCLASS_SINGLETON(klass)) {\
VALUE obj = rb_iv_get(klass, "__attached__");\
switch (TYPE(obj)) {\
case T_MODULE:\
@@ -1958,7 +2418,7 @@
klass = RCLASS_SUPER(klass);\
}\
while (klass) {\
- if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),id,(v))) {\
+ if (IV_LOOKUP(klass, id, v)) {\
r;\
}\
klass = RCLASS_SUPER(klass);\
@@ -1969,8 +2429,15 @@
rb_cvar_set(VALUE klass, ID id, VALUE val)
{
VALUE tmp, front = 0, target = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
tmp = klass;
+#if WITH_OBJC
+ if (!RCLASS_META(klass))
+ tmp = klass = *(VALUE *)klass;
+#endif
CVAR_LOOKUP(0, {if (!front) front = klass; target = klass;});
if (target) {
if (front && target != front) {
@@ -1981,8 +2448,12 @@
rb_id2name(id), rb_class2name(original_module(front)),
rb_class2name(original_module(target)));
}
- if (BUILTIN_TYPE(front) == T_CLASS) {
+ if (TYPE(front) == T_CLASS) {
+#if WITH_OBJC
+ CFDictionaryRemoveValue(rb_class_ivar_dict(front), (const void *)did);
+#else
st_delete(RCLASS_IV_TBL(front),&did,0);
+#endif
}
}
}
@@ -1996,8 +2467,15 @@
rb_cvar_get(VALUE klass, ID id)
{
VALUE value, tmp, front = 0, target = 0;
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
tmp = klass;
+#if WITH_OBJC
+ if (!RCLASS_META(klass))
+ tmp = klass = *(VALUE *)klass;
+#endif
CVAR_LOOKUP(&value, {if (!front) front = klass; target = klass;});
if (!target) {
rb_name_error(id,"uninitialized class variable %s in %s",
@@ -2012,7 +2490,11 @@
rb_class2name(original_module(target)));
}
if (BUILTIN_TYPE(front) == T_CLASS) {
+#if WITH_OBJC
+ CFDictionaryRemoveValue(rb_class_ivar_dict(front), (const void *)did);
+#else
st_delete(RCLASS_IV_TBL(front),&did,0);
+#endif
}
}
return value;
@@ -2021,7 +2503,14 @@
VALUE
rb_cvar_defined(VALUE klass, ID id)
{
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict;
+#endif
if (!klass) return Qfalse;
+#if WITH_OBJC
+ if (!RCLASS_META(klass))
+ klass = *(VALUE *)klass;
+#endif
CVAR_LOOKUP(0,return Qtrue);
return Qfalse;
}
@@ -2090,9 +2579,15 @@
{
VALUE ary = rb_ary_new();
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(obj);
+ if (iv_dict != NULL)
+ ivar_dict_foreach((VALUE)iv_dict, cv_i, (VALUE)ary);
+#else
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), cv_i, ary);
}
+#endif
return ary;
}
@@ -2129,9 +2624,17 @@
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
+#if WITH_OBJC
+ CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(mod);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent((CFDictionaryRef)iv_dict, (const void *)id, (const void **)&val)) {
+ CFDictionaryRemoveValue(iv_dict, (const void *)id);
+ return val;
+ }
+#else
if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
return val;
}
+#endif
if (rb_cvar_defined(mod, id)) {
rb_name_error(id, "cannot remove %s for %s",
rb_id2name(id), rb_class2name(mod));
Modified: MacRuby/trunk/version.c
===================================================================
--- MacRuby/trunk/version.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/version.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -23,6 +23,7 @@
const int ruby_patchlevel = RUBY_PATCHLEVEL;
const char ruby_description[] = RUBY_DESCRIPTION;
const char ruby_copyright[] = RUBY_COPYRIGHT;
+const char ruby_engine[] = RUBY_ENGINE;
void
Init_version(void)
@@ -34,6 +35,7 @@
rb_define_global_const("RUBY_REVISION", INT2FIX(RUBY_REVISION));
rb_define_global_const("RUBY_DESCRIPTION", MKSTR(description));
rb_define_global_const("RUBY_COPYRIGHT", MKSTR(copyright));
+ rb_define_global_const("RUBY_ENGINE", MKSTR(engine));
#if WITH_OBJC
rb_define_global_const("MACRUBY_VERSION", rb_float_new(MACRUBY_VERSION));
#endif
Modified: MacRuby/trunk/version.h
===================================================================
--- MacRuby/trunk/version.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/version.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -46,9 +46,9 @@
#endif
#if WITH_OBJC
-# define RUBY_IMPL_NAME "MacRuby"
+# define RUBY_ENGINE "macruby"
#else
-# define RUBY_IMPL_NAME "ruby"
+# define RUBY_ENGINE "ruby"
#endif
#if WITH_OBJC
Modified: MacRuby/trunk/vm.c
===================================================================
--- MacRuby/trunk/vm.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -14,10 +14,6 @@
#include "ruby/encoding.h"
#include "gc.h"
-#if WITH_OBJC
-NODE *rb_current_cfunc_node = NULL;
-#endif
-
#include "insnhelper.h"
#include "vm_insnhelper.c"
#include "vm_eval.c"
@@ -95,7 +91,7 @@
th->cfp->sp, block->lfp, iseq->local_size);
if (cref) {
- th->cfp->dfp[-1] = (VALUE)cref;
+ GC_WB(&th->cfp->dfp[-1], (VALUE)cref);
}
}
@@ -250,8 +246,8 @@
env->env_size = local_size + 1 + 2;
env->local_size = local_size;
- env->env = ALLOC_N(VALUE, env->env_size);
- env->prev_envval = penvval;
+ GC_WB(&env->env, ALLOC_N(VALUE, env->env_size));
+ GC_WB(&env->prev_envval, penvval);
for (i = 0; i <= local_size; i++) {
env->env[i] = envptr[-local_size + i];
@@ -857,19 +853,26 @@
static void
rb_vm_check_redefinition_opt_method(const NODE *node)
{
+#if !WITH_OBJC
VALUE bop;
- if (st_lookup(vm_opt_method_table, (st_data_t)node, &bop)) {
+ if (vm_opt_method_table != NULL
+ && st_lookup(vm_opt_method_table, (st_data_t)node, &bop)) {
ruby_vm_redefined_flag |= bop;
}
+#endif
}
static void
add_opt_method(VALUE klass, ID mid, VALUE bop)
{
NODE *node;
+#if WITH_OBJC
+ if ((node = rb_method_node(klass, mid)) != NULL) {
+#else
if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&node) &&
nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
+#endif
st_insert(vm_opt_method_table, (st_data_t)node, (st_data_t)bop);
}
else {
@@ -899,9 +902,7 @@
OP(LTLT, LTLT), (C(String), C(Array));
OP(AREF, AREF), (C(Array), C(Hash));
OP(ASET, ASET), (C(Array), C(Hash));
-#if WITH_OBJC
- OP(Length, LENGTH), (C(Array), C(Hash));
-#else
+#if !WITH_OBJC
OP(Length, LENGTH), (C(Array), C(String), C(Hash));
#endif
OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
@@ -1724,11 +1725,12 @@
rb_iseq_t *iseq;
/* create vm object */
- vm->self = Data_Wrap_Struct(rb_cVM, rb_vm_mark, vm_free, vm);
+ GC_WB(&vm->self, Data_Wrap_Struct(rb_cVM, rb_vm_mark, vm_free, vm));
/* create main thread */
- th_self = th->self = Data_Wrap_Struct(rb_cThread, rb_thread_mark,
+ th_self = Data_Wrap_Struct(rb_cThread, rb_thread_mark,
thread_free, th);
+ GC_WB(&th->self, th_self);
vm->main_thread = th;
vm->running_thread = th;
th->vm = vm;
@@ -1736,10 +1738,11 @@
th->top_self = rb_vm_top_self();
rb_thread_set_current(th);
- vm->living_threads = st_init_numtable();
+ GC_WB(&vm->living_threads, st_init_numtable());
st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
rb_register_mark_object(iseqval);
+ rb_objc_retain((void *)iseqval);
GetISeqPtr(iseqval, iseq);
th->cfp->iseq = iseq;
th->cfp->pc = iseq->iseq_encoded;
Modified: MacRuby/trunk/vm_core.h
===================================================================
--- MacRuby/trunk/vm_core.h 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_core.h 2008-08-21 06:13:14 UTC (rev 459)
@@ -543,6 +543,35 @@
#define ic_vmstat u3.cnt
typedef NODE *IC;
+#if WITH_OBJC
+# include "bs.h"
+struct rb_method_cache {
+ unsigned int flags;
+#define RB_MCACHE_RCALL_FLAG 0x10
+#define RB_MCACHE_OCALL_FLAG 0x20
+#define RB_MCACHE_CFUNC_FLAG 0x40
+#define RB_MCACHE_NOT_CFUNC_FLAG 0x100
+ union {
+ struct {
+ SEL sel;
+ VALUE klass;
+ NODE *node;
+ } rcall;
+ struct {
+ SEL sel;
+ VALUE klass;
+ IMP imp;
+ Method method;
+ bs_element_method_t *bs_method;
+ } ocall;
+ struct {
+ bs_element_function_t *bs_func;
+ void *sym;
+ } cfunc;
+ } as;
+};
+#endif
+
void rb_vm_change_state(void);
typedef VALUE CDHASH;
Modified: MacRuby/trunk/vm_eval.c
===================================================================
--- MacRuby/trunk/vm_eval.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_eval.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -72,13 +72,7 @@
cfp->method_id = id;
cfp->method_class = klass;
-#if WITH_OBJC
- rb_current_cfunc_node = (NODE *)body;
-#endif
val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
-#if WITH_OBJC
- rb_current_cfunc_node = NULL;
-#endif
if (reg_cfp != th->cfp + 1) {
SDR2(reg_cfp);
@@ -188,42 +182,56 @@
NODE *body, *method;
int noex;
ID id = mid;
+#if !WITH_OBJC
struct cache_entry *ent;
+#endif
rb_thread_t *th = GET_THREAD();
-#if WITH_OBJC
- unsigned redo = 0;
-#endif
-rb_call0_redo:
-
-#if WITH_OBJC
-# define REDO_PERHAPS() \
- do { \
- if (!redo && mid != missing) { \
- ID newid = rb_objc_missing_sel(mid, argc); \
- if (newid != mid) { \
- id = mid = newid; \
- redo = 1; \
- goto rb_call0_redo; \
- } \
- } \
- } \
- while (0)
-#else
-# define REDO_PERHAPS()
-#endif
-
if (!klass) {
rb_raise(rb_eNotImpError,
"method `%s' called on terminated object (%p)",
rb_id2name(mid), (void *)recv);
}
+
+#if WITH_OBJC
+ IMP imp;
+ SEL sel;
+
+ if (argc > 0 && mid != ID_ALLOCATOR) {
+ const char *mid_str;
+ char buf[100];
+ size_t len;
+
+ mid_str = rb_id2name(mid);
+ len = strlen(mid_str);
+ if (mid_str[len - 1] != ':') {
+ snprintf(buf, sizeof buf, "%s:", mid_str);
+ mid = rb_intern(buf);
+ }
+ }
+
+ method = rb_objc_method_node(klass, mid, &imp, &sel);
+
+ if (imp != NULL && method == NULL)
+ return rb_objc_call(recv, sel, argc, (VALUE *)argv);
+
+ DLOG("RCALL", "%c[<%s %p> %s] node=%p", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)sel, method);
+
+ if (method == NULL) {
+ int missing_scope = scope == 2 ? NOEX_VCALL : scope == 3 ? NOEX_SUPER : NOEX_VCALL;
+ return method_missing(recv, mid, argc, argv, missing_scope);
+ }
+ else {
+ noex = method->nd_noex;
+ klass = method->nd_clss;
+ body = method->nd_body;
+ }
+#else
/* is it in the method cache? */
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
if (!ent->method) {
- REDO_PERHAPS();
return method_missing(recv, mid, argc, argv,
scope == 2 ? NOEX_VCALL : 0);
}
@@ -238,15 +246,14 @@
body = method->nd_body;
}
else {
- REDO_PERHAPS();
if (scope == 3) {
return method_missing(recv, mid, argc, argv, NOEX_SUPER);
}
return method_missing(recv, mid, argc, argv,
scope == 2 ? NOEX_VCALL : 0);
}
+#endif
-
if (mid != missing) {
/* receiver specified form for private method */
if (UNLIKELY(noex)) {
@@ -1334,11 +1341,18 @@
rb_define_global_function("loop", rb_f_loop, 0);
+#if WITH_OBJC
+ rb_define_method(rb_cNSObject, "instance_eval", rb_obj_instance_eval, -1);
+ rb_define_method(rb_cNSObject, "instance_exec", rb_obj_instance_exec, -1);
+ rb_define_private_method(rb_cNSObject, "method_missing", rb_method_missing, -1);
+ rb_define_method(rb_cNSObject, "__send__", rb_f_send, -1);
+#else
rb_define_method(rb_cBasicObject, "instance_eval", rb_obj_instance_eval, -1);
rb_define_method(rb_cBasicObject, "instance_exec", rb_obj_instance_exec, -1);
rb_define_private_method(rb_cBasicObject, "method_missing", rb_method_missing, -1);
+ rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
+#endif
- rb_define_method(rb_cBasicObject, "__send__", rb_f_send, -1);
rb_define_method(rb_mKernel, "send", rb_f_send, -1);
rb_define_method(rb_mKernel, "public_send", rb_f_public_send, -1);
Modified: MacRuby/trunk/vm_insnhelper.c
===================================================================
--- MacRuby/trunk/vm_insnhelper.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_insnhelper.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -13,6 +13,10 @@
#include <math.h>
+#if WITH_OBJC
+# include <dlfcn.h>
+#endif
+
/* control stack frame */
@@ -371,13 +375,7 @@
reg_cfp->sp -= num + 1;
-#if WITH_OBJC
- rb_current_cfunc_node = (NODE *)mn;
-#endif
val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1);
-#if WITH_OBJC
- rb_current_cfunc_node = NULL;
-#endif
if (reg_cfp != th->cfp + 1) {
rb_bug("cfp consistency error - send");
@@ -485,15 +483,220 @@
}
}
+static inline void
+vm_send_optimize(rb_control_frame_t * const reg_cfp, NODE ** const mn,
+ rb_num_t * const flag, rb_num_t * const num,
+ ID * const id, const VALUE klass)
+{
+ if (*mn && nd_type((*mn)->nd_body) == NODE_CFUNC) {
+ NODE *node = (*mn)->nd_body;
+ extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
+
+ if (node->nd_cfnc == rb_f_send) {
+ int i = *num - 1;
+ VALUE sym = TOPN(i);
+ *id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
+
+ /* shift arguments */
+ if (i > 0) {
+ MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
+ }
+
+ *mn = rb_method_node(klass, *id);
+ *num -= 1;
+ DEC_SP(1);
+ *flag |= VM_CALL_FCALL_BIT;
+ }
+ }
+}
+
+bs_element_method_t * rb_bs_find_method(Class klass, SEL sel);
+VALUE rb_objc_call2(VALUE recv, VALUE klass, SEL sel, IMP imp, Method method, bs_element_method_t *bs_method, int argc, VALUE *argv);
+
static inline VALUE
vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
- const int num, rb_block_t * const blockptr, const VALUE flag,
- const ID id, const NODE * mn, const VALUE recv, VALUE klass)
+ /*const*/ int num, rb_block_t * const blockptr, const VALUE flag,
+ /*const*/ ID id, const VALUE recv, VALUE klass,
+ struct rb_method_cache *mcache)
{
VALUE val;
+#if WITH_OBJC
+ NODE *mn;
+#if ENABLE_DEBUG_LOGGING
+ bool cached = false;
+#endif
- start_method_dispatch:
+ mn = NULL;
+ if (mcache != NULL) {
+ if (mcache->flags & RB_MCACHE_RCALL_FLAG) {
+ if (mcache->as.rcall.klass == klass && mcache->as.rcall.node != NULL) {
+ mn = mcache->as.rcall.node;
+#if ENABLE_DEBUG_LOGGING
+ cached = true;
+#endif
+ goto rcall_dispatch;
+ }
+ else {
+ IMP imp;
+ char *p, *mname;
+
+ mn = rb_objc_method_node2(klass, mcache->as.rcall.sel, &imp);
+ if (mn == NULL) {
+ if (imp != NULL) {
+ mcache->flags = RB_MCACHE_OCALL_FLAG;
+ mcache->as.ocall.klass = klass;
+ mcache->as.ocall.imp = imp;
+ mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+ mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+ goto ocall_dispatch;
+ }
+
+ if ((mcache->flags & RB_MCACHE_NOT_CFUNC_FLAG) == 0) {
+ extern struct st_table *bs_functions;
+ bs_element_function_t *bs_func;
+
+ if (!st_lookup(bs_functions, (st_data_t)id, (st_data_t *)&bs_func)) {
+ mcache->flags |= RB_MCACHE_NOT_CFUNC_FLAG;
+ goto rcall_missing;
+ }
+
+ mcache->flags = RB_MCACHE_CFUNC_FLAG;
+ mcache->as.cfunc.bs_func = bs_func;
+ mcache->as.cfunc.sym = dlsym(RTLD_DEFAULT, bs_func->name);
+ if (mcache->as.cfunc.sym == NULL)
+ rb_bug("bs func sym '%s' is NULL", bs_func->name);
+ goto cfunc_dispatch;
+ }
+rcall_missing:
+ mname = (char *)mcache->as.rcall.sel;
+ if (num > 1
+ && (p = strchr(mname, ':')) != NULL
+ && p + 1 != '\0') {
+ char *tmp = alloca(p - mname + 1);
+ NODE *new_mn;
+
+ strncpy(tmp, mname, p - mname + 1);
+ tmp[p - mname + 1] = '\0';
+ new_mn = rb_objc_method_node2(klass, sel_registerName(tmp), &imp);
+ if (new_mn == NULL) {
+ goto rcall_dispatch;
+ }
+
+ VALUE *argv = cfp->sp - num;
+ VALUE h = rb_hash_new();
+ int i;
+
+ mname = p + 1;
+ for (i = 1; i < num; i++) {
+ char buf[100];
+
+ p = strchr(mname, ':');
+ if (p == NULL) {
+ goto rcall_dispatch;
+ }
+ strlcpy(buf, mname, sizeof buf);
+ buf[p - mname] = '\0';
+ mname = p + 1;
+ rb_hash_aset(h, ID2SYM(rb_intern(buf)), argv[i]);
+ }
+
+ VALUE new_argv[2];
+ new_argv[0] = argv[0];
+ new_argv[1] = h;
+
+ memcpy(cfp->sp - 2, new_argv, sizeof(void *) * 2);
+ cfp->bp -= 2 - num;
+ mn = new_mn;
+ id = rb_intern(tmp);
+ num = 2;
+ goto rcall_dispatch;
+ }
+ }
+ mcache->as.rcall.node = mn;
+ mcache->as.rcall.klass = klass;
+ }
+ }
+ else if (mcache->flags & RB_MCACHE_OCALL_FLAG) {
+ rb_control_frame_t *reg_cfp;
+ rb_control_frame_t *_cfp;
+
+ocall_dispatch:
+ reg_cfp = cfp;
+ _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+ recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
+
+ _cfp->method_id = id;
+ _cfp->method_class = klass;
+
+ reg_cfp->sp -= num + 1;
+
+
+ val = rb_objc_call2(recv, klass, mcache->as.rcall.sel, mcache->as.ocall.imp, mcache->as.ocall.method, mcache->as.ocall.bs_method, num, reg_cfp->sp + 1);
+
+ if (reg_cfp != th->cfp + 1)
+ rb_bug("cfp consistency error - send");
+
+ vm_pop_frame(th);
+
+ return val;
+ }
+ else if (mcache->flags & RB_MCACHE_CFUNC_FLAG) {
+ rb_control_frame_t *reg_cfp;
+ rb_control_frame_t *_cfp;
+
+cfunc_dispatch:
+ reg_cfp = cfp;
+ _cfp = vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+ recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
+
+ _cfp->method_id = id;
+ _cfp->method_class = klass;
+
+ reg_cfp->sp -= num + 1;
+
+ VALUE rb_bsfunc_call(bs_element_function_t *bs_func, void *sym, int argc, VALUE *argv);
+
+ val = rb_bsfunc_call(mcache->as.cfunc.bs_func, mcache->as.cfunc.sym, num, reg_cfp->sp + 1);
+
+ if (reg_cfp != th->cfp + 1)
+ rb_bug("cfp consistency error - send");
+
+ vm_pop_frame(th);
+
+ return val;
+ }
+ else {
+ rb_bug("invalid cache flag");
+ }
+ }
+ else {
+ SEL sel;
+ IMP imp;
+ mn = rb_objc_method_node(klass, id, &imp, &sel);
+ if (mn == NULL && imp != NULL) {
+ static struct rb_method_cache mcache_s;
+ mcache = &mcache_s;
+ mcache->as.ocall.sel = sel;
+ mcache->as.ocall.klass = klass;
+ mcache->as.ocall.imp = imp;
+ mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+ mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+ goto ocall_dispatch;
+ }
+ }
+
+rcall_dispatch:
+
+ if (flag & VM_CALL_SEND_BIT) {
+ vm_send_optimize(cfp, (NODE **)&mn, (rb_num_t *)&flag, (rb_num_t *)&num, (ID *)&id, klass);
+ }
+
+ DLOG("RCALL", "%c[<%s %p> %s] node=%p cached=%d", class_isMetaClass((Class)klass) ? '+' : '-', class_getName((Class)klass), (void *)recv, (char *)rb_id2name(id), mn, cached);
+#endif
+
+start_method_dispatch:
+
if (mn != 0) {
if ((mn->nd_noex == 0)) {
/* dispatch method */
@@ -588,19 +791,69 @@
}
}
else {
+#if WITH_OBJC
+ if (flag & VM_CALL_SUPER_BIT) {
+ VALUE k;
+ for (k = CLASS_OF(recv); k != 0; k = RCLASS_SUPER(k)) {
+ VALUE ary = rb_attr_get(k, idIncludedModules);
+ if (ary != Qnil) {
+ int i, count = RARRAY_LEN(ary);
+ for (i = 0; i < count; i++) {
+ VALUE imod = RARRAY_AT(ary, i);
+ mn = rb_objc_method_node(imod, id, NULL, NULL);
+ if (mn != NULL) {
+ goto start_method_dispatch;
+ }
+ }
+ }
+ }
+ }
+ else if (mcache != NULL) {
+ const char *p = (const char *)mcache->as.rcall.sel;
+ size_t len = strlen(p);
+ if (len >= 3) {
+ char buf[100];
+ SEL sel = 0;
+ if (isalpha(p[len - 3]) && p[len - 2] == '=' && p[len - 1] == ':') {
+ /* foo=: -> setFoo: shortcut */
+ snprintf(buf, sizeof buf, "set%s", p);
+ buf[3] = toupper(buf[3]);
+ buf[len + 1] = ':';
+ buf[len + 2] = '\0';
+ sel = sel_registerName(buf);
+ }
+ else if (isalpha(p[len - 2]) && p[len - 1] == '?') {
+ /* foo?: -> isFoo: shortcut */
+ snprintf(buf, sizeof buf, "is%s", p);
+ buf[2] = toupper(buf[2]);
+ buf[len + 1] = '\0';
+ sel = sel_registerName(buf);
+ }
+ if (sel != 0) {
+ Method method = class_getInstanceMethod((Class)klass, sel);
+ if (method != NULL) {
+ IMP imp = method_getImplementation(method);
+ if (rb_objc_method_node3(imp) == NULL) {
+ assert(class_addMethod((Class)klass, mcache->as.rcall.sel, imp,
+ method_getTypeEncoding(method)));
+ mcache->flags = RB_MCACHE_OCALL_FLAG;
+ mcache->as.ocall.klass = klass;
+ mcache->as.ocall.imp = imp;
+ mcache->as.ocall.method = class_getInstanceMethod((Class)klass, mcache->as.rcall.sel);
+ mcache->as.ocall.bs_method = rb_bs_find_method((Class)klass, mcache->as.rcall.sel);
+ goto ocall_dispatch;
+ }
+ }
+ }
+ }
+ }
+#endif
/* method missing */
if (id == idMethodMissing) {
rb_bug("method missing");
}
else {
int stat = 0;
-#if WITH_OBJC
- mn = rb_objc_define_objc_mid_closure(recv, id, 0);
- if (mn != NULL) {
- return vm_call_method(th, cfp, num, blockptr, flag, id,
- mn, recv, klass);
- }
-#endif
if (flag & VM_CALL_VCALL_BIT) {
stat |= NOEX_VCALL;
}
@@ -615,33 +868,6 @@
return val;
}
-static inline void
-vm_send_optimize(rb_control_frame_t * const reg_cfp, NODE ** const mn,
- rb_num_t * const flag, rb_num_t * const num,
- ID * const id, const VALUE klass)
-{
- if (*mn && nd_type((*mn)->nd_body) == NODE_CFUNC) {
- NODE *node = (*mn)->nd_body;
- extern VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
-
- if (node->nd_cfnc == rb_f_send) {
- int i = *num - 1;
- VALUE sym = TOPN(i);
- *id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
-
- /* shift arguments */
- if (i > 0) {
- MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
- }
-
- *mn = rb_method_node(klass, *id);
- *num -= 1;
- DEC_SP(1);
- *flag |= VM_CALL_FCALL_BIT;
- }
- }
-}
-
/* yield */
static inline int
@@ -997,6 +1223,9 @@
VALUE orig_klass, ID id, int is_defined)
{
VALUE val;
+#if WITH_OBJC
+ CFDictionaryRef iv_dict;
+#endif
if (orig_klass == Qnil) {
/* in current lexical scope */
@@ -1010,8 +1239,13 @@
if (!NIL_P(klass)) {
search_continue:
+#if WITH_OBJC
+ iv_dict = (CFDictionaryRef)rb_class_ivar_dict(klass);
+ if (iv_dict != NULL && CFDictionaryGetValueIfPresent(iv_dict, (const void *)id, (const void **)&val)) {
+#else
if (RCLASS_IV_TBL(klass) &&
st_lookup(RCLASS_IV_TBL(klass), id, &val)) {
+#endif
if (val == Qundef) {
rb_autoload_load(klass, id);
goto search_continue;
@@ -1057,7 +1291,7 @@
{
VALUE klass;
- while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
+ while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || RCLASS_SINGLETON(cref->nd_clss))) {
cref = cref->nd_next;
if (!cref->nd_next) {
@@ -1114,66 +1348,6 @@
INC_VM_STATE_VERSION();
}
-#if WITH_OBJC
-static inline void
-vm_method_process_named_args(ID *pid, NODE **pmn, VALUE recv, rb_num_t *pnum,
- rb_control_frame_t *cfp)
-{
- VALUE *argv = cfp->sp - *pnum;
- NODE *mn;
- ID id;
-
- if (*pmn == NULL) {
- const char *p, *mname;
- long i;
- mn = rb_objc_define_objc_mid_closure(recv, *pid, 0);
- if (mn != NULL) {
- *pmn = mn;
- return;
- }
- mname = rb_id2name(*pid);
- if (*pid > 1 && (p = strchr(mname, ':')) != NULL) {
- char buf[512];
- strlcpy(buf, mname, sizeof buf);
- buf[p - mname] = '\0';
- mname = p + 1;
- id = rb_intern(buf);
- mn = rb_method_node(CLASS_OF(recv), id);
- if (mn != NULL) {
- VALUE h = rb_hash_new();
- VALUE new_argv[2];
- for (i = 1; i < *pnum; i++) {
- p = strchr(mname, ':');
- if (p == NULL)
- return;
- strlcpy(buf, mname, sizeof buf);
- buf[p - mname] = '\0';
- mname = p + 1;
- rb_hash_aset(h, ID2SYM(rb_intern(buf)), argv[i]);
- }
- new_argv[0] = argv[0];
- new_argv[1] = h;
- memcpy(cfp->sp - 2, new_argv, sizeof(void *) * 2);
- cfp->bp -= 2 - *pnum;
- *pmn = mn;
- *pid = id;
- *pnum = 2;
- return;
- }
- }
- id = rb_objc_missing_sel(*pid, *pnum);
- if (id != *pid) {
- mn = rb_objc_define_objc_mid_closure(recv, id, *pid);
- if (mn != NULL) {
- *pmn = mn;
- *pid = id;
- return;
- }
- }
- }
-}
-#endif
-
static inline NODE *
vm_method_search(VALUE id, VALUE klass, IC ic)
{
@@ -1201,13 +1375,13 @@
static inline VALUE
vm_search_normal_superclass(VALUE klass, VALUE recv)
{
- if (BUILTIN_TYPE(klass) == T_CLASS) {
+ if (TYPE(klass) == T_CLASS) {
klass = RCLASS_SUPER(klass);
}
- else if (BUILTIN_TYPE(klass) == T_MODULE) {
+ else if (TYPE(klass) == T_MODULE) {
VALUE k = CLASS_OF(recv);
while (k) {
- if (BUILTIN_TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) {
+ if (TYPE(k) == T_ICLASS && RBASIC(k)->klass == klass) {
klass = RCLASS_SUPER(k);
break;
}
@@ -1217,10 +1391,41 @@
return klass;
}
+#if WITH_OBJC
+static VALUE previous_sklass = Qnil;
+static inline VALUE
+vm_search_normal_superclass2(VALUE klass, VALUE recv, ID mid, NODE **mnp, IMP *impp, SEL *selp)
+{
+ VALUE ary = rb_attr_get(klass, idIncludedModules);
+ if (ary != Qnil) {
+ int i, count = RARRAY_LEN(ary);
+ for (i = 0; i < count; i++) {
+ VALUE imod = RARRAY_AT(ary, i);
+ NODE *mn;
+ IMP imp;
+ SEL sel;
+ mn = rb_objc_method_node(imod, mid, &imp, &sel);
+ if (imp != NULL) {
+ previous_sklass = klass;
+ *mnp = mn;
+ *impp = imp;
+ *selp = sel;
+ return imod;
+ }
+ }
+ }
+ if (previous_sklass != Qnil) {
+ klass = previous_sklass;
+ previous_sklass = Qnil;
+ }
+ return vm_search_normal_superclass(klass, recv);
+}
+#endif
+
static void
vm_search_superclass(rb_control_frame_t *reg_cfp, rb_iseq_t *ip,
VALUE recv, VALUE sigval,
- ID *idp, VALUE *klassp)
+ ID *idp, VALUE *klassp, NODE **mnp, IMP *impp, SEL *selp)
{
ID id;
VALUE klass;
@@ -1250,7 +1455,7 @@
}
id = lcfp->method_id;
- klass = vm_search_normal_superclass(lcfp->method_class, recv);
+ klass = vm_search_normal_superclass2(lcfp->method_class, recv, id, mnp, impp, selp);
if (sigval == Qfalse) {
/* zsuper */
@@ -1258,7 +1463,7 @@
}
}
else {
- klass = vm_search_normal_superclass(ip->klass, recv);
+ klass = vm_search_normal_superclass2(ip->klass, recv, id, mnp, impp, selp);
}
*idp = id;
Modified: MacRuby/trunk/vm_method.c
===================================================================
--- MacRuby/trunk/vm_method.c 2008-08-21 04:57:31 UTC (rev 458)
+++ MacRuby/trunk/vm_method.c 2008-08-21 06:13:14 UTC (rev 459)
@@ -62,6 +62,7 @@
}
}
+#if !WITH_OBJC
static void
rb_clear_cache_by_id(ID id)
{
@@ -80,6 +81,7 @@
ent++;
}
}
+#endif
void
rb_clear_cache_by_class(VALUE klass)
@@ -100,18 +102,7 @@
}
}
-#if WITH_OBJC
-void rb_objc_sync_ruby_method(VALUE, ID, NODE*, unsigned);
-#endif
-
void
-rb_add_method_direct(VALUE klass, ID mid, NODE *node)
-{
- rb_clear_cache_by_id(mid);
- st_insert(RCLASS_M_TBL(klass), (st_data_t)mid, (st_data_t)node);
-}
-
-void
rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
{
NODE *body;
@@ -122,12 +113,12 @@
if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
rb_raise(rb_eSecurityError, "Insecure: can't define method");
}
- if (!FL_TEST(klass, FL_SINGLETON) &&
+ if (!RCLASS_SINGLETON(klass) &&
node && nd_type(node) != NODE_ZSUPER &&
(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
noex = NOEX_PRIVATE | noex;
}
- else if (FL_TEST(klass, FL_SINGLETON) && node
+ else if (RCLASS_SINGLETON(klass) && node
&& nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
rb_warn
("defining %s.allocate is deprecated; use rb_define_alloc_func()",
@@ -137,7 +128,9 @@
if (OBJ_FROZEN(klass)) {
rb_error_frozen("class/module");
}
+#if !WITH_OBJC
rb_clear_cache_by_id(mid);
+#endif
/*
* NODE_METHOD (NEW_METHOD(body, klass, vis)):
@@ -157,6 +150,7 @@
body = 0;
}
+#if !WITH_OBJC // TODO
{
/* check re-definition */
st_data_t data;
@@ -184,18 +178,16 @@
}
}
}
+#endif
+#if WITH_OBJC
+ rb_objc_register_ruby_method(klass, mid, body != NULL ? body->nd_body : NULL);
+#else
st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);
-
-#if WITH_OBJC
- if (node != NULL && noex == NOEX_PUBLIC) {
- unsigned override = !FL_TEST(klass, FL_SINGLETON);
- rb_objc_sync_ruby_method(klass, mid, node, override);
- }
#endif
if (node && mid != ID_ALLOCATOR && ruby_running) {
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
ID2SYM(mid));
}
@@ -210,7 +202,7 @@
{
Check_Type(klass, T_CLASS);
rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0),
- NOEX_PRIVATE);
+ NOEX_PUBLIC);
}
void
@@ -236,6 +228,17 @@
static NODE *
search_method(VALUE klass, ID id, VALUE *klassp)
{
+#if WITH_OBJC
+ NODE *node;
+ if (klass == 0)
+ return NULL;
+ node = rb_method_node(klass, id);
+ if (node != NULL) {
+ if (klassp != NULL) /* TODO honour klassp */
+ *klassp = klass;
+ }
+ return node;
+#else
st_data_t body;
if (!klass) {
@@ -253,6 +256,7 @@
}
return (NODE *)body;
+#endif
}
/*
@@ -266,6 +270,9 @@
NODE *
rb_get_method_body(VALUE klass, ID id, ID *idp)
{
+#if WITH_OBJC
+ return search_method(klass, id, NULL);
+#else
NODE *volatile fbody, *body;
NODE *method;
@@ -301,11 +308,38 @@
}
return body;
+#endif
}
NODE *
rb_method_node(VALUE klass, ID id)
{
+#if WITH_OBJC
+ NODE *node = rb_objc_method_node(klass, id, NULL, NULL);
+ if (node == NULL && id != ID_ALLOCATOR) {
+ const char *id_str = rb_id2name(id);
+ size_t slen = strlen(id_str);
+
+ if (strcmp(id_str, "retain") == 0
+ || strcmp(id_str, "release") == 0
+ || strcmp(id_str, "zone") == 0) {
+ char buf[100];
+ snprintf(buf, sizeof buf, "__rb_%s__", id_str);
+ return rb_method_node(klass, rb_intern(buf));
+ }
+ else {
+ if (id_str[slen - 1] == ':') {
+ return NULL;
+ }
+ else {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%s:", id_str);
+ return rb_method_node(klass, rb_intern(buf));
+ }
+ }
+ }
+ return node;
+#else
struct cache_entry *ent;
ent = cache + EXPR1(klass, id);
@@ -314,12 +348,15 @@
}
return rb_get_method_body(klass, id, 0);
+#endif
}
static void
remove_method(VALUE klass, ID mid)
{
+#if !WITH_OBJC
st_data_t data;
+#endif
NODE *body = 0;
if (klass == rb_cObject) {
@@ -333,6 +370,9 @@
if (mid == object_id || mid == __send__ || mid == idInitialize) {
rb_warn("removing `%s' may cause serious problem", rb_id2name(mid));
}
+#if WITH_OBJC
+ // TODO
+#else
if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
body = (NODE *)data;
if (!body || !body->nd_body) body = 0;
@@ -340,6 +380,7 @@
st_delete(RCLASS_M_TBL(klass), &mid, &data);
}
}
+#endif
if (!body) {
rb_name_error(mid, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass));
@@ -350,7 +391,7 @@
}
rb_clear_cache_for_undef(klass, mid);
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"), singleton_removed, 1,
ID2SYM(mid));
}
@@ -408,6 +449,32 @@
if (klass == rb_cObject) {
rb_secure(4);
}
+#if WITH_OBJC
+ fbody = rb_method_node(klass, name);
+ if (fbody == NULL && TYPE(klass) == T_MODULE) {
+ fbody = rb_method_node(rb_cObject, name);
+ origin = rb_method_node(rb_cObject, name) == fbody
+ ? rb_cObject : klass;
+ }
+ else {
+ origin = rb_method_node(RCLASS_SUPER(klass), name) == fbody
+ ? RCLASS_SUPER(klass) : klass;
+ }
+ if (fbody == NULL) {
+ rb_print_undef(klass, name, 0);
+ }
+ if (fbody->nd_noex != noex) {
+ if (nd_type(fbody->nd_body) == NODE_CFUNC) {
+ rb_vm_check_redefinition_opt_method(fbody);
+ }
+ if (klass == origin) {
+ fbody->nd_noex = noex;
+ }
+ else {
+ rb_add_method(klass, name, NEW_ZSUPER(), noex);
+ }
+ }
+#else
fbody = search_method(klass, name, &origin);
if (!fbody && TYPE(klass) == T_MODULE) {
fbody = search_method(rb_cObject, name, &origin);
@@ -426,6 +493,7 @@
rb_add_method(klass, name, NEW_ZSUPER(), noex);
}
}
+#endif
}
int
@@ -500,21 +568,15 @@
if (id == object_id || id == __send__ || id == idInitialize) {
rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
}
-#if WITH_OBJC
- /* TODO: we should only warn regarding important NSObject methods that
- are necessary by the GC to call finalizers. */
- if (class_respondsToSelector(RCLASS_OCID(rb_cBasicObject),
- sel_registerName(rb_id2name(id)))) {
- rb_warn("undefining `NSObject#%s' may cause serious problem",
- rb_id2name(id));
- }
-#endif
+ /* TODO: warn if a very important method of NSObject is undefined
+ * by default, pure objc methods are not exposed by introspections API
+ */
body = search_method(klass, id, &origin);
if (!body || !body->nd_body) {
const char *s0 = " class";
VALUE c = klass;
- if (FL_TEST(c, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(c)) {
VALUE obj = rb_iv_get(klass, "__attached__");
switch (TYPE(obj)) {
@@ -527,27 +589,13 @@
else if (TYPE(c) == T_MODULE) {
s0 = " module";
}
-#if WITH_OBJC
- if (!class_respondsToSelector(RCLASS(klass)->ocklass,
- sel_registerName(rb_id2name(id))))
-#endif
rb_name_error(id, "undefined method `%s' for%s `%s'",
rb_id2name(id), s0, rb_class2name(c));
}
rb_add_method(klass, id, 0, NOEX_PUBLIC);
-#if WITH_OBJC
- {
- Method method;
- method = class_getInstanceMethod(RCLASS(klass)->ocklass,
- sel_registerName(rb_id2name(id)));
- if (method != NULL)
- method_setImplementation(method, NULL);
- }
-#endif
-
- if (FL_TEST(klass, FL_SINGLETON)) {
+ if (RCLASS_SINGLETON(klass)) {
rb_funcall(rb_iv_get(klass, "__attached__"),
singleton_undefined, 1, ID2SYM(id));
}
@@ -766,14 +814,22 @@
void
rb_alias(VALUE klass, ID name, ID def)
{
+#if !WITH_OBJC
NODE *orig_fbody, *node;
+ st_data_t data;
+#endif
VALUE singleton = 0;
- st_data_t data;
rb_frozen_class_p(klass);
if (klass == rb_cObject) {
rb_secure(4);
}
+#if WITH_OBJC
+ if (RCLASS_SINGLETON(klass)) {
+ singleton = rb_iv_get(klass, "__attached__");
+ }
+ rb_objc_alias(klass, name, def);
+#else
orig_fbody = search_method(klass, def, 0);
if (!orig_fbody || !orig_fbody->nd_body) {
if (TYPE(klass) == T_MODULE) {
@@ -807,13 +863,9 @@
orig_fbody->nd_body->nd_clss,
NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
-#if WITH_OBJC
- if (orig_fbody->nd_body->nd_noex == NOEX_PUBLIC)
- rb_objc_sync_ruby_method(klass, name, orig_fbody->nd_body->nd_body, 0);
+ rb_clear_cache_by_id(name);
#endif
- rb_clear_cache_by_id(name);
-
if (!ruby_running) return;
if (singleton) {
@@ -1074,18 +1126,32 @@
if (fbody == 0) {
fbody = search_method(rb_cObject, id, &m);
}
+#if WITH_OBJC
+ if (fbody == 0) {
+ rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+ }
+ if (nd_type(fbody->nd_body) != NODE_ZSUPER) {
+ break; /* normal case: need not to follow 'super' link */
+ }
+#else
if (fbody == 0 || fbody->nd_body == 0) {
rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
}
if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
break; /* normal case: need not to follow 'super' link */
}
+#endif
m = RCLASS_SUPER(m);
if (!m)
break;
}
+#if WITH_OBJC
+ rb_add_method(rb_singleton_class(module), id, fbody->nd_body,
+ NOEX_PUBLIC);
+#else
rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body,
NOEX_PUBLIC);
+#endif
}
return module;
}
@@ -1104,6 +1170,10 @@
int
rb_obj_respond_to(VALUE obj, ID id, int priv)
{
+#if WITH_OBJC
+ SEL sel = sel_registerName(rb_id2name(id));
+ return class_respondsToSelector((Class)CLASS_OF(obj), sel);
+#else
VALUE klass = CLASS_OF(obj);
if (rb_method_node(klass, idRespond_to) == basic_respond_to) {
@@ -1117,6 +1187,7 @@
args[n++] = Qtrue;
return RTEST(rb_funcall2(obj, idRespond_to, n, args));
}
+#endif
}
int
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080820/c9bc4dd4/attachment-0001.html
More information about the macruby-changes
mailing list