/* This file is part of TDevelop Copyright (C) 2002,2003 Roberto Raggi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef DRIVER_H #define DRIVER_H #include "ast.h" #include "macro.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lexercache.h" class Lexer; class Parser; enum { Dep_Global, Dep_Local }; typedef TQPair Dependence; class ParsedFile; typedef KSharedPtr< ParsedFile > ParsedFilePointer; class ParsedFile : public AbstractParseResult { public: struct IncludeDesc { bool local; //Whether it is a local include(#include "local.h", not #include ) TQString includePath; ParsedFilePointer parsed; //May be zero! }; // ParsedFile() { // } ParsedFile( TQDataStream& s ) { read( s ); } ParsedFile( const TQString& fileName, const TQDateTime& timeStamp ); ///Deserializes the ParsedFile from a previous call to serialize(). AST will always be zero after a call to this. ParsedFile( const TQByteArray& array ); /** * @return All Macros that were used while processing this translation-unit. May be modified. */ MacroSet& usedMacros(); const MacroSet& usedMacros() const; /** * @return the count of lines that were skipped while preprocessing the file * */ int skippedLines() const; void setSkippedLines( int lines ); /** * @return Absolutely all files included by this one(no matter through how many other files they were included) */ // HashedStringSet& includeFiles(); const HashedStringSet& includeFiles() const; void addIncludeFiles( const HashedStringSet& includeFiles ); void addIncludeFile( const TQString& includePath, const ParsedFilePointer& parsed, bool localInclude ); ///If this file was parsed while resolving the dependencies of another file, this returns the file this one was included from. Else returns an empty string. TQString includedFrom() const; void setIncludedFrom( const TQString& str ); /** * @return Reference to the internal list of all directly included files(without those included indirectly) */ const TQValueList& directIncludeFiles() const; operator TranslationUnitAST* () const; //May be zero! TranslationUnitAST* operator -> () const { if( !this ) return 0; return m_translationUnit; } void setTranslationUnit( const TranslationUnitAST::Node& trans ); TQString fileName() const; TQDateTime timeStamp() const; ///Serializes the content of this class into a byte-array. Note that this does not serialize the AST. TQByteArray serialize() const; /*void read( TQDataStream& stream ); void write( TQDataStream& stream ) const;*/ virtual void read( TQDataStream& stream ) { int directIncludeFilesCount; stream >> directIncludeFilesCount; m_directIncludeFiles.clear(); for( int a = 0; a < directIncludeFilesCount; a++ ) { IncludeDesc i; TQ_INT8 in; stream >> in; i.local = in; stream >> i.includePath; //"parsed" will not be reconstructed m_directIncludeFiles.push_back( i ); } stream >> m_skippedLines; stream >> m_fileName; stream >> m_timeStamp; stream >> m_includedFrom; m_usedMacros.read( stream ); m_translationUnit = 0; m_includeFiles.read( stream ); } virtual void write( TQDataStream& stream ) const { int i = m_directIncludeFiles.size(); stream << i; for( TQValueList::const_iterator it = m_directIncludeFiles.begin(); it != m_directIncludeFiles.end(); ++it ) { TQ_INT8 i = (*it).local; stream << i; stream << (*it).includePath; } stream << m_skippedLines; stream << m_fileName; stream << m_timeStamp; stream << m_includedFrom; m_usedMacros.write( stream ); m_includeFiles.write( stream ); } virtual ParsedFileType type() const { return CppParsedFile; } private: TQValueList m_directIncludeFiles; MacroSet m_usedMacros; TranslationUnitAST::Node m_translationUnit; HashedStringSet m_includeFiles; int m_skippedLines; TQString m_fileName; TQDateTime m_timeStamp; TQString m_includedFrom; }; /** * An interface that provides source code to the Driver */ class SourceProvider { public: SourceProvider() {} virtual ~SourceProvider() {} /** * Get the contents of a file * \param fileName The name of the file to get the contents for. An absolute * path should be used. * \return A TQString that contains the contents of the file */ virtual TQString contents( const TQString& fileName ) = 0; /** * Check to see if a file has been modified * \param fileName The name of hte file to get the modification state of. An * absolute path should be used. * \return true if the file has been modified * \return false if the file has not been modified */ virtual bool isModified( const TQString& fileName ) = 0; private: SourceProvider( const SourceProvider& source ); void operator = ( const SourceProvider& source ); }; class Driver { public: Driver(); virtual ~Driver(); typedef std::multimap< HashedString, Macro > MacroMap; /** * Get the source provider for this driver. This would be useful for * getting the text the driver is working with. */ SourceProvider* sourceProvider(); /** * Sets the source provider the driver will use * @param sourceProvider the SourceProvider the driver will use */ void setSourceProvider( SourceProvider* sourceProvider ); /** * @brief Resets the driver * * Clears the driver of all problems, dependencies, macros, and include paths and * removes any translation units that have been parsed */ virtual void reset(); /** * Tells the driver to start parsing a file * @param fileName The name of the file to parse * @param onlyPreProcesss Tells the driver to only run the file through the preprocessor. Defaults to false * @param force Force the parsing of the file. Defaults to false * @param macrosGlobal Should the macros be global? (Global macros are not deleted once a new translation-unit is parsed) */ virtual void parseFile( const TQString& fileName, bool onlyPreProcesss = false, bool force = false, bool macrosGlobal = false ); /** * Indicates that the file has been parsed * @param fileName The name of the file parsed. It is legal to create a ParsedFilePointer on the given item. */ virtual void fileParsed( ParsedFile& fileName ); /** * Removes the file specified by @p fileName from the driver * @param fileName The name of the file to remove */ virtual void remove ( const TQString& fileName ); /** * Add a dependency on another header file for @p fileName * @param fileName The file name to add the dependency for * @param dep The dependency to add */ virtual void addDependence( const TQString& fileName, const Dependence& dep ); /** * Add a macro to the driver * @param macro The macro to add to the driver */ virtual void addMacro( const Macro& macro ); /** * Add a problem to the driver * @param fileName The file name to add the problem for * @param problem The problem to add */ virtual void addProblem( const TQString& fileName, const Problem& problem ); /** * The current file name the driver is working with */ TQString currentFileName() const { return m_currentFileName; } ParsedFilePointer takeTranslationUnit( const TQString& fileName ); void takeTranslationUnit( const ParsedFile& file ); /** * Get the translation unit contained in the driver for @p fileName. * @param fileName The name of the file to get the translation unit for * @return The TranslationUnitAST pointer that represents the translation unit * @return 0 if no translation unit exists for the file */ ParsedFilePointer translationUnit( const TQString& fileName ) const; /** * Get the dependencies for a file * @param fileName The file name to get dependencies for * @return The dependencies for the file */ TQMap dependences( const TQString& fileName ) const; /** * Get all the macros the driver contains * @return The macros */ const MacroMap& macros() const; /** * Take all macros from the given map(forgetting own macros) */ void insertMacros( const MacroSet& macros ); /** * Get the list of problem areas the driver contains * @param fileName The filename to get problems for * @return The list of problems for @p fileName */ TQValueList problems( const TQString& fileName ) const; void usingString( const HashedString& str ); /** * Check if we have a macro in the driver * If the last stacked macro of that name is an undef-macro, false is returned. * @param name The name of the macro to check for * @return true if we have the macro in the driver * @return false if we don't have the macro in the driver */ bool hasMacro( const HashedString& name ) ; /** * Get the macro identified by @p name * @param name The name of the macro to get * @return A const reference of the macro object represented by @p name */ const Macro& macro( const HashedString& name ) const; /** * Get the last inserted macro identified by @p name * @override * @param name The name of the macro to get * @return A non-const reference of the macro object represented by @p name * */ Macro& macro( const HashedString& name ); /** * Remove the last inserted Macro of that name * @param macroName The name of the macro to remove */ virtual void removeMacro( const HashedString& macroName ); /** * Remove all macros from the driver for a certain file * @param fileName The file name */ virtual void removeAllMacrosInFile( const TQString& fileName ); ///Check when this is called. It may be wrong. TQStringList includePaths() const { return m_includePaths; } virtual TQStringList getCustomIncludePath( const TQString& ); virtual void addIncludePath( const TQString &path ); virtual void clearIncludePaths(); /// @todo remove const TQMap &parsedUnits() const { return m_parsedUnits; } /** * Set whether or not to enable dependency resolving for files added to the driver */ virtual void setResolveDependencesEnabled( bool enabled ); /** * Check if dependency resolving is enabled * \return true if dependency resolving is enabled * \return false if dependency resolving is disabled */ bool isResolveDependencesEnabled() const { return depresolv; } void setMaxDependenceDepth( int depth ); /** * Used by the Lexer to indicate that a Macro was used * @param macro The used macro * */ void usingMacro( const Macro& macro ); /** * Returns the local instance of the lexer-cache, can be used from outside to control the cache-behavior. * */ LexerCache* lexerCache(); ///This uses getCustomIncludePath(..) to resolve the include-path internally TQString findIncludeFile( const Dependence& dep, const TQString& fromFile ); protected: ///This uses the state of the parser to find the include-file TQString findIncludeFile( const Dependence& dep ) const; /** * Set up the lexer. */ virtual void setupLexer( Lexer* lexer ); /** * Setup the parser */ virtual void setupParser( Parser* parser ); /** * Set up the preprocessor */ virtual void setupPreProcessor(); /** * Is code-information for this file already available? If false is returned, the file will be parsed. * Code-model and static repository should be checked to find out whether the file is already available. * This function is only used when dependency-resolving is activated. * @arg file absolute path to the file */ virtual bool shouldParseIncludedFile( const ParsedFilePointer& /*file*/ ); void clearMacros(); void clearParsedMacros(); private: TQMap& findOrInsertDependenceList( const TQString& fileName ); TQValueList& findOrInsertProblemList( const TQString& fileName ); private: TQString m_currentFileName; TQString m_currentMasterFileName; typedef TQMap DependenceMap; typedef TQMap< TQString, DependenceMap> DependencesMap; DependencesMap m_dependences; MacroMap m_macros; TQMap< TQString, TQValueList > m_problems; TQMap m_parsedUnits; TQStringList m_includePaths; uint depresolv : 1; Lexer *lexer; SourceProvider* m_sourceProvider; ParsedFilePointer m_currentParsedFile; CachedLexedFilePointer m_currentLexerCache; LexerCache m_lexerCache; int m_dependenceDepth; int m_maxDependenceDepth; class ParseHelper; friend class ParseHelper; private: Driver( const Driver& source ); void operator = ( const Driver& source ); }; #endif