/*************************************************************************** * rubyinterpreter.cpp * 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 "rubyinterpreter.h" #include #include #include #include #include #include
#include "rubyconfig.h" #include "rubyextension.h" #include "rubymodule.h" #include "rubyscript.h" extern "C" { /** * Exported and loadable function as entry point to use * the \a RubyInterpreter. * The krossruby library will be loaded dynamicly at runtime from e.g. * \a Kross::Api::Manager::getInterpreter and this exported * function will be used to return an instance of the * \a RubyInterpreter implementation. */ void* krossinterpreter(Kross::Api::InterpreterInfo* info) { #ifdef KROSS_RUBY_INTERPRETER_DEBUG krossdebug("krossinterpreter(info)"); #endif try { return new Kross::Ruby::RubyInterpreter(info); } catch(Kross::Api::Exception::Ptr e) { Kross::krosswarning("krossinterpreter(Kross::Api::InterpreterInfo* info): Unhandled exception."); } return 0; } }; namespace Kross { namespace Ruby { typedef std::map mStrVALUE; typedef mStrVALUE::iterator mStrVALUE_it; typedef mStrVALUE::const_iterator mStrVALUE_cit; class RubyInterpreterPrivate { friend class RubyInterpreter; }; RubyInterpreterPrivate* RubyInterpreter::d = 0; RubyInterpreter::RubyInterpreter(Kross::Api::InterpreterInfo* info): Kross::Api::Interpreter(info) { #ifdef KROSS_RUBY_INTERPRETER_DEBUG krossdebug("RubyInterpreter::RubyInterpreter(info)"); #endif if(d == 0) { initRuby(); } if(info->hasOption("safelevel") ) { rb_set_safe_level( info->getOption("safelevel")->value.toInt() ); } else { rb_set_safe_level(4); // if the safelevel option is undefined, set it to maximum level } } RubyInterpreter::~RubyInterpreter() { finalizeRuby(); } Kross::Api::Script* RubyInterpreter::createScript(Kross::Api::ScriptContainer* scriptcontainer) { return new RubyScript(this, scriptcontainer); } void RubyInterpreter::initRuby() { d = new RubyInterpreterPrivate(); ruby_init(); ruby_init_loadpath(); rb_define_global_function("require", (VALUE (*)(...))RubyInterpreter::require, 1); } void RubyInterpreter::finalizeRuby() { delete d; d = 0; ruby_finalize(); } VALUE RubyInterpreter::require (VALUE obj, VALUE name) { #ifdef KROSS_RUBY_INTERPRETER_DEBUG krossdebug("RubyInterpreter::require(obj,name)"); #endif QString modname = StringValuePtr(name); if(modname.startsWith("kross")) { krossdebug( QString("RubyInterpreter::require() module=%1").arg(modname) ); if( modname.find( QRegExp("[^a-zA-Z0-9\\_\\-]") ) >= 0 ) { krosswarning( QString("Denied import of Kross module '%1' cause of untrusted chars.").arg(modname) ); } else { Kross::Api::Module::Ptr module = Kross::Api::Manager::scriptManager()->loadModule(modname); if(module) { new RubyModule(module, modname); // VALUE rmodule = rb_define_module(modname.ascii()); // rb_define_module_function(); // VALUE rm = RubyExtension::toVALUE(module); // rb_define_variable( ("$" + modname).ascii(), & RubyInterpreter::d->m_modules.insert( mStrVALUE::value_type( modname, rm) ).first->second ); return Qtrue; } krosswarning( QString("Loading of Kross module '%1' failed.").arg(modname) ); } } else { return rb_f_require(obj, name); } return Qfalse; } } }