You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kross/ruby/rubyinterpreter.cpp

150 lines
4.6 KiB

/***************************************************************************
* 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 <qregexp.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"
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<QString, VALUE> 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;
}
}
}