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 Wed Nov 17 06:54:17 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003