KDevelop API Documentation

driver.cpp

Go to the documentation of this file.
00001 /* This file is part of KDevelop
00002     Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.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 "driver.h"
00021 #include "lexer.h"
00022 #include "parser.h"
00023 #include <kdebug.h>
00024 #include <stdlib.h>
00025 #include <qfile.h>
00026 #include <qfileinfo.h>
00027 #include <qdir.h>
00028 
00029 class DefaultSourceProvider: public SourceProvider
00030 {
00031 public:
00032     DefaultSourceProvider() {}
00033 
00034     virtual QString contents( const QString& fileName )
00035     {
00036     QString source;
00037 
00038     QFile f( fileName );
00039     if( f.open(IO_ReadOnly) ){
00040         QTextStream s( &f );
00041         source = s.read();
00042         f.close();
00043     }
00044     return source;
00045     }
00046 
00047     virtual bool isModified( const QString& fileName )
00048     {
00049     Q_UNUSED( fileName );
00050     return true;
00051     }
00052 
00053 private:
00054     DefaultSourceProvider( const DefaultSourceProvider& source );
00055     void operator = ( const DefaultSourceProvider& source );
00056 };
00057 
00058 
00059 Driver::Driver()
00060     : depresolv( FALSE ), lexer( 0 )
00061 {
00062     m_sourceProvider = new DefaultSourceProvider();
00063 }
00064 
00065 Driver::~Driver()
00066 {
00067     reset();
00068     delete( m_sourceProvider );
00069 }
00070 
00071 SourceProvider* Driver::sourceProvider()
00072 {
00073     return m_sourceProvider;
00074 }
00075 
00076 void Driver::setSourceProvider( SourceProvider* sourceProvider )
00077 {
00078     if( m_sourceProvider )
00079     delete( m_sourceProvider );
00080     m_sourceProvider = sourceProvider;
00081 }
00082 
00083 void Driver::reset( )
00084 {
00085     m_dependences.clear();
00086     m_macros.clear();
00087     m_problems.clear();
00088     m_includePaths.clear();
00089 
00090     while( m_parsedUnits.size() ){
00091     TranslationUnitAST* unit = *m_parsedUnits.begin();
00092     m_parsedUnits.remove( m_parsedUnits.begin() );
00093     delete( unit );
00094     }
00095 }
00096 
00097 void Driver::remove( const QString & fileName )
00098 {
00099     m_dependences.remove( fileName );
00100     m_problems.remove( fileName );
00101     removeAllMacrosInFile( fileName );
00102 
00103     QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
00104     if( it != m_parsedUnits.end() ){
00105     TranslationUnitAST* unit = *it;
00106     m_parsedUnits.remove( it );
00107     delete( unit );
00108     }
00109 }
00110 
00111 void Driver::removeAllMacrosInFile( const QString& fileName )
00112 {
00113     QMap<QString, Macro>::Iterator it = m_macros.begin();
00114     while( it != m_macros.end() ){
00115         Macro m = *it++;
00116         if( m.fileName() == fileName )
00117             removeMacro( m.name() );
00118     }
00119 }
00120 
00121 TranslationUnitAST::Node Driver::takeTranslationUnit( const QString& fileName )
00122 {
00123     QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( fileName );
00124     TranslationUnitAST::Node unit( *it );
00125     //m_parsedUnits.remove( it );
00126     m_parsedUnits[ fileName] = 0;
00127     return unit;
00128 }
00129 
00130 TranslationUnitAST* Driver::translationUnit( const QString& fileName ) const
00131 {
00132     QMap<QString, TranslationUnitAST*>::ConstIterator it = m_parsedUnits.find( fileName );
00133     return it != m_parsedUnits.end() ? *it : 0;
00134 }
00135 
00136 void Driver::addDependence( const QString & fileName, const Dependence & dep )
00137 {
00138     QFileInfo fileInfo( dep.first );
00139     QString fn = fileInfo.absFilePath();
00140 
00141     if ( !depresolv ){
00142         findOrInsertDependenceList( fileName ).insert( fn, dep );
00143     return;
00144     }
00145 
00146     QString file = findIncludeFile( dep );
00147     findOrInsertDependenceList( fileName ).insert( file, dep );
00148 
00149     if ( m_parsedUnits.find(file) != m_parsedUnits.end() )
00150     return;
00151 
00152     if ( !QFile::exists( file ) ) {
00153     Problem p( "Couldn't find include file " + dep.first,
00154            lexer ? lexer->currentLine() : -1,
00155            lexer ? lexer->currentColumn() : -1 );
00156     addProblem( fileName, p );
00157     return;
00158     }
00159 
00160     QString cfn = m_currentFileName;
00161     Lexer *l = lexer;
00162     parseFile( file );
00163     m_currentFileName = cfn;
00164     lexer = l;
00165 }
00166 
00167 void Driver::addMacro( const Macro & macro )
00168 {
00169     m_macros.insert( macro.name(), macro );
00170 }
00171 
00172 void Driver::addProblem( const QString & fileName, const Problem & problem )
00173 {
00174     findOrInsertProblemList( fileName ).append( problem );
00175 }
00176 
00177 QMap< QString, Dependence >& Driver::findOrInsertDependenceList( const QString & fileName )
00178 {
00179     QMap<QString, QMap<QString, Dependence> >::Iterator it = m_dependences.find( fileName );
00180     if( it != m_dependences.end() )
00181         return it.data();
00182 
00183     QMap<QString, Dependence> l;
00184     m_dependences.insert( fileName, l );
00185     return m_dependences[ fileName ];
00186 }
00187 
00188 QValueList < Problem >& Driver::findOrInsertProblemList( const QString & fileName )
00189 {
00190     QMap<QString, QValueList<Problem> >::Iterator it = m_problems.find( fileName );
00191     if( it != m_problems.end() )
00192         return it.data();
00193 
00194     QValueList<Problem> l;
00195     m_problems.insert( fileName, l );
00196     return m_problems[ fileName ];
00197 }
00198 
00199 QMap< QString, Dependence > Driver::dependences( const QString & fileName ) const
00200 {
00201     QMap<QString, QMap<QString, Dependence> >::ConstIterator it = m_dependences.find( fileName );
00202     if( it != m_dependences.end() )
00203     return it.data();
00204     return QMap<QString, Dependence>();
00205 }
00206 
00207 QMap< QString, Macro > Driver::macros() const
00208 {
00209     return m_macros;
00210 }
00211 
00212 QValueList < Problem > Driver::problems( const QString & fileName ) const
00213 {
00214     QMap<QString, QValueList<Problem> >::ConstIterator it = m_problems.find( fileName );
00215     if( it != m_problems.end() )
00216     return it.data();
00217     return QValueList<Problem>();
00218 }
00219 
00220 void Driver::parseFile( const QString& fileName, bool onlyPreProcess, bool force )
00221 {
00222     QFileInfo fileInfo( fileName );
00223     QString absFilePath = fileInfo.absFilePath();
00224 
00225     QMap<QString, TranslationUnitAST*>::Iterator it = m_parsedUnits.find( absFilePath );
00226 
00227     if( force && it != m_parsedUnits.end() ){
00228     takeTranslationUnit( absFilePath );
00229     } else if( it != m_parsedUnits.end() && *it != 0 ){
00230     // file already processed
00231     return;
00232     }
00233 
00234     m_dependences.remove( fileName );
00235     m_problems.remove( fileName );
00236 
00237     m_currentFileName = fileName;
00238 
00239     Lexer lex( this );
00240     lexer = &lex;
00241     setupLexer( &lex );
00242 
00243     lex.setSource( sourceProvider()->contents(fileName) );
00244 
00245     if( !onlyPreProcess ){
00246     Parser parser( this, &lex );
00247     setupParser( &parser );
00248 
00249         TranslationUnitAST :: Node translationUnit;
00250     parser.parseTranslationUnit( translationUnit );
00251         m_parsedUnits.insert( fileName, translationUnit.release() );
00252         fileParsed( fileName );
00253     }
00254     
00255     m_currentFileName = QString::null;
00256     lexer = 0;
00257 }
00258 
00259 void Driver::setupLexer( Lexer * lexer )
00260 {
00261     // stl
00262     lexer->addSkipWord( "__STL_BEGIN_NAMESPACE" );
00263     lexer->addSkipWord( "__STL_END_NAMESPACE" );
00264     lexer->addSkipWord( "__STL_BEGIN_RELOPS_NAMESPACE" );
00265     lexer->addSkipWord( "__STL_END_RELOPS_NAMESPACE" );
00266     lexer->addSkipWord( "__STL_TEMPLATE_NULL" );
00267     lexer->addSkipWord( "__STL_TRY" );
00268     lexer->addSkipWord( "__STL_UNWIND" );
00269     lexer->addSkipWord( "__STL_NOTHROW" );
00270     lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
00271     lexer->addSkipWord( "__STL_UNWIND", SkipWordAndArguments );
00272     lexer->addSkipWord( "__GC_CONST" );
00273     lexer->addSkipWord( "__HASH_ALLOC_INIT", SkipWordAndArguments );
00274     lexer->addSkipWord( "__STL_DEFAULT_ALLOCATOR",  SkipWordAndArguments, "T" );
00275     lexer->addSkipWord( "__STL_MUTEX_INITIALIZER" );
00276     lexer->addSkipWord( "__STL_NULL_TMPL_ARGS" );
00277 
00278     // antlr
00279     lexer->addSkipWord( "ANTLR_BEGIN_NAMESPACE", SkipWordAndArguments );
00280     lexer->addSkipWord( "ANTLR_USE_NAMESPACE", SkipWordAndArguments );
00281     lexer->addSkipWord( "ANTLR_USING_NAMESPACE", SkipWordAndArguments );
00282     lexer->addSkipWord( "ANTLR_END_NAMESPACE" );
00283     lexer->addSkipWord( "ANTLR_C_USING", SkipWordAndArguments );
00284     lexer->addSkipWord( "ANTLR_API" );
00285 
00286     // gnu
00287     lexer->addSkipWord( "__extension__", SkipWordAndArguments );
00288     lexer->addSkipWord( "__attribute__", SkipWordAndArguments );
00289     lexer->addSkipWord( "__BEGIN_DECLS" );
00290     lexer->addSkipWord( "__END_DECLS" );
00291     lexer->addSkipWord( "__THROW" );
00292     lexer->addSkipWord( "__restrict" );
00293     lexer->addSkipWord( "__restrict__" );
00294     lexer->addSkipWord( "__attribute_pure__" );
00295     lexer->addSkipWord( "__attribute_malloc__" );
00296     lexer->addSkipWord( "__attribute_format_strfmon__" );
00297     lexer->addSkipWord( "__asm__", SkipWordAndArguments );
00298     lexer->addSkipWord( "__devinit" );
00299     lexer->addSkipWord( "__devinit__" );
00300     lexer->addSkipWord( "__init" );
00301     lexer->addSkipWord( "__init__" );
00302     lexer->addSkipWord( "__signed" );
00303     lexer->addSkipWord( "__signed__" );
00304     lexer->addSkipWord( "__unsigned" );
00305     lexer->addSkipWord( "__unsigned__" );
00306     lexer->addSkipWord( "asmlinkage" );
00307     lexer->addSkipWord( "____cacheline_aligned" );
00308     lexer->addSkipWord( "__glibcpp_class_requires", SkipWordAndArguments );
00309     lexer->addSkipWord( "__glibcpp_class2_requires", SkipWordAndArguments );
00310     lexer->addSkipWord( "__glibcpp_class4_requires", SkipWordAndArguments );
00311     lexer->addSkipWord( "__glibcpp_function_requires", SkipWordAndArguments );
00312     lexer->addSkipWord( "restrict" );
00313 
00314     lexer->addSkipWord( "__BEGIN_NAMESPACE_STD" );
00315     lexer->addSkipWord( "__END_NAMESPACE_STD" );
00316     lexer->addSkipWord( "__BEGIN_NAMESPACE_C99" );
00317     lexer->addSkipWord( "__END_NAMESPACE_C99" );
00318     lexer->addSkipWord( "__USING_NAMESPACE_STD", SkipWordAndArguments );
00319 
00320     // kde
00321     lexer->addSkipWord( "K_SYCOCATYPE", SkipWordAndArguments );
00322     lexer->addSkipWord( "EXPORT_DOCKCLASS" );
00323     lexer->addSkipWord( "K_EXPORT_COMPONENT_FACTORY", SkipWordAndArguments );
00324     lexer->addSkipWord( "K_SYCOCAFACTORY", SkipWordAndArguments );
00325     lexer->addSkipWord( "KDE_DEPRECATED" );
00326 
00327     // qt
00328     lexer->addSkipWord( "Q_OVERRIDE", SkipWordAndArguments );
00329     lexer->addSkipWord( "Q_ENUMS", SkipWordAndArguments );
00330     lexer->addSkipWord( "Q_PROPERTY", SkipWordAndArguments );
00331     lexer->addSkipWord( "Q_CLASSINFO", SkipWordAndArguments );
00332     lexer->addSkipWord( "Q_SETS", SkipWordAndArguments );
00333     lexer->addSkipWord( "Q_UNUSED", SkipWordAndArguments );
00334     lexer->addSkipWord( "Q_CREATE_INSTANCE", SkipWordAndArguments );
00335     lexer->addSkipWord( "Q_DUMMY_COMPARISON_OPERATOR", SkipWordAndArguments );
00336     lexer->addSkipWord( "ACTIVATE_SIGNAL_WITH_PARAM", SkipWordAndArguments );
00337     lexer->addSkipWord( "Q_INLINE_TEMPLATES" );
00338     lexer->addSkipWord( "Q_TEMPLATE_EXTERN" );
00339     lexer->addSkipWord( "Q_TYPENAME" );
00340     lexer->addSkipWord( "Q_REFCOUNT" );
00341     lexer->addSkipWord( "Q_EXPLICIT" );
00342     lexer->addSkipWord( "QMAC_PASCAL" );
00343     lexer->addSkipWord( "QT_STATIC_CONST" );
00344     lexer->addSkipWord( "QT_STATIC_CONST_IMPL" );
00345     lexer->addSkipWord( "QT_WIN_PAINTER_MEMBERS" );
00346     lexer->addSkipWord( "QT_NC_MSGBOX" );
00347     lexer->addSkipWord( "Q_VARIANT_AS", SkipWordAndArguments );
00348     lexer->addSkipWord( "CALLBACK_CALL_TYPE" );
00349 
00350     // flex
00351     lexer->addSkipWord( "yyconst" );
00352     lexer->addSkipWord( "YY_RULE_SETUP" );
00353     lexer->addSkipWord( "YY_BREAK" );
00354     lexer->addSkipWord( "YY_RESTORE_YY_MORE_OFFSET" );
00355 
00356     // gtk
00357     lexer->addSkipWord( "G_BEGIN_DECLS" );
00358     lexer->addSkipWord( "G_END_DECLS" );
00359     lexer->addSkipWord( "G_GNUC_CONST" );
00360     lexer->addSkipWord( "G_CONST_RETURN" );
00361     lexer->addSkipWord( "GTKMAIN_C_VAR" );
00362     lexer->addSkipWord( "GTKVAR" );
00363     lexer->addSkipWord( "GDKVAR" );
00364     lexer->addSkipWord( "G_GNUC_PRINTF", SkipWordAndArguments );
00365 
00366     // windows
00367     lexer->addSkipWord( "WINAPI" );
00368     lexer->addSkipWord( "__stdcall" );
00369     lexer->addSkipWord( "__cdecl" );
00370     lexer->addSkipWord( "_cdecl" );
00371     lexer->addSkipWord( "CALLBACK" );
00372 
00373    // gcc extensions
00374     addMacro( Macro("__asm__", "asm") );
00375     addMacro( Macro("__inline", "inline") );
00376     addMacro( Macro("__inline__", "inline") );
00377     addMacro( Macro("__const", "const") );
00378     addMacro( Macro("__const__", "const") );
00379     addMacro( Macro("__volatile__", "volatile") );
00380     addMacro( Macro("__complex__", "") );
00381 }
00382 
00383 void Driver::setupParser( Parser * parser )
00384 {
00385     Q_UNUSED( parser );
00386 }
00387 
00388 void Driver::removeMacro( const QString& macroName )
00389 {
00390     m_macros.remove( macroName );
00391 }
00392 
00393 void Driver::addIncludePath( const QString &path )
00394 {
00395     if( !path.stripWhiteSpace().isEmpty() )
00396         m_includePaths << path;
00397 }
00398 
00399 QString Driver::findIncludeFile( const Dependence& dep ) const
00400 {
00401     QString fileName = dep.first;
00402 
00403     if( dep.second == Dep_Local ){
00404         QString path = QFileInfo( currentFileName() ).dirPath( true );
00405         QFileInfo fileInfo( QFileInfo(path, fileName) );
00406     if ( fileInfo.exists() && fileInfo.isFile() )
00407         return fileInfo.absFilePath();
00408 
00409     }
00410 
00411     for ( QStringList::ConstIterator it = m_includePaths.begin(); it != m_includePaths.end(); ++it ) {
00412         QFileInfo fileInfo( *it, fileName );
00413     if ( fileInfo.exists() && fileInfo.isFile() )
00414         return fileInfo.absFilePath();
00415     }
00416 
00417     return QString::null;
00418 }
00419 
00420 void Driver::setResolveDependencesEnabled( bool enabled )
00421 {
00422     depresolv = enabled;
00423     if ( depresolv )
00424     setupPreProcessor();
00425 }
00426 
00427 void Driver::setupPreProcessor()
00428 {
00429 }
00430 
00431 void Driver::fileParsed( const QString & fileName )
00432 {
00433     Q_UNUSED( fileName );
00434 }
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:51 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003