|
|
|
/***************************************************************************
|
|
|
|
* 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 <map>
|
|
|
|
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <ksharedptr.h>
|
|
|
|
|
|
|
|
#include <api/exception.h>
|
|
|
|
#include <api/module.h>
|
|
|
|
#include <main/manager.h>
|
|
|
|
|
|
|
|
#include "rubyconfig.h"
|
|
|
|
#include "rubyextension.h"
|
|
|
|
#include "rubymodule.h"
|
|
|
|
#include "rubyscript.h"
|
|
|
|
#include "rubywrapper.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<TQString, VALUE> mStrVALUE;
|
|
|
|
typedef mStrVALUE::iterator mStrVALUE_it;
|
|
|
|
typedef mStrVALUE::const_iterator mStrVALUE_cit;
|
|
|
|
class RubyInterpreterPrivate {
|
|
|
|
friend class RubyInterpreter;
|
|
|
|
static VALUE s_krossModule;
|
|
|
|
};
|
|
|
|
|
|
|
|
VALUE RubyInterpreterPrivate::s_krossModule = 0;
|
|
|
|
|
|
|
|
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") )
|
|
|
|
{
|
|
|
|
kross_rb_set_safe_level( info->getOption("safelevel")->value.toInt() );
|
|
|
|
} else {
|
|
|
|
kross_rb_set_safe_level(3); // 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE RubyInterpreter::krossModule()
|
|
|
|
{
|
|
|
|
if(RubyInterpreterPrivate::s_krossModule == 0)
|
|
|
|
{
|
|
|
|
RubyInterpreterPrivate::s_krossModule = rb_define_module("Kross");
|
|
|
|
}
|
|
|
|
return RubyInterpreterPrivate::s_krossModule;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
TQString modname = StringValuePtr(name);
|
|
|
|
if(modname.startsWith("kross")) {
|
|
|
|
krossdebug( TQString("RubyInterpreter::require() module=%1").arg(modname) );
|
|
|
|
if( modname.find( TQRegExp("[^a-zA-Z0-9\\_\\-]") ) >= 0 ) {
|
|
|
|
krosswarning( TQString("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( TQString("Loading of Kross module '%1' failed.").arg(modname) );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return rb_f_require(obj, name);
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|