00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
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
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
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
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
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
00367 lexer->addSkipWord( "WINAPI" );
00368 lexer->addSkipWord( "__stdcall" );
00369 lexer->addSkipWord( "__cdecl" );
00370 lexer->addSkipWord( "_cdecl" );
00371 lexer->addSkipWord( "CALLBACK" );
00372
00373
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 }