/*************************************************************************** * rubyscript.h * This file is part of the KDE project * copyright (C)2005 by Cyrille Berger (cberger@cberger.net) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * You should have received a copy of the GNU Library General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ***************************************************************************/ #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 #ifndef HAVE_RUBY_3 #include #endif // HAVE_RUBY_3 #endif // HAVE_RUBY_1_9 #include
#include "rubyconfig.h" #include "rubyextension.h" #include "rubyinterpreter.h" 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_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()) { } RubyScript::~RubyScript() { } void RubyScript::compile() { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("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); VALUE name = RubyExtension::toVALUE( m_scriptcontainer->getName() ); #ifdef HAVE_RUBY_1_9 // FIXME #else // HAVE_RUBY_1_9 critical = rb_thread_critical; rb_thread_critical = Qtrue; ruby_in_eval++; #endif // HAVE_RUBY_1_9 rb_funcall(d->m_script, rb_intern("module_eval"), 2, src, name); #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 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"); #endif } const TQStringList& RubyScript::getFunctionNames() { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::getFunctionNames()"); #endif if(not d->m_hasBeenCompiled ) { compile(); } return d->m_functions; } Kross::Api::Object::Ptr RubyScript::execute() { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::execute()"); #endif // TODO: catch ruby exception compile(); #if 0 if (result != 0) { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Execution has failed"); #endif if( TYPE( ruby_errinfo ) == T_DATA && RubyExtension::isOfExceptionType( ruby_errinfo ) ) { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Kross exception"); #endif setException( RubyExtension::convertToException( ruby_errinfo ) ); } else { 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 #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("Execution is finished"); #endif return 0; } Kross::Api::Object::Ptr RubyScript::callFunction(const TQString& name, Kross::Api::List::Ptr args) { Q_UNUSED(name) Q_UNUSED(args) #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::callFunction()"); #endif if(not d->m_hasBeenCompiled ) { compile(); } 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(TQString("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; } const TQStringList& RubyScript::getClassNames() { #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::getClassNames()"); #endif if(not d->m_hasBeenCompiled ) { compile(); } return d->m_classes; } Kross::Api::Object::Ptr RubyScript::classInstance(const TQString& name) { Q_UNUSED(name) #ifdef KROSS_RUBY_SCRIPT_DEBUG krossdebug("RubyScript::classInstance()"); #endif if(not d->m_hasBeenCompiled ) { compile(); } Q_ASSERT(d->m_hasBeenCompiled ); // FIXME // The original code never really did anything from what I can tell! return 0; } } }