/***************************************************************************
* 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 <ruby.h>
# ifndef HAVE_RUBY_1_9
# include <env.h>
# include <rubysig.h>
# include <node.h>
# else // HAVE_RUBY_1_9
# ifndef HAVE_RUBY_3
# include <ruby/backward/rubysig.h>
# endif // HAVE_RUBY_3
# endif // HAVE_RUBY_1_9
# include <main/scriptcontainer.h>
# 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 < TQVariant > : : toVALUE ( args [ i ] ) ;
}
//VALUE r = rb_eval_string("myFunc()");
VALUE v = rb_funcall2 ( self , rb_intern ( name . toLatin1 ( ) ) , rnargs , rargs ) ;
result = RubyType < TQVariant > : : 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 ;
}
}
}