lib Library API Documentation

koscript.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "koscript_parser.h"
00021 #include "koscript_context.h"
00022 #include "koscript_func.h"
00023 #include "koscript.h"
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <sys/types.h>
00028 #include <dirent.h>
00029 #include <sys/stat.h>
00030 
00031 #include <qfile.h>
00032 #include <qtextstream.h>
00033 
00034 #include <kglobal.h>
00035 #include <kdebug.h>
00036 #include <kstandarddirs.h>
00037 #include <klocale.h>
00038 
00039 KSInterpreter::KSInterpreter()
00040 {
00041     m_outStream = 0;
00042     m_currentArg = -1;
00043     m_outDevice = 0;
00044     m_lastInputLine = new KSValue( QString() );
00045     m_lastInputLine->setMode( KSValue::LeftExpr );
00046 
00047     KSModule::Ptr m = ksCreateModule_KScript( this );
00048     m_modules.insert( m->name(), m );
00049 
00050     // This module will serve as our global namespace
00051     // since adressing all kscript builtin stuff via its module
00052     // is too much typing for our users.
00053     m_global = m->nameSpace();
00054 
00055     m_globalContext.setScope( new KSScope( m_global, 0 ) );
00056 }
00057 
00058 KSInterpreter::~KSInterpreter()
00059 {
00060     if ( m_outStream )
00061         delete m_outStream;
00062     if ( m_outDevice )
00063     {
00064         m_outDevice->close();
00065         delete m_outDevice;
00066     }
00067 }
00068 
00069 KSModule::Ptr KSInterpreter::module( const QString& name )
00070 {
00071   QMap<QString,KSModule::Ptr>::Iterator it = m_modules.find( name );
00072   if ( it == m_modules.end() )
00073     return 0;
00074 
00075   return it.data();
00076 }
00077 
00078 QString KSInterpreter::runScript( const QString& filename, const QStringList& args )
00079 {
00080     // Save for usage by the <> operator
00081     m_args = args;
00082 
00083     KSContext context( m_globalContext );
00084     // The "" indicates that this is not a module but
00085     // a script in its original meaning.
00086     if ( !runModule( context, "", filename, args ) )
00087         return context.exception()->toString( context );
00088 
00089     return QString::null;
00090 }
00091 
00092 bool KSInterpreter::runModule( KSContext& context, const QString& name )
00093 {
00094   // Did we load this module already ? Dont load it twice
00095   if ( m_modules.contains( name ) )
00096   {
00097     KSModule* m = m_modules[name];
00098     m->ref();
00099     context.setValue( new KSValue( m ) );
00100 
00101     return true;
00102   }
00103 
00104   QString ksname = name + ".ks";
00105 
00106   QStringList::Iterator it = m_searchPaths.begin();
00107   for( ; it != m_searchPaths.end(); ++it )
00108   {
00109     DIR *dp = 0L;
00110     struct dirent *ep;
00111 
00112     dp = opendir( QFile::encodeName(*it) );
00113     if ( dp == 0L )
00114       return false;
00115 
00116     while ( ( ep = readdir( dp ) ) != 0L )
00117     {
00118       if ( ksname == ep->d_name )
00119       {
00120         QString f = *it;
00121         f += "/";
00122         f += ep->d_name;
00123         struct stat buff;
00124         if ( ( stat( QFile::encodeName(f), &buff ) == 0 ) && S_ISREG( buff.st_mode ) )
00125         {
00126           QStringList lst;
00127           kdDebug() << "runModule " << name << " " << f << endl;
00128           return runModule( context, name, f, lst );
00129         }
00130       }
00131     }
00132 
00133     closedir( dp );
00134   }
00135 
00136   QString tmp( i18n("Could not find module %1") );
00137   context.setException( new KSException( "IOError", tmp.arg( name ) ) );
00138   return false;
00139 }
00140 
00141 bool KSInterpreter::runModule( KSContext& result, const QString& name, const QString& filename, const QStringList& args )
00142 {
00143   // Did we load this module already ? Dont load it twice
00144   if ( m_modules.contains( name ) )
00145   {
00146     KSModule* m = m_modules[name];
00147     m->ref();
00148     result.setValue( new KSValue( m ) );
00149 
00150     return true;
00151   }
00152 
00153   m_globalContext.setException( 0 );
00154 
00155   // s_current = this;
00156 
00157   FILE* f = fopen( QFile::encodeName(filename), "r" );
00158   if ( !f )
00159   {
00160     QString tmp( i18n("Could not open file %1") );
00161     result.setException( new KSException( "IOError", tmp.arg( filename ) ) );
00162     return false;
00163   }
00164 
00165   KSModule::Ptr module;
00166   // Create the parse tree.
00167   KSParser parser;
00168   if ( !parser.parse( f, QFile::encodeName( filename ) ) )
00169   {
00170       fclose( f );
00171       result.setException( new KSException( "SyntaxError", parser.errorMessage() ) );
00172       return false;
00173   }
00174   // Create a module
00175   module = new KSModule( this, name, parser.donateParseTree() );
00176 
00177   fclose( f );
00178   // parser.print( true );
00179 
00180   // Put the module in the return value
00181   module->ref();
00182   result.setValue( new KSValue( &*module ) );
00183 
00184   // Put all global functions etc. in the scope
00185   KSContext context;
00186   // ### TODO: Do we create a memory leak here ?
00187   context.setScope( new KSScope( m_global, module ) );
00188 
00189   // Travers the parse tree to find functions and classes etc.
00190   if ( !module->eval( context ) )
00191   {
00192     if ( context.exception() )
00193     {
00194       result.setException( context );
00195       return false;
00196     }
00197     // TODO: create exception
00198     printf("No exception available\n");
00199     return false;
00200   }
00201 
00202   // Is there a main function to execute ?
00203   KSValue* code = module->object( "main" );
00204   if ( code )
00205   {
00206     // create a context that holds the argument list
00207     // for the main function ( the list is empty currently ).
00208     KSContext context;
00209     context.setValue( new KSValue( KSValue::ListType ) );
00210     // ### TODO: Do we create a memory leak here ?
00211     context.setScope( new KSScope( m_global, module ) );
00212 
00213     // Insert parameters
00214     QStringList::ConstIterator sit = args.begin();
00215     QStringList::ConstIterator send = args.end();
00216     for( ; sit != send; ++sit )
00217     {
00218         context.value()->listValue().append( new KSValue( *sit ) );
00219     }
00220 
00221     if ( !code->functionValue()->call( context ) )
00222     {
00223       if ( context.exception() )
00224       {
00225         result.setException( context );
00226         return false;
00227       }
00228 
00229       // TODO: create exception
00230       printf("No exception available\n");
00231       return false;
00232     }
00233   }
00234 
00235   KSException* ex = m_globalContext.shareException();
00236   m_globalContext.setException( 0 );
00237   if ( ex )
00238   {
00239     result.setException( ex );
00240     return false;
00241   }
00242 
00243   // Did we just execute a file ? -> Done
00244   if ( name.isEmpty() )
00245     return true;
00246 
00247   m_modules.insert( name, module );
00248 
00249   return true;
00250 }
00251 
00252 bool KSInterpreter::processExtension( KSContext& context, KSParseNode* node )
00253 {
00254   QString tmp( i18n("The interpreter does not support an extended syntax you are using."));
00255   context.setException( new KSException( "UnsupportedSyntaxExtension", tmp, node->getLineNo() ) );
00256 
00257   return false;
00258 }
00259 
00260 KRegExp* KSInterpreter::regexp()
00261 {
00262     return &m_regexp;
00263 }
00264 
00265 QString KSInterpreter::readInput()
00266 {
00267     if ( !m_outStream )
00268     {
00269         if ( m_args.count() > 0 )
00270         {
00271             m_currentArg = 0;
00272             m_outDevice = new QFile( m_args[ m_currentArg ] );
00273             m_outDevice->open( IO_ReadOnly );
00274             m_outStream = new QTextStream( m_outDevice );
00275         }
00276         else
00277             m_outStream = new QTextStream( stdin, IO_ReadOnly );
00278     }
00279 
00280     QString tmp = m_outStream->readLine();
00281 
00282     if ( !tmp.isNull() )
00283     {
00284         tmp += "\n";
00285         m_lastInputLine->setValue( tmp );
00286         return tmp;
00287     }
00288 
00289     m_lastInputLine->setValue( tmp );
00290 
00291     // Ended reading a file ...
00292 
00293     // Did we scan the last file ?
00294     if ( m_currentArg == (int)m_args.count() - 1 )
00295         return QString();
00296     else
00297     {
00298         m_currentArg++;
00299         if ( m_outStream )
00300             delete m_outStream;
00301         if ( m_outDevice )
00302             delete m_outDevice;
00303         m_outDevice = new QFile( m_args[ m_currentArg ] );
00304         m_outDevice->open( IO_ReadOnly );
00305         m_outStream = new QTextStream( m_outDevice );
00306     }
00307 
00308     return readInput();
00309 }
00310 
00311 KSValue::Ptr KSInterpreter::lastInputLine() const
00312 {
00313     return m_lastInputLine;
00314 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Mar 11 11:47:43 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003