KDevelop API Documentation

lib/cppparser/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.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:47 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003