From cc2788364dd9c6a14d94646f09222f4721740a15 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 28 Sep 2012 15:22:53 -0500 Subject: [PATCH] Attempt to make kross compile with Ruby 1.9.x --- lib/kross/configure.in.in | 52 +++++++---- lib/kross/ruby/Makefile.am | 2 +- lib/kross/ruby/rubyextension.cpp | 18 +++- lib/kross/ruby/rubyinterpreter.cpp | 10 ++ lib/kross/ruby/rubyinterpreter.h | 9 ++ lib/kross/ruby/rubyscript.cpp | 141 ++++++++++++++++++++++------- 6 files changed, 177 insertions(+), 55 deletions(-) diff --git a/lib/kross/configure.in.in b/lib/kross/configure.in.in index 47c2d2d3..c679be43 100644 --- a/lib/kross/configure.in.in +++ b/lib/kross/configure.in.in @@ -1,3 +1,7 @@ +KDE_FIND_PATH(pkg-config, PKGCONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/bin /usr/local/bin /opt/local/bin], [ + AC_MSG_WARN([Could not find pkg-config]) +]) + AC_ARG_ENABLE(scripting, AC_HELP_STRING([--enable-scripting], [build scripting library (Kross) [default=yes]]), @@ -25,13 +29,33 @@ if test "x$compile_kross" = "xyes" ; then if test -n "$RUBY"; then AC_MSG_CHECKING(for Ruby dirs) - RUBY_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'` - RUBY_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'` - RUBY_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'` - RUBY_INCLUDEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"rubyincludedir"@:>@)'` - RUBY_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'` - RUBY_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'` - RUBY_ENABLESHARED=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"ENABLE_SHARED"@:>@)'` + if test -n "$PKGCONFIG"; then + RUBY_VERSION=`$PKGCONFIG ruby --modversion 2>/dev/null` + if test -n "$RUBY_VERSION"; then + RUBY_CFLAGS=`$PKGCONFIG ruby --cflags` + else + RUBY_VERSION=`$PKGCONFIG ruby-1.9 --modversion 2>/dev/null` + RUBY_CFLAGS=`$PKGCONFIG ruby-1.9 --cflags` + fi + if test -n "$RUBY_VERSION"; then + RUBY_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG@<:@"archdir"@:>@)'` + RUBY_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG@<:@"sitearchdir"@:>@)'` + RUBY_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG@<:@"sitelibdir"@:>@)'` + RUBY_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG@<:@"libdir"@:>@)'` + RUBY_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'` + RUBY_ENABLESHARED=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"ENABLE_SHARED"@:>@)'` + AC_DEFINE_UNQUOTED(HAVE_RUBY_1_9, 1, [Defines if your system has Ruby 1.9.x]) + fi + fi + if test -z "$RUBY_VERSION"; then + RUBY_ARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"archdir"@:>@)'` + RUBY_SITEARCHDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitearchdir"@:>@)'` + RUBY_SITEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"sitelibdir"@:>@)'` + RUBY_INCLUDEDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"rubyincludedir"@:>@)'` + RUBY_LIBDIR=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"libdir"@:>@)'` + RUBY_LIBRUBYARG=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"LIBRUBYARG_SHARED"@:>@)'` + RUBY_ENABLESHARED=`$RUBY -r rbconfig -e 'printf("%s",Config::CONFIG@<:@"ENABLE_SHARED"@:>@)'` + fi AC_MSG_RESULT([ archdir $RUBY_ARCHDIR, sitearchdir $RUBY_SITEARCHDIR, @@ -47,6 +71,7 @@ if test "x$compile_kross" = "xyes" ; then AC_SUBST(RUBY_LIBDIR) AC_SUBST(RUBY_LIBRUBYARG) AC_SUBST(RUBY_ENABLESHARED) + AC_SUBST(RUBY_CFLAGS) AC_MSG_CHECKING(for Ruby header) @@ -55,10 +80,6 @@ if test "x$compile_kross" = "xyes" ; then RUBY_INCLUDEDIR=$RUBY_ARCHDIR fi - if test ! -r $RUBY_INCLUDEDIR/ruby.h; then - RUBY_LIBDIR="" - AC_MSG_RESULT([not found]) - else AC_MSG_RESULT([found]) # header AC_MSG_CHECKING(Ruby shared library) @@ -76,18 +97,12 @@ if test "x$compile_kross" = "xyes" ; then AC_LANG_SAVE AC_LANG_CPLUSPLUS ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS -I$RUBY_INCLUDEDIR" + CXXFLAGS="$CXXFLAGS -I$RUBY_INCLUDEDIR $RUBY_CFLAGS" AC_CACHE_VAL(ruby_build, [ AC_TRY_COMPILE([ #include - #include ],[ - -#if(RUBY_VERSION_MAJOR==1 && RUBY_VERSION_MINOR == 8 && RUBY_VERSION_TEENY <= 1) -#error "need at least ruby 1.8.2\n" -#endif - ruby_init(); return 0; ], ruby_build=yes, @@ -101,7 +116,6 @@ if test "x$compile_kross" = "xyes" ; then AC_LANG_RESTORE fi # have ruby shared lib argument fi # have shared lib - fi # have ruby header fi # have ruby fi # compiling kross diff --git a/lib/kross/ruby/Makefile.am b/lib/kross/ruby/Makefile.am index 1a06e7a4..f8bc012a 100644 --- a/lib/kross/ruby/Makefile.am +++ b/lib/kross/ruby/Makefile.am @@ -1,6 +1,6 @@ include $(top_srcdir)/lib/kross/Makefile.global -INCLUDES = -I$(top_srcdir)/lib/kross -I$(RUBY_INCLUDEDIR) $(all_includes) +INCLUDES = -I$(top_srcdir)/lib/kross -I$(RUBY_INCLUDEDIR) $(RUBY_CFLAGS) $(all_includes) METASOURCES = AUTO kde_module_LTLIBRARIES = krossruby.la diff --git a/lib/kross/ruby/rubyextension.cpp b/lib/kross/ruby/rubyextension.cpp index 98474bf6..89c73b1a 100644 --- a/lib/kross/ruby/rubyextension.cpp +++ b/lib/kross/ruby/rubyextension.cpp @@ -17,8 +17,18 @@ * Boston, MA 02110-1301, USA. ***************************************************************************/ #include "rubyextension.h" +#include "rubyinterpreter.h" +#define HAVE_STRLCAT_PROTO 1 +#define HAVE_STRLCPY_PROTO 1 +#include "config.h" + +#ifndef HAVE_RUBY_1_9 #include +#else // HAVE_RUBY_1_9 +#include +#define STR2CSTR(x) StringValuePtr(x) +#endif // HAVE_RUBY_1_9 #include #include @@ -174,7 +184,7 @@ VALUE RubyExtension::convertFromException(Kross::Api::Exception::Ptr exc) { if(RubyExtensionPrivate::s_krossException == 0) { - RubyExtensionPrivate::s_krossException = rb_define_class("KrossException", rb_eRuntimeError); + RubyExtensionPrivate::s_krossException = rb_define_class_under(RubyInterpreter::krossModule(), "KrossException", rb_eRuntimeError); } exc->_KShared_ref(); return Data_Wrap_Struct(RubyExtensionPrivate::s_krossException, 0, RubyExtension::delete_exception, exc.data() ); @@ -211,7 +221,11 @@ Kross::Api::Object::Ptr RubyExtension::toObject(VALUE value) case T_ARRAY: { TQValueList l; +#ifdef HAVE_RUBY_1_9 + for(int i = 0; i < RARRAY_LEN(value); i++) +#else // HAVE_RUBY_1_9 for(int i = 0; i < RARRAY(value)->len; i++) +#endif // HAVE_RUBY_1_9 { Kross::Api::Object::Ptr o = toObject( rb_ary_entry( value , i ) ); if(o) l.append(o); @@ -357,7 +371,7 @@ VALUE RubyExtension::toVALUE(Kross::Api::Object::Ptr object) if(RubyExtensionPrivate::s_krossObject == 0) { - RubyExtensionPrivate::s_krossObject = rb_define_class("KrossObject", rb_cObject); + RubyExtensionPrivate::s_krossObject = rb_define_class_under(RubyInterpreter::krossModule(), "Object", rb_cObject ); rb_define_method(RubyExtensionPrivate::s_krossObject, "method_missing", (VALUE (*)(...))RubyExtension::method_missing, -1); } return Data_Wrap_Struct(RubyExtensionPrivate::s_krossObject, 0, RubyExtension::delete_object, new RubyExtension(object) ); diff --git a/lib/kross/ruby/rubyinterpreter.cpp b/lib/kross/ruby/rubyinterpreter.cpp index 6af8ecbe..e2c4022a 100644 --- a/lib/kross/ruby/rubyinterpreter.cpp +++ b/lib/kross/ruby/rubyinterpreter.cpp @@ -66,6 +66,7 @@ typedef mStrVALUE::iterator mStrVALUE_it; typedef mStrVALUE::const_iterator mStrVALUE_cit; class RubyInterpreterPrivate { friend class RubyInterpreter; + static VALUE s_krossModule; }; RubyInterpreterPrivate* RubyInterpreter::d = 0; @@ -107,6 +108,15 @@ void RubyInterpreter::initRuby() rb_define_global_function("require", (VALUE (*)(...))RubyInterpreter::require, 1); } +VALUE RubyInterpreter::krossModule() +{ + if(RubyInterpreterPrivate::s_krossModule == 0) + { + RubyInterpreterPrivate::s_krossModule = rb_define_module("Kross"); + } + return RubyInterpreterPrivate::s_krossModule; +} + void RubyInterpreter::finalizeRuby() { delete d; diff --git a/lib/kross/ruby/rubyinterpreter.h b/lib/kross/ruby/rubyinterpreter.h index f16f2b3d..0c7eb5fc 100644 --- a/lib/kross/ruby/rubyinterpreter.h +++ b/lib/kross/ruby/rubyinterpreter.h @@ -61,6 +61,15 @@ class RubyInterpreter : public Kross::Api::Interpreter void finalizeRuby(); /// Load an external plugin / module. static VALUE require (VALUE, VALUE); + + public: + /** + * @return the ruby object with the module Kross, this module holds class + * definition used by kross, and scripts object. All kross specific objects + * should be member of that module. + */ + static VALUE krossModule(); + private: /// Private d-pointer. static RubyInterpreterPrivate* d; diff --git a/lib/kross/ruby/rubyscript.cpp b/lib/kross/ruby/rubyscript.cpp index 370d4aa7..106164c4 100644 --- a/lib/kross/ruby/rubyscript.cpp +++ b/lib/kross/ruby/rubyscript.cpp @@ -18,11 +18,22 @@ ***************************************************************************/ #include "rubyscript.h" +#include "rubyvariant.h" + +#define HAVE_STRLCAT_PROTO 1 +#define HAVE_STRLCPY_PROTO 1 +#include "config.h" #include + +#ifndef HAVE_RUBY_1_9 #include #include #include +#else // HAVE_RUBY_1_9 +#include +#define STR2CSTR(x) StringValuePtr(x) +#endif // HAVE_RUBY_1_9 #include
@@ -30,23 +41,44 @@ #include "rubyextension.h" #include "rubyinterpreter.h" -extern NODE *ruby_eval_tree; - namespace Kross { namespace Ruby { +namespace Internals { + namespace Script { + static VALUE method_added(VALUE self, VALUE unit) + { + rb_funcall(self, rb_intern("module_function"), unit); + return self; + } + }; +}; + class RubyScriptPrivate { friend class RubyScript; - RubyScriptPrivate() : m_compile(0) { } - RNode* m_compile; + + RubyScriptPrivate() : m_script(0), m_hasBeenCompiled(false) + { + if(RubyScriptPrivate::s_krossScript == 0) + { + RubyScriptPrivate::s_krossScript = rb_define_class_under(RubyInterpreter::krossModule(), "Script", rb_cModule); + rb_define_method(RubyScriptPrivate::s_krossScript, "method_added", (VALUE (*)(...))Internals::Script::method_added, 1); + } + } + VALUE m_script; + static VALUE s_krossScript; + bool m_hasBeenCompiled; + /// A list of functionnames. TQStringList m_functions; /// A list of classnames. TQStringList m_classes; }; - + +VALUE RubyScriptPrivate::s_krossScript = 0; + RubyScript::RubyScript(Kross::Api::Interpreter* interpreter, Kross::Api::ScriptContainer* scriptcontainer) : Kross::Api::Script(interpreter, scriptcontainer), d(new RubyScriptPrivate()) { @@ -57,13 +89,6 @@ RubyScript::~RubyScript() { } -#define selectScript() \ - NODE* old_tree = ruby_eval_tree; \ - ruby_eval_tree = d->m_compile; -#define unselectScript() \ - d->m_compile = 0; \ - ruby_eval_tree = old_tree; - void RubyScript::compile() { #ifdef KROSS_RUBY_SCRIPT_DEBUG @@ -71,24 +96,41 @@ void RubyScript::compile() #endif int critical; +#ifdef HAVE_RUBY_1_9 + // FIXME + int ruby_nerrs = 0; + int ruby_errinfo = Qnil; +#else // HAVE_RUBY_1_9 ruby_nerrs = 0; ruby_errinfo = Qnil; +#endif // HAVE_RUBY_1_9 VALUE src = RubyExtension::toVALUE( m_scriptcontainer->getCode() ); StringValue(src); + +#ifdef HAVE_RUBY_1_9 + // FIXME +#else // HAVE_RUBY_1_9 critical = rb_thread_critical; rb_thread_critical = Qtrue; ruby_in_eval++; - d->m_compile = rb_compile_string((char*) m_scriptcontainer->getName().latin1(), src, 0); +#endif // HAVE_RUBY_1_9 + rb_funcall(d->m_script, rb_intern("module_eval"), 2, src, (char*) m_scriptcontainer->getName().latin1()); +#ifdef HAVE_RUBY_1_9 + // FIXME +#else // HAVE_RUBY_1_9 ruby_in_eval--; rb_thread_critical = critical; +#endif // HAVE_RUBY_1_9 if (ruby_nerrs != 0) { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Compilation has failed"); #endif - setException( new Kross::Api::Exception(TQString("Failed to compile ruby code: %1").arg(STR2CSTR( rb_obj_as_string(ruby_errinfo) )), 0) ); // TODO: get the error - d->m_compile = 0; + VALUE errorstring = rb_obj_as_string(ruby_errinfo); + setException( new Kross::Api::Exception(TQString("Failed to compile ruby code: %1").arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error + } else { + d->m_hasBeenCompiled = true; } #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Compilation was successfull"); @@ -100,7 +142,7 @@ const TQStringList& RubyScript::getFunctionNames() #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::getFunctionNames()"); #endif - if(d->m_compile == 0) + if(not d->m_hasBeenCompiled ) { compile(); } @@ -112,15 +154,9 @@ Kross::Api::Object::Ptr RubyScript::execute() #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::execute()"); #endif - if(d->m_compile == 0) - { - compile(); - } -#ifdef KROSS_RUBY_SCRIPT_DEBUG - krossdebug("Start execution"); -#endif - selectScript(); - int result = ruby_exec(); + // TODO: catch ruby exception + compile(); +#if 0 if (result != 0) { #ifdef KROSS_RUBY_SCRIPT_DEBUG @@ -136,8 +172,8 @@ Kross::Api::Object::Ptr RubyScript::execute() setException( new Kross::Api::Exception(TQString("Failed to execute ruby code: %1").arg(STR2CSTR( rb_obj_as_string(ruby_errinfo) )), 0) ); // TODO: get the error } } +#endif // 0 - unselectScript(); #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Execution is finished"); #endif @@ -151,12 +187,47 @@ Kross::Api::Object::Ptr RubyScript::callFunction(const TQString& name, Kross::Ap #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::callFunction()"); #endif - if(d->m_compile == 0) + if(not d->m_hasBeenCompiled ) { compile(); } - selectScript(); - unselectScript(); + + Q_ASSERT(d->m_hasBeenCompiled ); + +#ifdef HAVE_RUBY_1_9 + // FIXME + int ruby_errinfo = Qnil; +#endif // HAVE_RUBY_1_9 + +#if 0 + // FIXME + // The original code never really did anything as far as I can tell! + TQVariant result; + int r = ruby_exec(); + if (r != 0) { + #ifdef KROSS_RUBY_SCRIPT_DEBUG + krossdebug("RubyScript::callFunction failed"); + #endif + VALUE errorstring = rb_obj_as_string(ruby_errinfo); + setException( new Kross::Api::Exception(TQString("Failed to call function \"%1\": %2").arg(name).arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error + } + else { + VALUE self = rb_eval_string("self"); + //krossdebug(QString("RubyScript::callFunction() ===> %1").arg(STR2CSTR(rb_inspect(self)))); + + const int rnargs = args.size(); + VALUE *rargs = new VALUE[rnargs]; + for(int i = 0; i < rnargs; ++i) { + rargs[i] = RubyType::toVALUE( args[i] ); + } + + //VALUE r = rb_eval_string("myFunc()"); + VALUE v = rb_funcall2(self, rb_intern(name.toLatin1()), rnargs, rargs); + result = RubyType::toVariant(v); + delete[] rargs; + } +#endif + return 0; } @@ -165,7 +236,7 @@ const TQStringList& RubyScript::getClassNames() #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::getClassNames()"); #endif - if(d->m_compile == 0) + if(not d->m_hasBeenCompiled ) { compile(); } @@ -178,12 +249,16 @@ Kross::Api::Object::Ptr RubyScript::classInstance(const TQString& name) #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::classInstance()"); #endif - if(d->m_compile == 0) + if(not d->m_hasBeenCompiled ) { compile(); } - selectScript(); - unselectScript(); + + Q_ASSERT(d->m_hasBeenCompiled ); + + // FIXME + // The original code never really did anything from what I can tell! + return 0; }