diff --git a/app/qtlockedfile.cpp b/app/qtlockedfile.cpp index bf181a97cb..39cddbbff2 100644 --- a/app/qtlockedfile.cpp +++ b/app/qtlockedfile.cpp @@ -1,154 +1,154 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "qtlockedfile.h" namespace SharedTools { /*! \class QtLockedFile \brief The QtLockedFile class extends QFile with advisory locking functions. A file may be locked in read or write mode. Multiple instances of \e QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file. The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QtLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost. The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode This enum describes the available lock modes. \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() */ QtLockedFile::QtLockedFile() : QFile() + , m_lock_mode(NoLock) { #ifdef Q_OS_WIN m_semaphore_hnd = 0; m_mutex_hnd = 0; #endif - m_lock_mode = NoLock; } /*! Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in the same way as \e QFile::QFile(const QString&). \sa QFile::QFile() */ QtLockedFile::QtLockedFile(const QString &name) : QFile(name) + , m_lock_mode(NoLock) { #ifdef Q_OS_WIN m_semaphore_hnd = 0; m_mutex_hnd = 0; #endif - m_lock_mode = NoLock; } /*! Returns \e true if this object has a in read or write lock; otherwise returns \e false. \sa lockMode() */ bool QtLockedFile::isLocked() const { return m_lock_mode != NoLock; } /*! Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. \sa isLocked() */ QtLockedFile::LockMode QtLockedFile::lockMode() const { return m_lock_mode; } /*! \fn bool QtLockedFile::lock(LockMode mode, bool block = true) Obtains a lock of type \a mode. If \a block is true, this function will block until the lock is acquired. If \a block is false, this function returns \e false immediately if the lock cannot be acquired. If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock is first released and then a new lock is obtained. This function returns \e true if, after it executes, the file is locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() */ /*! \fn bool QtLockedFile::unlock() Releases a lock. If the object has no lock, this function returns immediately. This function returns \e true if, after it executes, the file is not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. */ } // namespace SharedTools diff --git a/debuggers/gdb/unittests/debugeemultiplebreakpoint.cpp b/debuggers/gdb/unittests/debugeemultiplebreakpoint.cpp index af63b7c073..25b86c62fa 100644 --- a/debuggers/gdb/unittests/debugeemultiplebreakpoint.cpp +++ b/debuggers/gdb/unittests/debugeemultiplebreakpoint.cpp @@ -1,53 +1,52 @@ /* Copyright 2013 Vlas Puhov This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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. */ #include class Str2 { public: void print(void) { std::cout << "Str2\n"; } }; class Str { - public: Str() { - S="str\n"; + public: Str() : S("str\n") { } public: void print(void) { std::cout << S; } private: std::string S; }; void Print ( Str2& c, Str& s, bool b ) { if(b){ c.print(); s.print(); } } int main ( void ) { Str2 c; Str s; Print ( c, s, true ); return 1; } diff --git a/debuggers/lldb/unittests/debugees/debugeemultiplebreakpoint.cpp b/debuggers/lldb/unittests/debugees/debugeemultiplebreakpoint.cpp index af63b7c073..25b86c62fa 100644 --- a/debuggers/lldb/unittests/debugees/debugeemultiplebreakpoint.cpp +++ b/debuggers/lldb/unittests/debugees/debugeemultiplebreakpoint.cpp @@ -1,53 +1,52 @@ /* Copyright 2013 Vlas Puhov This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. 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. */ #include class Str2 { public: void print(void) { std::cout << "Str2\n"; } }; class Str { - public: Str() { - S="str\n"; + public: Str() : S("str\n") { } public: void print(void) { std::cout << S; } private: std::string S; }; void Print ( Str2& c, Str& s, bool b ) { if(b){ c.print(); s.print(); } } int main ( void ) { Str2 c; Str s; Print ( c, s, true ); return 1; } diff --git a/languages/cpp/cppduchain/environmentmanager.h b/languages/cpp/cppduchain/environmentmanager.h index 7e6ed29ccb..bdbc1d9e66 100644 --- a/languages/cpp/cppduchain/environmentmanager.h +++ b/languages/cpp/cppduchain/environmentmanager.h @@ -1,380 +1,383 @@ /*************************************************************************** Copyright 2006 David Nolden ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ENVIRONMENTMANAGER_H #define ENVIRONMENTMANAGER_H #include #include #include #include #include #include "cppduchainexport.h" #include "parser/rpp/macrorepository.h" namespace KDevelop { class TopDUContext; } /** * The environment-manager helps achieving right representation of the way c++ works: * When a file is processed by the preprocessor, the same file may create totally * different results depending on the defined macros. Think for example of header- * guards. * * Now when one file includes another, we want to know whether there already * is a readily parsed du-context for the file that WOULD BE CREATED if it was * preprocessed under the current environment of macros. * * The environment-manager is there to answer that question: * EnvironmentFile collects all information about the context a file was parsed in, * the macros used, the words contained in a file that can be influenced by macros, * and the defined macros. * * The environment-manager is able to match that information agains a current parsing-environment * to see whether preprocessing the file would yield the same result as an already stored * run. * * If the result would be different, the file will be re-preprocessed, parsed, and imported. * Else the set of defined macros is taken from the stored EnvironmentFile, * and the already available du-context will be imported. The result: correct behavior, perfectly working header-guards, no missing macros, intelligent reparsing of changed headers, ... * * There is only one assumption made that needs to be fulfilled to be correct: * - Headers should be included at the top of the file * */ /** * Simplified matching: * Consider this case: ----- File 3.h #ifndef HAD_3 #define HAD_3 int i; #endif ----- File 2.h #include "3.h" int independent; ----- File test_1.h #include "2.h" ----- File test_2.h #include "3.h" #include "2.h" ----- end 2.h and 3.h both depend on the macro HAD_3. In test_2.h, 3.h is included before 3.h, and when 2.h is included in the next line, it needs to be completeley re-parsed, because 2.h depends on the macro HAD_3, and that macro is different(it is set) then when it was parsed in test_1.h. In practice this is very problematic, because it leads to massive multiple parsing of everything, which costs a lot of resources. To solve this, "Simplified matching" can be used(it is enabled in CppLanguageSupport). With simplified matching enabled, every file is always represented by at least 2 parts: One part for all the headers at the top(we will call it header-section), and one part for the real content below the headers. From the header-section, we create a proxy-context, that only stores the environment-matching information, and that imports the next created content-context. The content-context starts right behind the header-context, and its environment-matching information only represents the real content. The content-context can then be re-used many times, as long as the environment matches, while many different proxy-contexts will be created that represent different constellations of macro-dependences across included headers. The downside of this approach: - Many different includes may be added to the content-context, coming from different proxy-contexts. This is not 100% correct visibility-wise. - This only works perfectly if the includes are at the top, within one block. If this is not the case, the behavior will partially become like without simplified matching. The good things: - The general code-completion should be exactly as good as without simplified matching. * */ namespace rpp { class pp_macro; class Environment; } class CppPreprocessEnvironment; namespace Cpp { struct MacroSetRepository : public Utils::BasicSetRepository { MacroSetRepository() : Utils::BasicSetRepository("macro sets") { } virtual void itemRemovedFromSets(uint index) override; }; ///@todo Make string-sets work correctly with IndexedString reference-counting struct KDEVCPPDUCHAIN_EXPORT IndexedStringConversion { KDevelop::IndexedString toItem(uint index) const { return KDevelop::IndexedString::fromIndex(index); } uint toIndex(const KDevelop::IndexedString& str) const { return str.index(); } }; struct KDEVCPPDUCHAIN_EXPORT MacroIndexConversion { const rpp::pp_macro& toItem(uint index) const; uint toIndex(const rpp::pp_macro& _macro) const; }; struct KDEVCPPDUCHAIN_EXPORT StaticStringSetRepository { static Utils::BasicSetRepository* repository(); struct Locker : public QMutexLocker { Locker() : QMutexLocker(repository()->mutex()) { } }; }; struct KDEVCPPDUCHAIN_EXPORT StaticMacroSetRepository { static Utils::BasicSetRepository* repository(); struct Locker : public QMutexLocker { Locker() : QMutexLocker(repository()->mutex()) { } }; }; typedef Utils::StorableSet ReferenceCountedStringSet; typedef Utils::StorableSet ReferenceCountedMacroSet; class EnvironmentManager; class MacroSet; DECLARE_LIST_MEMBER_HASH(EnvironmentFileData, m_includePaths, KDevelop::IndexedString) class EnvironmentFileData : public KDevelop::ParsingEnvironmentFileData { public: - EnvironmentFileData() { - m_contentStartLine = 0; + EnvironmentFileData() + : m_contentStartLine(0) + , m_identityOffset(0) + , m_includePaths(0) + { // m_includeFiles = 0; - m_identityOffset = 0; - m_includePaths = 0; } - EnvironmentFileData(const EnvironmentFileData& rhs) : KDevelop::ParsingEnvironmentFileData(rhs) { - m_url = rhs.m_url; - m_strings = rhs.m_strings; //String-set + EnvironmentFileData(const EnvironmentFileData& rhs) + : KDevelop::ParsingEnvironmentFileData(rhs) + , m_url(rhs.m_url) + , m_strings(rhs.m_strings) //String-set + , m_missingIncludeFiles(rhs.m_missingIncludeFiles) //String-set + , m_usedMacros(rhs.m_usedMacros) //Macro-set + , m_usedMacroNames(rhs.m_usedMacroNames) //String-set + , m_definedMacros(rhs.m_definedMacros) //Macro-set + , m_definedMacroNames(rhs.m_definedMacroNames) //String-set + , m_unDefinedMacroNames(rhs.m_unDefinedMacroNames) //String-set + , m_contentStartLine(rhs.m_contentStartLine) + , m_topContext(rhs.m_topContext) + , m_identityOffset(rhs.m_identityOffset) + , m_includePaths(rhs.m_includePaths) + , m_guard(rhs.m_guard) + , m_includePathDependencies(rhs.m_includePathDependencies) + { // m_includeFiles = rhs.m_includeFiles; //String-set - m_missingIncludeFiles = rhs.m_missingIncludeFiles; //String-set - m_usedMacros = rhs.m_usedMacros; //Macro-set - m_usedMacroNames = rhs.m_usedMacroNames; //String-set - m_definedMacros = rhs.m_definedMacros; //Macro-set - m_definedMacroNames = rhs.m_definedMacroNames; //String-set - m_unDefinedMacroNames = rhs.m_unDefinedMacroNames; //String-set - m_contentStartLine = rhs.m_contentStartLine; - m_topContext = rhs.m_topContext; - m_identityOffset = rhs.m_identityOffset; - m_includePaths = rhs.m_includePaths; - m_guard = rhs.m_guard; - m_includePathDependencies = rhs.m_includePathDependencies; } ~EnvironmentFileData() { } uint m_identityOffset; //All the following sets get their reference-count increased whenever put in here //Set of all strings that can be affected by macros from outside ReferenceCountedStringSet m_strings; ReferenceCountedStringSet m_missingIncludeFiles; ReferenceCountedMacroSet m_usedMacros; ReferenceCountedStringSet m_usedMacroNames; ReferenceCountedMacroSet m_definedMacros; ReferenceCountedStringSet m_definedMacroNames; ReferenceCountedStringSet m_unDefinedMacroNames; uint m_includePaths; //Index in the internal include-paths repository int m_contentStartLine; //Name of the header-guard macro that protects this file KDevelop::IndexedString m_guard; KDevelop::ModificationRevisionSet m_includePathDependencies; }; class KDEVCPPDUCHAIN_EXPORT EnvironmentFile : public KDevelop::ParsingEnvironmentFile { public: ///@todo Respect changing include-paths: Check if the included files are still the same(maybe new files are found that were not found before) EnvironmentFile( const KDevelop::IndexedString& url, KDevelop::TopDUContext* topContext ); EnvironmentFile( EnvironmentFileData& data ); ~EnvironmentFile(); void addStrings( const std::set& strings ); ///If there previously was a macro defined of the same name, it must be given through previousOfSameName, else it can be zero. void addDefinedMacro( const rpp::pp_macro& macro, const rpp::pp_macro& previousOfSameName ); ///the given macro will only make it into usedMacros() if it was not defined in this file void usingMacro( const rpp::pp_macro& macro ); void addIncludeFile( const KDevelop::IndexedString& file, const KDevelop::ModificationRevision& modificationTime ); ///Returns the set of all strings that can affect this file from outside. const ReferenceCountedStringSet& strings() const; ///The parameter should be a EnvironmentFile that was processed AFTER the content of this file ///@param file The file to merge ///@warning The file must _not_ be merged yet into the environment when this is called. Also, /// after merging the environment-files a file cannot be merged into the environment any more, /// so this should only be used indirectly through CppPreprocessEnvironment::merge void merge( const EnvironmentFile& file ); bool operator < ( const EnvironmentFile& rhs ) const { return url() < rhs.url(); } size_t hash() const; /**Set of all files with absolute paths, including those included indirectly * * This by definition also includes this file, so when the count is 1, * no other files were included. * * */ //const IndexedStringSet& includeFiles() const; void addMissingIncludeFile(const KDevelop::IndexedString& file); const ReferenceCountedStringSet& missingIncludeFiles() const; void clearMissingIncludeFiles(); KDevelop::IndexedString headerGuard() const; void setHeaderGuard( KDevelop::IndexedString guardName ); ///Set of all defined macros, including those of all deeper included files const ReferenceCountedMacroSet& definedMacros() const; ///Set of all macros used from outside, including those used in deeper included files const ReferenceCountedMacroSet& usedMacros() const; const ReferenceCountedStringSet& usedMacroNames() const; const ReferenceCountedStringSet& definedMacroNames() const; ///Set of all macros undefined to the outside const ReferenceCountedStringSet& unDefinedMacroNames() const; ///Should return the include-paths that were used while parsing this file(as used/found in CppLanguageSupport) const QList includePaths() const; void setIncludePaths( const QList& paths ); ///Set the first line of actual content, behind includes etc. void setContentStartLine(int line); int contentStartLine() const; /** * The identity-value usually only depends on the content of the environment-information. This can be used to separate environments that have the same content. * For example a content-environment from a proxy-environment. * */ void setIdentityOffset(uint offset); uint identityOffset() const; virtual bool matchEnvironment(const KDevelop::ParsingEnvironment* environment) const override; virtual bool needsUpdate(const KDevelop::ParsingEnvironment* environment = 0) const override; const KDevelop::ModificationRevisionSet& includePathDependencies() const; void setIncludePathDependencies(const KDevelop::ModificationRevisionSet&); enum { Identity = 73 }; private: virtual int type() const override; friend class EnvironmentManager; DUCHAIN_DECLARE_DATA(EnvironmentFile) /* Needed data: 1. Set of all strings that appear in this file(For memory-reasons they should be taken from a global string-repository, because many will be the same) 2. Set of all macros that were defined outside of, but affected the file Algorithm: Iterate over all available macros, and check whether they affect the file. If it does, make sure that the macro is in the macro-set and has the same body. If the check fails: We need to reparse. */ }; typedef QExplicitlySharedDataPointer EnvironmentFilePointer; class KDEVCPPDUCHAIN_EXPORT EnvironmentManager { public: static EnvironmentManager* self() { Q_ASSERT_X(m_self, "EnvironmentManager::self()", "call EnvironmentManager::init() before ::self()"); return m_self; } /** * Initialize the static EnvironmentManager */ static void init(); MacroDataRepository& macroDataRepository() { return m_macroDataRepository; } //Set-repository that contains the string-sets Utils::StringSetRepository& stringSetRepository() { return m_stringSetRepository; } //Set-repository that contains the macro-sets MacroSetRepository& macroSetRepository() { return m_macroSetRepository; } ///See the comment about simplified matching at the top void setSimplifiedMatching(bool simplified); bool isSimplifiedMatching() const { return m_simplifiedMatching; } enum MatchingLevel { IgnoreGuardsForImporting = 1, Disabled = IgnoreGuardsForImporting | (1<<5), Naive = IgnoreGuardsForImporting | (1<<6), Full = 1 << 7 }; bool ignoreGuardsForImporting() const { return matchingLevel() & IgnoreGuardsForImporting; } void setMatchingLevel(MatchingLevel level); MatchingLevel matchingLevel() const { return m_matchingLevel; } private: EnvironmentManager(); static EnvironmentManager* m_self; MatchingLevel m_matchingLevel; bool m_simplifiedMatching; //Repository that contains the actual macros, and maps them to indices MacroDataRepository m_macroDataRepository; //Set-repository that contains the string-sets Utils::StringSetRepository m_stringSetRepository; //Set-repository that contains the macro-sets MacroSetRepository m_macroSetRepository; }; } #endif diff --git a/projectmanagers/cmake/parser/cmakeast.cpp b/projectmanagers/cmake/parser/cmakeast.cpp index 013c23e99e..5e29eb3bf0 100644 --- a/projectmanagers/cmake/parser/cmakeast.cpp +++ b/projectmanagers/cmake/parser/cmakeast.cpp @@ -1,3972 +1,3972 @@ /* KDevelop CMake Support * * Copyright 2006 Matt Rogers * Copyright 2007-2009 Aleix Pol * * Some parts of this code are based on CMake * Copyright 2002 Kitware, Inc. Insight Consortium * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakeast.h" #include #include "astfactory.h" #include "cmakelistsparser.h" #include "cmakeparserutils.h" #include "../debug.h" #define CMAKE_REGISTER_AST( klassName, astId ) namespace { \ CMakeAst* Create##klassName() { return new klassName; } \ bool b_##astId = AstFactory::self()->registerAst( QLatin1String( #astId ), Create##klassName ); } QDebug operator<<(QDebug dbg, const CMakeFunctionDesc &func) { dbg.nospace() << func.name << "(" << func.arguments << ")"; return dbg.space(); } QDebug operator<<(QDebug dbg, const CMakeFunctionArgument &arg) { dbg.nospace() << arg.value; return dbg.space(); } CMAKE_REGISTER_AST( AddDefinitionsAst, add_definitions ) CMAKE_REGISTER_AST( AddDependenciesAst, add_dependencies ) CMAKE_REGISTER_AST( AddExecutableAst, add_executable ) CMAKE_REGISTER_AST( AddLibraryAst, add_library ) CMAKE_REGISTER_AST( AddSubdirectoryAst, add_subdirectory ) CMAKE_REGISTER_AST( AddTestAst, add_test ) CMAKE_REGISTER_AST( AuxSourceDirectoryAst, aux_source_directory ) CMAKE_REGISTER_AST( BreakAst, break) CMAKE_REGISTER_AST( BuildCommandAst, build_command ) CMAKE_REGISTER_AST( BuildNameAst, build_name ) CMAKE_REGISTER_AST( CMakeMinimumRequiredAst, cmake_minimum_required ) CMAKE_REGISTER_AST( CMakePolicyAst, cmake_policy) CMAKE_REGISTER_AST( ConfigureFileAst, configure_file ) CMAKE_REGISTER_AST( CreateTestSourcelistAst, create_test_sourcelist ) CMAKE_REGISTER_AST( CustomCommandAst, add_custom_command ) CMAKE_REGISTER_AST( CustomTargetAst, add_custom_target ) CMAKE_REGISTER_AST( EnableLanguageAst, enable_language ) CMAKE_REGISTER_AST( EnableTestingAst, enable_testing ) CMAKE_REGISTER_AST( ExecProgramAst, exec_program ) CMAKE_REGISTER_AST( ExecuteProcessAst, execute_process ) CMAKE_REGISTER_AST( ExportAst, export) CMAKE_REGISTER_AST( ExportLibraryDepsAst, export_library_dependencies) CMAKE_REGISTER_AST( FileAst, file ) CMAKE_REGISTER_AST( FindFileAst, find_file ) CMAKE_REGISTER_AST( FindLibraryAst, find_library ) CMAKE_REGISTER_AST( FindPackageAst, find_package ) CMAKE_REGISTER_AST( FindPathAst, find_path ) CMAKE_REGISTER_AST( FindProgramAst, find_program ) CMAKE_REGISTER_AST( ForeachAst, foreach ) CMAKE_REGISTER_AST( FunctionAst, function ) CMAKE_REGISTER_AST( GetCMakePropertyAst, get_cmake_property ) CMAKE_REGISTER_AST( GetDirPropertyAst, get_directory_property ) CMAKE_REGISTER_AST( GetPropertyAst, get_property ) CMAKE_REGISTER_AST( GetSourceFilePropAst, get_source_file_property ) CMAKE_REGISTER_AST( GetTargetPropAst, get_target_property ) CMAKE_REGISTER_AST( GetTestPropAst, get_test_property ) CMAKE_REGISTER_AST( GetFilenameComponentAst, get_filename_component ) CMAKE_REGISTER_AST( IfAst, if ) CMAKE_REGISTER_AST( IncludeAst, include ) CMAKE_REGISTER_AST( IncludeDirectoriesAst, include_directories ) CMAKE_REGISTER_AST( IncludeRegularExpressionAst, include_regular_expression ) CMAKE_REGISTER_AST( InstallFilesAst, install_files ) CMAKE_REGISTER_AST( InstallProgramsAst, install_programs ) CMAKE_REGISTER_AST( InstallTargetsAst, install_targets ) CMAKE_REGISTER_AST( LinkDirectoriesAst, link_directories ) CMAKE_REGISTER_AST( LinkLibrariesAst, link_libraries ) CMAKE_REGISTER_AST( ListAst, list ) CMAKE_REGISTER_AST( LoadCacheAst, load_cache ) CMAKE_REGISTER_AST( LoadCommandAst, load_command ) CMAKE_REGISTER_AST( MacroAst, macro ) CMAKE_REGISTER_AST( MarkAsAdvancedAst, mark_as_advanced ) CMAKE_REGISTER_AST( MakeDirectoryAst, make_directory ) CMAKE_REGISTER_AST( MathAst, math ) CMAKE_REGISTER_AST( MessageAst, message ) CMAKE_REGISTER_AST( OptionAst, option ) CMAKE_REGISTER_AST( OutputRequiredFilesAst, output_required_files ) CMAKE_REGISTER_AST( ProjectAst, project ) CMAKE_REGISTER_AST( RemoveAst, remove ) CMAKE_REGISTER_AST( ReturnAst, return ) CMAKE_REGISTER_AST( RemoveDefinitionsAst, remove_definitions ) CMAKE_REGISTER_AST( SetAst, set ) CMAKE_REGISTER_AST( SetDirectoryPropsAst, set_directory_properties ) CMAKE_REGISTER_AST( SetSourceFilesPropsAst, set_source_files_properties ) CMAKE_REGISTER_AST( SetTargetPropsAst, set_target_properties ) CMAKE_REGISTER_AST( SetTestsPropsAst, set_tests_properties ) CMAKE_REGISTER_AST( SetPropertyAst, set_property ) CMAKE_REGISTER_AST( SourceGroupAst, source_group ) CMAKE_REGISTER_AST( SeparateArgumentsAst, separate_arguments ) CMAKE_REGISTER_AST( SiteNameAst, site_name ) CMAKE_REGISTER_AST( StringAst, string ) CMAKE_REGISTER_AST( SubdirsAst, subdirs ) CMAKE_REGISTER_AST( SubdirDependsAst, subdir_depends ) CMAKE_REGISTER_AST( TargetIncludeDirectoriesAst, target_include_directories) CMAKE_REGISTER_AST( TargetLinkLibrariesAst, target_link_libraries) CMAKE_REGISTER_AST( TryCompileAst, try_compile ) CMAKE_REGISTER_AST( TryRunAst, try_run ) CMAKE_REGISTER_AST( UseMangledMesaAst, use_mangled_mesa ) CMAKE_REGISTER_AST( UtilitySourceAst, utility_source ) CMAKE_REGISTER_AST( UnsetAst, unset ) CMAKE_REGISTER_AST( VariableRequiresAst, variable_requires ) CMAKE_REGISTER_AST( WhileAst, while) CMAKE_REGISTER_AST( WriteFileAst, write_file) #undef CMAKE_REGISTER_AST enum Stage {NAMES, PATHS, PATH_SUFFIXES, HINTS}; CustomCommandAst::CustomCommandAst() + : m_isForTarget(false) //only used here? :S + , m_buildStage(PostBuild) + , m_isVerbatim(false) + , m_append(false) { - m_isForTarget = false; //only used here? :S - m_buildStage = PostBuild; - m_isVerbatim = false; - m_append = false; } CustomCommandAst::~CustomCommandAst() { } bool CustomCommandAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name.toLower() != QLatin1String( "add_custom_command" ) ) return false; if (func.arguments.size() < 4) return false; enum tdoing { doing_source, doing_command, doing_target, doing_depends, doing_main_dependency, doing_output, doing_outputs, doing_comment, doing_working_directory, doing_nothing }; tdoing doing = doing_nothing; QString currentLine; QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin(); it != itEnd; ++it) { QString copy = it->value; if(copy == "SOURCE") doing = doing_source; else if(copy == "COMMAND") { doing = doing_command; // Save the current command before starting the next command. if ( !currentLine.isEmpty() ) { m_commands.append( currentLine ); currentLine.clear(); } } else if(copy == "PRE_BUILD") m_buildStage = PreBuild; else if(copy == "PRE_LINK") m_buildStage = PreLink; else if(copy == "POST_BUILD") m_buildStage = PostBuild; else if(copy == "VERBATIM") m_isVerbatim = true; else if(copy == "APPEND") m_append = true; else if(copy == "TARGET") doing = doing_target; else if(copy == "ARGS") // Ignore this old keyword. ; else if (copy == "DEPENDS") doing = doing_depends; else if (copy == "OUTPUTS") doing = doing_outputs; else if (copy == "OUTPUT") doing = doing_output; else if (copy == "WORKING_DIRECTORY") doing = doing_working_directory; else if (copy == "MAIN_DEPENDENCY") doing = doing_main_dependency; else if (copy == "COMMENT") doing = doing_comment; else { switch (doing) { case doing_working_directory: m_workingDirectory = copy; break; case doing_source: m_source = copy; break; case doing_main_dependency: m_mainDependency = copy; break; case doing_command: m_commands.append( copy ); break; case doing_target: m_targetName = copy; break; case doing_depends: m_otherDependencies.append( copy ); break; case doing_outputs: case doing_output: m_outputs.append(copy); break; case doing_comment: m_comment = copy; break; default: return false; } } } // Store the last command line finished. if ( !currentLine.isEmpty() ) { m_commands.append( currentLine ); currentLine.clear(); } // At this point we could complain about the lack of arguments. For // the moment, let's say that COMMAND, TARGET are always required. if ( m_outputs.isEmpty() && m_targetName.isEmpty() ) return false; if ( m_source.isEmpty() && !m_targetName.isEmpty() && !m_outputs.isEmpty()) return false; if ( m_append && m_outputs.isEmpty() ) return false; return true; } CustomTargetAst::CustomTargetAst() { m_buildAlways = false; m_isVerbatim = false; } CustomTargetAst::~CustomTargetAst() { } bool CustomTargetAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name.toLower() != QLatin1String( "add_custom_target" ) ) return false; //make sure we have at least one argument if ( func.arguments.size() < 1 ) return false; //check and make sure the target name isn't something silly CMakeFunctionArgument arg = func.arguments.front(); if ( arg.value=="ALL" ) return false; else m_target = arg.value; //check if we're part of the special "all" target if(func.arguments.count()>1) { CMakeFunctionArgument arg2 = func.arguments[1]; m_buildAlways = arg2.value == "ALL"; } //what are we doing? enum Action { ParsingCommand, ParsingDep, ParsingWorkingDir, ParsingComment, ParsingVerbatim, ParsingSources }; //command should be first QString currentLine; Action act = ParsingCommand; QList::const_iterator it, itEnd = func.arguments.end(); it = func.arguments.begin(); if(m_buildAlways) it+=2; else ++it; QString currCmd; for ( ; it != itEnd; ++it ) { QString arg = it->value; if ( arg == "DEPENDS" ) act = ParsingDep; else if ( arg == "WORKING_DIRECTORY" ) act = ParsingWorkingDir; else if ( arg == "VERBATIM" ) { m_isVerbatim = true; act = ParsingVerbatim; } else if ( arg == "COMMENT" ) act = ParsingComment; else if ( arg == "COMMAND" ) { currCmd.clear(); act = ParsingCommand; } else if ( arg == "SOURCES" ) act = ParsingSources; else { switch( act ) { case ParsingCommand: if(m_commandArgs.contains(currCmd)) m_commandArgs[currCmd].append(arg); else { currCmd=arg; m_commandArgs.insert(arg, QStringList()); } break; case ParsingDep: m_dependencies.append( arg ); break; case ParsingWorkingDir: m_workingDir = arg; break; case ParsingComment: m_comment += arg; break; case ParsingSources: m_sourceLists.append( arg ); break; default: return false; } } } //check for bogus characters in the target name if ( m_target.indexOf( QRegExp( "(#|<|>)" ) ) != -1 ) return false; return true; } /* Add Definitions AST */ AddDefinitionsAst::AddDefinitionsAst() { } AddDefinitionsAst::~AddDefinitionsAst() { } bool AddDefinitionsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_definitions" ) return false; if ( func.arguments.isEmpty() ) return false; foreach( const CMakeFunctionArgument& arg, func.arguments ) { m_definitions << arg.value; } return true; } /* Add Dependencies AST */ AddDependenciesAst::AddDependenciesAst() { } AddDependenciesAst::~AddDependenciesAst() { } bool AddDependenciesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_dependencies" ) return false; if ( func.arguments.size() < 2 ) return false; QList args = func.arguments; m_target = args.front().value; QList::const_iterator it, itEnd = args.constEnd(); it = args.constBegin() + 1; //skip the first argument since it's the target for ( ; it != itEnd; ++it ) { m_dependencies << it->value; } return true; } AddExecutableAst::AddExecutableAst() { m_isWin32 = false; m_isOsXBundle = false; m_excludeFromAll = false; m_isImported = false; } AddExecutableAst::~AddExecutableAst() { } bool AddExecutableAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_executable" ) return false; if ( func.arguments.size() < 2 ) return false; QList args = func.arguments; QList::const_iterator it, itEnd = args.constEnd(); it = args.constBegin(); m_executable = it->value; ++it; for ( ; it != itEnd; ++it ) { if ( it->value == "WIN32" ) m_isWin32 = true; else if ( it->value == "MACOSX_BUNDLE" ) m_isOsXBundle = true; else if ( it->value == "EXCLUDE_FROM_ALL" ) m_excludeFromAll = true; else if ( it->value == "IMPORTED") m_isImported = true; else m_sourceLists.append( it->value ); } if(!m_isImported && m_sourceLists.isEmpty()) return false; return true; } QMap AddLibraryAst::s_typeForName; AddLibraryAst::AddLibraryAst() { if(s_typeForName.isEmpty()) { s_typeForName.insert("STATIC", Static); s_typeForName.insert("SHARED", Shared); s_typeForName.insert("MODULE", Module); s_typeForName.insert("OBJECT", Object); s_typeForName.insert("UNKNOWN", Unknown); } m_type = Static; m_isImported = false; m_excludeFromAll = false; m_isAlias = false; } AddLibraryAst::~AddLibraryAst() { } bool AddLibraryAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_library" || func.arguments.isEmpty() ) return false; bool libTypeSet = false; QList args = func.arguments; QList::const_iterator it, itEnd = args.constEnd(); it = args.constBegin(); m_libraryName = it->value; ++it; for(; it != itEnd;) { if ( !libTypeSet && s_typeForName.contains(it->value) ) { m_type = s_typeForName.value(it->value); libTypeSet = true; ++it; } else if ( it->value == "IMPORTED") { m_isImported = true; ++it; } else if ( it->value == "EXCLUDE_FROM_ALL" ) { m_excludeFromAll = true; ++it; } else if ( it->value == "ALIAS") { m_isAlias = true; ++it; if(it==itEnd) return false; m_aliasTarget = it->value; } else break; } if ( !m_isImported && !m_isAlias) { while ( it != itEnd ) { m_sourceLists.append( it->value ); ++it; } if ( m_sourceLists.isEmpty() ) return false; } return true; } AddSubdirectoryAst::AddSubdirectoryAst() { } AddSubdirectoryAst::~AddSubdirectoryAst() { } bool AddSubdirectoryAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_subdirectory" ) return false; if ( func.arguments.size() < 1 || func.arguments[0].value.isEmpty()) return false; m_sourceDir = func.arguments[0].value; QList::const_iterator it, itEnd = func.arguments.constEnd(); it = ++func.arguments.constBegin(); for ( ; it != itEnd; ++it ) { if ( it->value == "EXCLUDE_FROM_ALL" ) m_excludeFromAll = true; else if ( m_binaryDir.isEmpty() ) m_binaryDir = it->value; else return false; //invalid num of args } return true; } AddTestAst::AddTestAst() { } AddTestAst::~AddTestAst() { } bool AddTestAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "add_test" ) return false; if ( func.arguments.size() < 2 ) return false; QList::const_iterator it, itEnd = func.arguments.constEnd(); it = func.arguments.constBegin(); enum {Name, Command, Arg, Unsupported} state = Unsupported; if (it->value != "NAME") { m_testName = (it++)->value; m_exeName = (it++)->value; state = Arg; } for ( ; it != itEnd; ++it ) { if ( it->value == "NAME" ) state = Name; else if ( it->value == "COMMAND" ) state = Command; else if ( it->value == "CONFIGURATIONS" || it->value == "WORKING_DIRECTORY" ) state = Unsupported; else switch (state) { case Name: m_testName = it->value; break; case Command: m_exeName = it->value; state = Arg; break; case Arg: m_testArgs << it->value; break; default: break; } } return !m_exeName.isEmpty(); } AuxSourceDirectoryAst::AuxSourceDirectoryAst() { } AuxSourceDirectoryAst::~AuxSourceDirectoryAst() { } bool AuxSourceDirectoryAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "aux_source_directory" ) return false; if ( func.arguments.size() != 2 ) return false; m_dirName = func.arguments[0].value; m_variableName = func.arguments[1].value; addOutputArgument(func.arguments[1].value); return true; } BuildCommandAst::BuildCommandAst() { } BuildCommandAst::~BuildCommandAst() { } bool BuildCommandAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "build_command" ) return false; if ( func.arguments.size() < 2 ) return false; m_variableName = func.arguments[0].value; m_makeCommand = func.arguments[1].value; return true; } BuildNameAst::BuildNameAst() { } BuildNameAst::~BuildNameAst() { } bool BuildNameAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "build_name" ) return false; if ( func.arguments.size() != 1 ) return false; m_buildName = func.arguments[0].value; addOutputArgument(func.arguments[0].value); return true; } CMakeMinimumRequiredAst::CMakeMinimumRequiredAst() : m_wrongVersionIsFatal(false) { } CMakeMinimumRequiredAst::~CMakeMinimumRequiredAst() { } bool CMakeMinimumRequiredAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "cmake_minimum_required" ) return false; if ( func.arguments.size() < 2 || func.arguments.count() > 3 || func.arguments.first().value != "VERSION") return false; bool correct = false; m_version = CMakeParserUtils::parseVersion(func.arguments[1].value, &correct); if (!correct) return false; if(func.arguments.count()==3) { if(func.arguments[2].value=="FATAL_ERROR") m_wrongVersionIsFatal = true; else return false; } return true; } ConfigureFileAst::ConfigureFileAst() : m_copyOnly(false) , m_escapeQuotes(false) , m_atsOnly(false) , m_immediate(false) { } ConfigureFileAst::~ConfigureFileAst() { } bool ConfigureFileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "configure_file" ) return false; if ( func.arguments.size() < 2 ) return false; m_inputFile = func.arguments[0].value; m_outputFile = func.arguments[1].value; QList::const_iterator it, itEnd = func.arguments.constEnd(); it = func.arguments.constBegin() + 2; for ( ; it != itEnd; ++it ) { CMakeFunctionArgument arg = ( *it ); if ( arg.value == "COPYONLY" ) m_copyOnly = true; else if ( arg.value == "ESCAPE_QUOTES" ) m_escapeQuotes = true; else if ( arg.value == "@ONLY" ) m_atsOnly = true; else if ( arg.value == "IMMEDIATE" ) m_immediate = true; } return true; } CreateTestSourcelistAst::CreateTestSourcelistAst() { } CreateTestSourcelistAst::~CreateTestSourcelistAst() { } bool CreateTestSourcelistAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "create_test_sourcelist" ) return false; if ( func.arguments.count() < 3 ) return false; addOutputArgument(func.arguments[0]); m_name=func.arguments[0].value; m_driverName=func.arguments[1].value; QList::const_iterator it, itEnd = func.arguments.constEnd(); it = func.arguments.constBegin() + 2; enum State { Tests, ExtraInclude, Function}; State s=Tests; for(; it!=itEnd; ++it) { if(it->value=="EXTRA_INCLUDE") s=ExtraInclude; else if(it->value=="FUNCTION") s=Function; else switch(s) { case Tests: m_tests.append(it->value); break; case ExtraInclude: m_extraIncludes.append(it->value); s=Tests; break; case Function: m_function.append(it->value); s=Tests; break; } } return !m_tests.isEmpty(); } EnableLanguageAst::EnableLanguageAst() { } EnableLanguageAst::~EnableLanguageAst() { } bool EnableLanguageAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "enable_language" ) return false; if ( func.arguments.isEmpty() || func.arguments.count() != 1 ) return false; if ( func.arguments[0].value.isEmpty() ) return false; m_language = func.arguments[0].value; return true; } EnableTestingAst::EnableTestingAst() { } EnableTestingAst::~EnableTestingAst() { } bool EnableTestingAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { return func.name.toLower() == "enable_testing" && func.arguments.isEmpty(); } ExecProgramAst::ExecProgramAst() { } ExecProgramAst::~ExecProgramAst() { } bool ExecProgramAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name != "exec_program" || func.arguments.count() == 0 ) return false; m_executableName = func.arguments[0].value; bool args=false; QList::const_iterator it=func.arguments.constBegin(), itEnd=func.arguments.constEnd(); // don't re-read the first element ++it; for(; it!=itEnd; ++it) { if(it->value=="OUTPUT_VARIABLE") { ++it; if(it!=itEnd) { addOutputArgument(*it); m_outputVariable = it->value; } else return false; } else if(it->value=="RETURN_VALUE") { ++it; if(it!=itEnd) { addOutputArgument(*it); m_returnValue = it->value; } else return false; } else if(it->value=="ARGS") { args=true; } else if(args) { m_arguments += it->value; } else m_workingDirectory = it->value; } return true; } ExecuteProcessAst::ExecuteProcessAst() : m_timeout(0.f), m_isOutputQuiet(false), m_isErrorQuiet(false), m_isOutputStrip(false), m_isErrorStrip(false) { } ExecuteProcessAst::~ExecuteProcessAst() { } bool ExecuteProcessAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name != "execute_process" || func.arguments.count()<2) return false; enum Action { None, Cmd, WorkDir, Timeout, ResultVar, OutputVar, ErrorVar, InputFile, OutputFile, ErrorFile }; Action act=None; foreach(const CMakeFunctionArgument &a, func.arguments) { QString val=a.value.toLower(); Action actAnt=act; if(val=="command") { m_commands.append(QStringList()); act=Cmd; } else if(val=="working_directory") act=WorkDir; else if(val=="timeout") act=Timeout; else if(val=="result_variable") act=ResultVar; else if(val=="output_variable") act=OutputVar; else if(val=="error_variable") act=ErrorVar; else if(val=="input_file") act=InputFile; else if(val=="output_file") act=OutputFile; else if(val=="error_file") act=ErrorFile; else if(val=="output_quiet") { m_isOutputQuiet=true; act=None; } else if(val=="error_quiet") { m_isErrorQuiet=true; act=None; } else if(val=="output_strip_trailing_whitespace") { m_isOutputStrip=true; act=None; } else if(val=="error_strip_trailing_whitespace") { m_isErrorStrip=true; act=None; } if(act!=actAnt) val.clear(); switch(act) { case None: break; case Cmd: if(!val.isEmpty()) m_commands.last().append(a.value); break; case WorkDir: m_workingDirectory=a.value; break; case Timeout: m_timeout=val.toFloat(); break; case ResultVar: addOutputArgument(a); m_resultVariable=a.value; break; case OutputVar: addOutputArgument(a); m_outputVariable=a.value; break; case ErrorVar: addOutputArgument(a); m_errorVariable=a.value; break; case InputFile: m_inputFile=a.value; break; case OutputFile: m_outputFile=a.value; break; case ErrorFile: m_errorFile=a.value; break; } } return !m_commands.isEmpty(); } ExportLibraryDepsAst::ExportLibraryDepsAst() : m_append(false) { } ExportLibraryDepsAst::~ExportLibraryDepsAst() { } bool ExportLibraryDepsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name != "export_library_dependencies" || func.arguments.isEmpty()) return false; m_file=func.arguments[0].value; if(func.arguments.count()>=2) { if(func.arguments[1].value=="APPEND") { m_append=true; } if(func.arguments.count()>(1+m_append)) return false; } return true; } FileAst::FileAst() : m_type(Write) , m_isFollowingSymlinks(false) , m_newlineConsume(false) , m_noHexConversion(false) { } FileAst::~FileAst() { } bool FileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "file" || func.arguments.count()<2) return false; QString type = func.arguments.first().value; int min_args=-1; if(type=="WRITE") { m_type = Write; min_args=3; } else if(type=="APPEND") { m_type = Append; min_args=3; } else if(type=="READ") { m_type = Read; min_args=3; } else if(type=="GLOB") { m_type = Glob; min_args=3; } else if(type=="GLOB_RECURSE") { m_type = GlobRecurse; min_args = 3; } else if(type=="REMOVE") { m_type = Remove; min_args=2; } else if(type=="REMOVE_RECURSE") { m_type = RemoveRecurse; min_args=2; } else if(type=="MAKE_DIRECTORY") { m_type = MakeDirectory; min_args=2; } else if(type=="RELATIVE_PATH") { m_type = RelativePath; min_args=4; } else if(type=="TO_CMAKE_PATH") { m_type = ToCmakePath; min_args=3; } else if(type=="TO_NATIVE_PATH") { m_type = ToNativePath; min_args=3; } else if(type=="STRINGS") { m_type = Strings; min_args=3; } else if(type=="DOWNLOADS") { m_type = Download; min_args=3; } else return false; if(func.arguments.count()::const_iterator it, itEnd; switch(m_type) { case Write: case Append: m_path = func.arguments[1].value; m_message = func.arguments[2].value; break; case Read: m_path=func.arguments[1].value; m_variable = func.arguments[2].value; addOutputArgument(func.arguments[2]); break; case Glob: addOutputArgument(func.arguments[1]); m_variable = func.arguments[1].value; it=func.arguments.constBegin()+2; itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { if(it->value=="RELATIVE") { ++it; if(it==itEnd) return false; else m_path = it->value; } else m_globbingExpressions << it->value; } break; case GlobRecurse: addOutputArgument(func.arguments[1]); m_variable = func.arguments[1].value; m_isFollowingSymlinks = false; it=func.arguments.constBegin()+2; itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { if(it->value=="RELATIVE") { ++it; if(it==itEnd) return false; else m_path = it->value; } else if(it->value=="FOLLOW_SYMLINKS") { m_isFollowingSymlinks = true; } else m_globbingExpressions << it->value; } break; case Remove: case RemoveRecurse: case MakeDirectory: it=func.arguments.constBegin()+1; itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) m_directories << it->value; break; case RelativePath: addOutputArgument(func.arguments[1]); m_variable = func.arguments[1].value; m_directory = func.arguments[2].value; m_path = func.arguments[3].value; break; case ToCmakePath: case ToNativePath: addOutputArgument(func.arguments[2]); m_path = func.arguments[1].value; m_variable = func.arguments[2].value; break; case Download: m_url=func.arguments[1].value; m_path=func.arguments[2].value; it=func.arguments.constBegin()+3; itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { if(it->value=="STATUS") { ++it; if(it==itEnd) break; m_variable = it->value; } else if(it->value=="LOG") { ++it; if(it==itEnd) break; m_message = it->value; } } break; case Strings: m_path=func.arguments[1].value; m_variable=func.arguments[2].value; it=func.arguments.constBegin()+3; itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { bool corr; if(it->value=="LIMIT_COUNT") { ++it; if(it==itEnd) break; m_limitCount = it->value.toInt(&corr); if(!corr) return false; } else if(it->value=="LIMIT_INPUT") { ++it; if(it==itEnd) break; m_limitInput = it->value.toInt(&corr); if(!corr) return false; } else if(it->value=="LIMIT_OUTPUT") { ++it; if(it==itEnd) break; m_limitOutput = it->value.toInt(&corr); if(!corr) return false; } else if(it->value=="LENGTH_MINIMUM") { ++it; if(it==itEnd) break; m_lengthMinimum = it->value.toInt(&corr); if(!corr) return false; } else if(it->value=="LENGTH_MAXIMUM") { ++it; if(it==itEnd) break; m_lengthMaximum = it->value.toInt(&corr); if(!corr) return false; } else if(it->value=="REGEX") { ++it; if(it==itEnd) break; m_regex = it->value; } else if(it->value=="NEWLINE_CONSUME") { m_newlineConsume=true; } else if(it->value=="NO_HEX_CONVERSION") { m_noHexConversion=true; } } break; } return true; } FindFileAst::FindFileAst() : m_noDefaultPath(false) , m_noCmakeEnvironmentPath(false) , m_noCmakePath(false) , m_noSystemEnvironmentPath(false) , m_noCmakeSystemPath(false) { } FindFileAst::~FindFileAst() { } bool FindFileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="find_file" || func.arguments.count()<3) return false; bool definedNames=false; addOutputArgument(func.arguments.first()); m_variableName = func.arguments.first().value; Stage s; QList::const_iterator it=func.arguments.constBegin()+1, itEnd=func.arguments.constEnd(); if(it->value=="NAMES") { definedNames = true; s=NAMES; } else { m_filenames=QStringList(it->value); s=PATHS; definedNames = false; } ++it; for(; it!=itEnd; ++it) { if(it->value=="NO_DEFAULT_PATH") m_noDefaultPath = true; else if(it->value=="NO_CMAKE_ENVIRONMENT_PATH") m_noCmakeEnvironmentPath = true; else if(it->value=="NO_CMAKE_PATH") m_noSystemEnvironmentPath = true; else if(it->value=="DOC") { ++it; if(it==itEnd) return false; m_documentation = it->value; } else if(it->value=="PATHS") s=PATHS; else if(it->value=="PATH_SUFFIXES") s=PATH_SUFFIXES; else if(it->value=="HINTS") s=HINTS; else switch(s) { case NAMES: m_filenames << it->value; if(!definedNames) s=PATHS; break; case PATHS: m_path << it->value; break; case PATH_SUFFIXES: m_pathSuffixes << it->value; break; case HINTS: m_hints << it->value; break; } } return !m_filenames.isEmpty(); } MacroCallAst::MacroCallAst() { } MacroCallAst::~MacroCallAst() { } bool MacroCallAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.isEmpty()) return false; m_name = func.name.toLower(); foreach(const CMakeFunctionArgument& fa, func.arguments) { m_arguments += fa.value; } return true; } FindLibraryAst::FindLibraryAst() : m_noDefaultPath(false) , m_noCmakeEnvironmentPath(false) , m_noCmakePath(false) , m_noSystemEnvironmentPath(false) , m_noCmakeSystemPath(false) , m_noCmakeFindRootPath(false) { } FindLibraryAst::~FindLibraryAst() { } bool FindLibraryAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="find_library" || func.arguments.count()<2) return false; bool definedNames=false; addOutputArgument(func.arguments[0]); m_variableName = func.arguments[0].value; Stage s = NAMES; QList::const_iterator it=func.arguments.constBegin()+1, itEnd=func.arguments.constEnd(); if(it->value=="NAMES") { ++it; definedNames = true; } else { m_filenames=QStringList(it->value); ++it; s=PATHS; definedNames = false; } for(; it!=itEnd; ++it) { if(it->value=="NO_DEFAULT_PATH") m_noDefaultPath = true; else if(it->value=="NO_CMAKE_ENVIRONMENT_PATH") m_noCmakeEnvironmentPath = true; else if(it->value=="NO_CMAKE_PATH") m_noSystemEnvironmentPath = true; else if(it->value=="NO_CMAKE_FIND_ROOT_PATH") m_noCmakeFindRootPath = true; else if(it->value=="DOC") { ++it; if(it==itEnd) return false; m_documentation = it->value; } else if(it->value=="PATHS") s=PATHS; else if(it->value=="PATH_SUFFIXES") s=PATH_SUFFIXES; else if(it->value=="HINTS") s=HINTS; else switch(s) { case NAMES: m_filenames << it->value; if(!definedNames) s=PATHS; break; case PATHS: m_path << it->value; break; case PATH_SUFFIXES: m_pathSuffixes << it->value; break; case HINTS: m_hints << it->value; break; } } return !m_filenames.isEmpty(); } FindPackageAst::FindPackageAst() : m_isQuiet(false) , m_noModule(false) , m_isRequired(false) { } FindPackageAst::~FindPackageAst() { } bool FindPackageAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { m_isQuiet=false; m_noModule=false; m_isRequired=false; if ( func.name != "find_package" ) return false; if ( func.arguments.isEmpty() ) return false; m_name = func.arguments[0].value; QList::const_iterator it=func.arguments.constBegin()+1; QList::const_iterator itEnd=func.arguments.constEnd(); bool ret=true; enum State { None, Components, Paths }; State s=None; for(; it!=itEnd; ++it) { if(it->value.isEmpty()) {} else if(it->value[0].isNumber()) m_version=it->value; else if(it->value=="QUIET") m_isQuiet=true; else if(it->value=="NO_MODULE" || it->value=="CONFIG") m_noModule=true; else if(it->value=="REQUIRED") { m_isRequired=true; s=Components; } else if(it->value=="COMPONENTS") s=Components; else if(it->value=="PATHS") s=Paths; else if(s==Components) m_components.append(it->value); else if(s==Paths) m_paths.append(it->value); else { qWarning() << "found error" << it->value; ret=false; } } return ret; } FindPathAst::FindPathAst() : m_noDefaultPath(false) , m_noCmakeEnvironmentPath(false) , m_noCmakePath(false) , m_noSystemEnvironmentPath(false) , m_noCmakeSystemPath(false) { } FindPathAst::~FindPathAst() { } bool FindPathAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="find_path" || func.arguments.count()<2) return false; //FIXME: FIND_PATH(KDE4_DATA_DIR cmake/modules/FindKDE4Internal.cmake ${_data_DIR}) bool definedNames=false; addOutputArgument(func.arguments[0]); m_variableName = func.arguments[0].value; Stage s = NAMES; QList::const_iterator it=func.arguments.constBegin()+1, itEnd=func.arguments.constEnd(); if(it->value=="NAMES") { ++it; definedNames = true; } else { m_filenames=QStringList(it->value); ++it; s=PATHS; definedNames = false; } for(; it!=itEnd; ++it) { if(it->value=="NO_DEFAULT_PATH") m_noDefaultPath = true; else if(it->value=="NO_CMAKE_ENVIRONMENT_PATH") m_noCmakeEnvironmentPath = true; else if(it->value=="NO_CMAKE_PATH") m_noCmakePath = true; else if(it->value=="NO_CMAKE_SYSTEM_PATH") m_noCmakeSystemPath = true; else if(it->value=="NO_SYSTEM_ENVIRONMENT_PATH") m_noSystemEnvironmentPath = true; else if(it->value=="DOC") { ++it; if(it==itEnd) return false; m_documentation = it->value; } else if(it->value=="PATHS") s=PATHS; else if(it->value=="PATH_SUFFIXES") s=PATH_SUFFIXES; else if(it->value=="HINTS") s=HINTS; else switch(s) { case NAMES: m_filenames << it->value; if(!definedNames) s=PATHS; break; case PATHS: m_path << it->value; break; case PATH_SUFFIXES: m_pathSuffixes << it->value; break; case HINTS: m_hints << it->value; break; } } return !m_filenames.isEmpty(); } FindProgramAst::FindProgramAst() : m_noDefaultPath(false) , m_noCmakeEnvironmentPath(false) , m_noCmakePath(false) , m_noSystemEnvironmentPath(false) , m_noCmakeSystemPath(false) , m_noCMakeFindRootPath(false) { } FindProgramAst::~FindProgramAst() { } bool FindProgramAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="find_program" || func.arguments.count()<2) return false; addOutputArgument(func.arguments[0]); m_variableName = func.arguments[0].value; Stage s = NAMES; QList::const_iterator it=func.arguments.constBegin()+1, itEnd=func.arguments.constEnd(); if(it->value=="NAMES") ++it; else { m_filenames=QStringList(it->value); s=PATHS; ++it; } for(; it!=itEnd; ++it) { if(it->value=="NO_DEFAULT_PATH") m_noDefaultPath = true; else if(it->value=="NO_CMAKE_ENVIRONMENT_PATH") m_noCmakeEnvironmentPath = true; else if(it->value=="NO_CMAKE_PATH") m_noCmakePath=true; else if(it->value=="NO_SYSTEM_ENVIRONMENT_PATH") m_noSystemEnvironmentPath = true; else if(it->value=="NO_CMAKE_FIND_ROOT_PATH") m_noCMakeFindRootPath = true; else if(it->value=="DOC") { ++it; if(it==itEnd) return false; m_documentation = it->value; } else if(it->value=="PATHS") s=PATHS; else if(it->value=="PATH_SUFFIXES") s=PATH_SUFFIXES; else if(it->value=="HINTS") s=HINTS; else switch(s) { case NAMES: m_filenames << it->value; break; case PATHS: m_path << it->value; break; case PATH_SUFFIXES: m_pathSuffixes << it->value; break; case HINTS: m_hints << it->value; break; } } return !m_filenames.isEmpty(); } FltkWrapUiAst::FltkWrapUiAst() { } FltkWrapUiAst::~FltkWrapUiAst() { } bool FltkWrapUiAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } ForeachAst::ForeachAst() : m_ranges{} , m_type(Range) { } ForeachAst::~ForeachAst() { } bool ForeachAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="foreach" || func.arguments.count()<1) return false; addOutputArgument(func.arguments.first()); m_loopVar=func.arguments.first().value; if(func.arguments.count()>1 && func.arguments[1].value=="RANGE") { bool correctStart = true, correctStop = true, correctRange = true; m_type=Range; if(func.arguments.count()<3) return false; m_ranges.step = 1; m_ranges.start = 0; if( func.arguments.count() == 3 ) { m_ranges.stop = func.arguments[2].value.toInt(&correctStop); }else { m_ranges.start = func.arguments[2].value.toInt(&correctStart); m_ranges.stop = func.arguments[3].value.toInt(&correctStop); } if(func.arguments.count()==5) m_ranges.step = func.arguments[4].value.toInt(&correctRange); if(!correctStart || !correctStop || !correctRange) return false; } else { int incr; if(func.arguments.count()>1 && func.arguments[1].value=="IN") { if(func.arguments[2].value=="LISTS") { m_type = InLists; } else if(func.arguments[2].value=="ITEMS") { m_type = InItems; } else return false; incr=3; } else { m_type=InItems; incr=1; } QList::const_iterator it=func.arguments.constBegin()+incr, itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { m_arguments += it->value; } } return true; } GetCMakePropertyAst::GetCMakePropertyAst() : m_type(Variables) { } GetCMakePropertyAst::~GetCMakePropertyAst() { } bool GetCMakePropertyAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_cmake_property" || func.arguments.count()!=2) return false; addOutputArgument(func.arguments[0]); m_variableName = func.arguments[0].value; QString type=func.arguments[1].value; if(type=="VARIABLES") m_type=Variables; else if(type=="CACHE_VARIABLES") m_type=CacheVariables; else if(type=="COMMANDS") m_type=Commands; else if(type=="MACROS") m_type=Macros; else if(type=="COMPONENTS") m_type=Components; else return false; return true; } GetDirPropertyAst::GetDirPropertyAst() { } GetDirPropertyAst::~GetDirPropertyAst() { } bool GetDirPropertyAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_directory_property" || (func.arguments.count()!=2 && func.arguments.count()!=4)) return false; addOutputArgument(func.arguments[0]); m_outputVariable = func.arguments[0].value; int next=1; if(func.arguments.count()==4) { if(func.arguments[1].value!="DIRECTORY") return false; m_directory=func.arguments[2].value; next=3; } m_propName=func.arguments[next].value; return true; } GetFilenameComponentAst::GetFilenameComponentAst() : m_type(Path) , m_cache(false) { } GetFilenameComponentAst::~GetFilenameComponentAst() { } bool GetFilenameComponentAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_filename_component" || func.arguments.count()<3) return false; addOutputArgument(func.arguments[0]); m_variableName = func.arguments[0].value; m_fileName = func.arguments[1].value; QString t = func.arguments[2].value; if(t=="PATH") m_type=Path; else if(t=="REALPATH") m_type=RealPath; else if(t=="ABSOLUTE") m_type=Absolute; else if(t=="NAME") m_type=Name; else if(t=="EXT") m_type=Ext; else if(t=="NAME_WE") m_type=NameWe; else if(t=="PROGRAM") m_type=Program; else return false; if(m_type==Program) { //TODO: Did not understand this option } m_cache = func.arguments.last().value=="CACHE"; return true; } GetSourceFilePropAst::GetSourceFilePropAst() { } GetSourceFilePropAst::~GetSourceFilePropAst() { } bool GetSourceFilePropAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_source_file_property" || func.arguments.count()!=3) return false; addOutputArgument(func.arguments[0]); m_variableName=func.arguments[0].value; m_filename=func.arguments[1].value; m_property=func.arguments[2].value; return true; } GetTargetPropAst::GetTargetPropAst() { } GetTargetPropAst::~GetTargetPropAst() { } bool GetTargetPropAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_target_property" || func.arguments.count()!=3) return false; addOutputArgument(func.arguments[0]); m_variableName=func.arguments[0].value; m_target=func.arguments[1].value; m_property=func.arguments[2].value; return true; } GetTestPropAst::GetTestPropAst() { } GetTestPropAst::~GetTestPropAst() { } bool GetTestPropAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_target_property" || func.arguments.count()!=3) return false; addOutputArgument(func.arguments[1]); m_test=func.arguments[0].value; m_variableName=func.arguments[1].value; m_property=func.arguments[2].value; return true; } IfAst::IfAst() { } IfAst::~IfAst() { } bool IfAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="if" && func.name.toLower()!="elseif" && func.name.toLower()!="else") return false; if(func.name.toLower()=="else" && !func.arguments.isEmpty()) return false; m_kind = func.name; m_condition.clear(); foreach(const CMakeFunctionArgument& fa, func.arguments) { m_condition += fa.value; } return true; } IncludeAst::IncludeAst() : m_optional(false) { } IncludeAst::~IncludeAst() { } bool IncludeAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "include" || (func.arguments.isEmpty() || func.arguments.size() > 4)) return false; m_includeFile = func.arguments[0].value; QList::const_iterator it, itEnd; it=func.arguments.constBegin() + 1; itEnd = func.arguments.constEnd(); bool nextIsResult=false; for ( ; it != itEnd; ++it ) { if(nextIsResult) { m_resultVariable=it->value; addOutputArgument( *it ); nextIsResult=false; } else if ( it->value == "OPTIONAL" ) m_optional = true; else if( it->value == "RESULT_VARIABLE" ) nextIsResult=true; } return !m_includeFile.isEmpty(); } IncludeDirectoriesAst::IncludeDirectoriesAst() : m_includeType(Default) , m_isSystem(false) { } IncludeDirectoriesAst::~IncludeDirectoriesAst() { } bool IncludeDirectoriesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "include_directories" || func.arguments.isEmpty() ) return false; int i=0; m_includeType = Default; m_isSystem = false; if(func.arguments.first().value=="AFTER") { m_includeType = After; i++; } else if(func.arguments.first().value=="BEFORE") { m_includeType = Before; i++; } if(i::const_iterator it=func.arguments.constBegin() + i; QList::const_iterator itEnd = func.arguments.constEnd(); for ( ; it != itEnd; ++it ) m_includedDirectories.append(it->value); return true; } IncludeExternalMsProjectAst::IncludeExternalMsProjectAst() { } IncludeExternalMsProjectAst::~IncludeExternalMsProjectAst() { } bool IncludeExternalMsProjectAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } IncludeRegularExpressionAst::IncludeRegularExpressionAst() { } IncludeRegularExpressionAst::~IncludeRegularExpressionAst() { } bool IncludeRegularExpressionAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "include_regular_expression" || func.arguments.isEmpty() || func.arguments.count()>2 ) return false; m_match=func.arguments[0].value; if(func.arguments.count()==2) m_complain=func.arguments[1].value; return true; } InstallAst::InstallAst() { } InstallAst::~InstallAst() { } bool InstallAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } InstallFilesAst::InstallFilesAst() { } InstallFilesAst::~InstallFilesAst() { } bool InstallFilesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()=="install_files" || func.arguments.count()<2) return false; m_directory=func.arguments[0].value; if(func.arguments.count()==2) { m_regex=func.arguments[1].value; } else { QList::const_iterator it, itEnd=func.arguments.constEnd(); if(func.arguments[1].value!="FILES") m_extension=func.arguments[1].value; for(it=func.arguments.constBegin()+2; it!=itEnd; ++it) { m_files.append(it->value); } } return !m_files.isEmpty() || !m_regex.isEmpty(); } InstallProgramsAst::InstallProgramsAst() { } InstallProgramsAst::~InstallProgramsAst() { } bool InstallProgramsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()=="install_programs" || func.arguments.count()<2) return false; m_directory=func.arguments[0].value; if(func.arguments.count()==2) { m_regex=func.arguments[1].value; } else { QList::const_iterator it, itEnd=func.arguments.constEnd(); int firstpos=1; if(func.arguments[1].value!="FILES") firstpos++; for(it=func.arguments.constBegin()+firstpos; it!=itEnd; ++it) { m_files.append(it->value); } } return !m_files.isEmpty() || !m_regex.isEmpty(); } InstallTargetsAst::InstallTargetsAst() { } InstallTargetsAst::~InstallTargetsAst() { } bool InstallTargetsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()=="install_targets" || func.arguments.count()<2) return false; m_directory=func.arguments[0].value; QList::const_iterator it, itEnd=func.arguments.constEnd(); int firstpos=1; if(func.arguments[1].value=="RUNTIME_DIRECTORY") { firstpos+=2; if(func.arguments.count()<3) return false; m_runtimeDir=func.arguments[2].value; } for(it=func.arguments.constBegin()+firstpos; it!=itEnd; ++it) { m_targets.append(it->value); } return !m_targets.isEmpty(); } LinkDirectoriesAst::LinkDirectoriesAst() { } LinkDirectoriesAst::~LinkDirectoriesAst() { } bool LinkDirectoriesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "link_directories" || func.arguments.isEmpty() ) return false; foreach(const CMakeFunctionArgument &arg, func.arguments) m_directories.append(arg.value); return true; } LinkLibrariesAst::LinkLibrariesAst() { } LinkLibrariesAst::~LinkLibrariesAst() { } bool LinkLibrariesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "link_libraries" || func.arguments.isEmpty() ) return false; QString lastLib; foreach(const CMakeFunctionArgument &arg, func.arguments) { BuildType current=None; if(arg.value=="debug") current=Debug; else if(arg.value=="optimized") current=Optimized; else { if(!lastLib.isEmpty()) m_libraries.append(LibraryType(lastLib, None)); lastLib=arg.value; } if(current!=None) m_libraries.append(LibraryType(lastLib, current)); } return true; } ListAst::ListAst() : m_type(Length) { } ListAst::~ListAst() { } bool ListAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "list" ) return false; if ( func.arguments.size() < 2) return false; QString argName = func.arguments.first().value; if(argName=="LENGTH") m_type = Length; else if(argName=="GET") m_type=Get; else if(argName=="APPEND") m_type = Append; else if(argName=="FIND") m_type = Find; else if(argName=="INSERT") m_type = Insert; else if(argName=="REMOVE_ITEM") m_type = RemoveItem; else if(argName=="REMOVE_AT") m_type = RemoveAt; else if(argName=="SORT") m_type = Sort; else if(argName=="REVERSE") m_type = Reverse; else if(argName=="REMOVE_DUPLICATES") m_type = RemoveDuplicates; else return false; m_list = func.arguments[1].value; switch(m_type) { case Length: if(func.arguments.count()!=3) return false; m_output = func.arguments[2].value; addOutputArgument(func.arguments[2]); break; case Get: { if(func.arguments.count()<3) return false; addOutputArgument(func.arguments[1]); addOutputArgument(func.arguments.last()); m_output = func.arguments.last().value; QList::const_iterator it=func.arguments.constBegin()+2, itEnd=func.arguments.constEnd(); int i=2; bool correct; for(; it!=itEnd; ++it) { if(i!=func.arguments.size()-1) { m_index.append(it->value.toInt(&correct)); if(!correct) return false; } i++; } } break; case Append: { if(func.arguments.count()<2) return false; addOutputArgument(func.arguments[1]); m_output = func.arguments[1].value; int i=0; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(i>1) m_elements.append(arg.value); i++; } } break; case Find: { if(func.arguments.count()!=4) return false; m_elements.append(func.arguments[2].value); m_output=func.arguments[3].value; addOutputArgument(func.arguments[3]); } break; case Insert: { bool correct; if(func.arguments.count()<4) return false; int i=0; addOutputArgument(func.arguments[1]); m_index.append(func.arguments[2].value.toInt(&correct)); if(!correct) return false; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(i>2) m_elements.append(arg.value); i++; } } break; case RemoveItem: { if(func.arguments.count()<3) return false; addOutputArgument(func.arguments[1]); m_output = func.arguments[1].value; QList::const_iterator it=func.arguments.constBegin()+2, itEnd=func.arguments.constEnd(); for(; it!=itEnd; ++it) { m_elements.append(it->value); } } break; case RemoveAt: { if(func.arguments.count()<3) return false; addOutputArgument(func.arguments[1]); m_output = func.arguments[1].value; int i=0; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(i>1) { bool correct; m_index.append(arg.value.toInt(&correct)); qCDebug(CMAKE) << "???" << arg.value; if(!correct) return false; } i++; } } break; case Sort: case Reverse: case RemoveDuplicates: addOutputArgument(func.arguments[1]); m_output = func.arguments[1].value; if(func.arguments.count()>2) return false; break; } return true; } LoadCacheAst::LoadCacheAst() { } LoadCacheAst::~LoadCacheAst() { } bool LoadCacheAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "load_cache" || func.arguments.count()<4) return false; m_cachePath=func.arguments[0].value; if(func.arguments[1].value=="READ_WITH_PREFIX") { QString prefix; QList::const_iterator it, itEnd = func.arguments.constEnd(); for ( it = func.arguments.constBegin() + 2; it != itEnd; ++it ) { if(prefix.isEmpty()) { prefix=it->value; } else { m_prefixes=PrefixEntry(prefix, it->value); prefix.clear(); } } return prefix.isEmpty(); } else { bool exclude=false; QList::const_iterator it, itEnd = func.arguments.constEnd(); for ( it = func.arguments.constBegin() + 2; it != itEnd; ++it ) { if(it->value=="EXCLUDE") exclude=true; else if(it->value=="INCLUDE_INTERNALS") exclude=false; else { if(exclude) m_exclude.append(it->value); else m_includeInternals.append(it->value); } } return true; } return false; } LoadCommandAst::LoadCommandAst() { } LoadCommandAst::~LoadCommandAst() { } bool LoadCommandAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "load_command" || func.arguments.count()<4) return false; m_cmdName=func.arguments[0].value; QList::const_iterator it, itEnd = func.arguments.constEnd(); for ( it = func.arguments.constBegin() + 1; it != itEnd; ++it ) m_location.append( it->value ); return !m_location.isEmpty(); } MacroAst::MacroAst() { } MacroAst::~MacroAst() { } bool MacroAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "macro" || func.arguments.isEmpty()) return false; m_macroName = func.arguments.first().value.toLower(); QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin() + 1; it != itEnd; ++it ) m_knownArgs.append( it->value ); return !m_macroName.isEmpty(); } FunctionAst::FunctionAst() { } FunctionAst::~FunctionAst() { } bool FunctionAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "function" || func.arguments.isEmpty()) return false; m_name = func.arguments.first().value.toLower(); QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin() + 1; it != itEnd; ++it ) m_knownArgs.append( it->value ); return true; } MakeDirectoryAst::MakeDirectoryAst() { } MakeDirectoryAst::~MakeDirectoryAst() { } bool MakeDirectoryAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "make_directory" || func.arguments.isEmpty() || func.arguments.size()>1) return false; m_directory=func.arguments.first().value; return true; } MarkAsAdvancedAst::MarkAsAdvancedAst() : m_isClear(false) , m_isForce(false) { } MarkAsAdvancedAst::~MarkAsAdvancedAst() { } bool MarkAsAdvancedAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "mark_as_advanced" || func.arguments.isEmpty() ) return false; m_isClear = func.arguments[0].value == "CLEAR"; m_isForce = func.arguments[0].value == "FORCE"; if ( (m_isClear || m_isForce) && func.arguments.size() < 2 ) return false; QList::const_iterator it, itEnd; it=func.arguments.begin(); itEnd = func.arguments.end(); if(m_isClear || m_isForce) ++it; for ( ; it != itEnd; ++it ) { m_advancedVars.append(it->value); } return true; } MathAst::MathAst() { } MathAst::~MathAst() { } bool MathAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="math" || func.arguments.count()!=3 || func.arguments.first().value!="EXPR") return false; addOutputArgument(func.arguments[1]); m_outputVariable = func.arguments[1].value; m_expression = func.arguments.last().value; return true; } MessageAst::MessageAst() : m_type(SendError) { } MessageAst::~MessageAst() { } bool MessageAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="message" || func.arguments.isEmpty()) return false; if(func.arguments.count()>1) { QString type=func.arguments.first().value; if(type=="SEND_ERROR") m_type=SendError; else if(type=="STATUS") m_type=Status; else if(type=="FATAL_ERROR") m_type=FatalError; } m_message.append(func.arguments.last().value); //Maybe should do a foreach return true; } OptionAst::OptionAst() { } OptionAst::~OptionAst() { } bool OptionAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="option" || func.arguments.count()<2 || func.arguments.count()>3) return false; m_variableName = func.arguments[0].value; m_description = func.arguments[1].value; m_defaultValue = "OFF"; if(func.arguments.count() ==3) m_defaultValue = func.arguments[2].value; return true; } OutputRequiredFilesAst::OutputRequiredFilesAst() { } OutputRequiredFilesAst::~OutputRequiredFilesAst() { } bool OutputRequiredFilesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="output_required_files" || func.arguments.count()!=2) return false; m_srcFile=func.arguments[0].value; m_outputFile=func.arguments[1].value; return true; } ProjectAst::ProjectAst() : m_useCpp(false) , m_useC(false) , m_useJava(false) { } ProjectAst::~ProjectAst() { } bool ProjectAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "project" ) return false; if ( func.arguments.size() < 1 ) return false; m_projectName = func.arguments[0].value; QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin()+1; it != itEnd; ++it ) { CMakeFunctionArgument arg = ( *it ); if ( arg.value == "CXX" ) m_useCpp = true; else if ( arg.value == "C" ) m_useC = true; else if ( arg.value == "Java" ) m_useJava = true; else return false; } return true; } QtWrapCppAst::QtWrapCppAst() { } QtWrapCppAst::~QtWrapCppAst() { } bool QtWrapCppAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } QtWrapUiAst::QtWrapUiAst() { } QtWrapUiAst::~QtWrapUiAst() { } bool QtWrapUiAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } RemoveAst::RemoveAst() { } RemoveAst::~RemoveAst() { } bool RemoveAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "remove" || func.arguments.isEmpty()) return false; m_variableName = func.arguments[0].value; QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin()+1; it != itEnd; ++it ) { m_values.append(it->value); } return !m_values.isEmpty(); } RemoveDefinitionsAst::RemoveDefinitionsAst() { } RemoveDefinitionsAst::~RemoveDefinitionsAst() { } bool RemoveDefinitionsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "remove_definitions") return false; QList::const_iterator it, itEnd = func.arguments.end(); for ( it = func.arguments.begin(); it != itEnd; ++it ) { m_definitions.append(it->value); } return !m_definitions.isEmpty(); } SeparateArgumentsAst::SeparateArgumentsAst() { } SeparateArgumentsAst::~SeparateArgumentsAst() { } /// @todo Parse the UNIX_COMMAND and WINDOWS_COMMAND keywords /// introduced in CMake 2.8. bool SeparateArgumentsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "separate_arguments" || func.arguments.count()!=1) return false; addOutputArgument(func.arguments.first()); m_variableName=func.arguments.first().value; return true; } SetAst::SetAst() : m_storeInCache(false) , m_forceStoring(false) , m_parentScope(false) { } SetAst::~SetAst() { } bool SetAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "set" || func.arguments.isEmpty() ) return false; m_variableName = func.arguments.first().value; addOutputArgument(func.arguments.first()); int argSize = func.arguments.size(); //look for the FORCE argument. Thanks to the CMake folks for letting //me read their code m_forceStoring = ( argSize > 4 && func.arguments.last().value == "FORCE" ); m_parentScope = ( argSize > 1 && func.arguments.last().value == "PARENT_SCOPE" ); m_storeInCache = ( argSize > 3 && func.arguments[argSize - 3 - ( m_forceStoring || m_parentScope ? 1 : 0 )].value == "CACHE" ); int numCacheArgs = ( m_storeInCache ? 3 : 0 ); int numForceArgs = ( m_forceStoring ? 1 : 0 ); int numParentScope = ( m_parentScope ? 1 : 0 ); if ( argSize > 1 + numCacheArgs + numForceArgs + numParentScope ) { QList args = func.arguments; QList::const_iterator it, itEnd; it = args.constBegin() + 1; itEnd = args.constEnd() - numCacheArgs - numForceArgs - numParentScope; for ( ; it != itEnd; ++it ) m_values.append( it->value ); } //catch some simple things. if CACHE is the last or next to last arg or if //FORCE was used without CACHE, then there's a problem. if ( func.arguments.last().value == "CACHE" || ( argSize > 1 && func.arguments[argSize - 2].value == "CACHE" ) || (m_forceStoring && !m_storeInCache) ) { return false; } if((m_storeInCache || m_forceStoring) && m_parentScope) return false; if(func.arguments.last().value=="FORCE" && !m_forceStoring) return false; return true; } SetDirectoryPropsAst::SetDirectoryPropsAst() { } SetDirectoryPropsAst::~SetDirectoryPropsAst() { } bool SetDirectoryPropsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="set_directory_properties" || func.arguments.count()<3) return false; if(func.arguments.first().value!="PROPERTIES") return false; QList::const_iterator it=func.arguments.begin()+1; QList::const_iterator itEnd=func.arguments.end(); for(; it!=itEnd; ++it) { QString prop=it->value; ++it; if(it==itEnd) return false; m_properties.append(PropPair(prop, it->value)); } return !m_properties.isEmpty(); } SetSourceFilesPropsAst::SetSourceFilesPropsAst() { } SetSourceFilesPropsAst::~SetSourceFilesPropsAst() { } bool SetSourceFilesPropsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="set_source_files_properties" || func.arguments.count()<4) return false; bool props=false; QList::const_iterator it=func.arguments.begin(); QList::const_iterator itEnd=func.arguments.end(); QString prop; for(; it!=itEnd; ++it) { if(it->value=="PROPERTIES") { props=true; continue; } if(!props) { m_files.append(it->value); } else { if(prop.isEmpty()) prop=it->value; else { m_properties.append(PropPair(prop, it->value)); prop.clear(); } } } return prop.isEmpty(); } SetTargetPropsAst::SetTargetPropsAst() { } SetTargetPropsAst::~SetTargetPropsAst() { } bool SetTargetPropsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="set_target_properties" || func.arguments.count()<4) return false; bool props=false; QList::const_iterator it=func.arguments.begin(); QList::const_iterator itEnd=func.arguments.end(); QString prop; for(; it!=itEnd; ++it) { if(it->value=="PROPERTIES") { props=true; continue; } if(!props) { m_targets.append(it->value); } else { if(prop.isEmpty()) prop=it->value; else { m_properties.append(PropPair(prop, it->value)); prop.clear(); } } } return prop.isEmpty(); } SetTestsPropsAst::SetTestsPropsAst() { } SetTestsPropsAst::~SetTestsPropsAst() { } bool SetTestsPropsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="set_tests_properties" || func.arguments.count()<4) return false; bool props=false; QList::const_iterator it=func.arguments.begin(); QList::const_iterator itEnd=func.arguments.end(); QString prop; for(; it!=itEnd; ++it) { if(it->value=="PROPERTIES") { props=true; continue; } if(!props) { m_tests.append(it->value); } else { if(prop.isEmpty()) prop=it->value; else { m_properties.append(PropPair(prop, it->value)); prop.clear(); } } } return prop.isEmpty(); } SiteNameAst::SiteNameAst() { } SiteNameAst::~SiteNameAst() { } bool SiteNameAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="site_name" || func.arguments.count()!=1) return false; addOutputArgument(func.arguments.first()); m_variableName = func.arguments.first().value; return true; } SourceGroupAst::SourceGroupAst() { } SourceGroupAst::~SourceGroupAst() { } bool SourceGroupAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="source_group" || func.arguments.count()>1) return false; m_name=func.arguments[0].value; QList::const_iterator it=func.arguments.begin()+1; QList::const_iterator itEnd=func.arguments.end(); enum Param { None, Regex, Files }; Param current=None; for(; it!=itEnd; ++it) { if(it->value=="REGULAR_EXPRESSION") current=Regex; else if(it->value=="FILES") current=Files; else switch(current) { case Regex: m_regex=it->value; case Files: m_files.append(it->value); break; case None: return false; } } return !m_regex.isEmpty() || !m_files.isEmpty(); } StringAst::StringAst() : m_type(Regex) , m_cmdType(Match) , m_only(false) , m_escapeQuotes(false) , m_begin(0) , m_length(0) { } StringAst::~StringAst() { } bool StringAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="string" || func.arguments.count()<2) return false; QString stringType=func.arguments[0].value; if(stringType=="REGEX") { if(func.arguments.count()<5) return false; m_type=Regex; QString regexType = func.arguments[1].value; int outpos=3; if(regexType=="MATCH") m_cmdType=Match; else if(regexType=="MATCHALL") m_cmdType=MatchAll; else if(regexType=="REPLACE") { m_cmdType=RegexReplace; m_replace=func.arguments[3].value; outpos=4; } m_regex = func.arguments[2].value; addOutputArgument(func.arguments[outpos]); m_outputVariable = func.arguments[outpos].value; QList::const_iterator it=func.arguments.begin()+outpos+1; QList::const_iterator itEnd=func.arguments.end(); for(; it!=itEnd; ++it) { m_input += it->value; } qCDebug(CMAKE) << "performing REGEX" << regexType << " : " << m_regex << " > "<< m_outputVariable << "result: "; } else if(stringType=="REPLACE") { if(func.arguments.count()<4) return false; m_type=Replace; m_regex = func.arguments[1].value; m_replace=func.arguments[2].value; m_outputVariable = func.arguments[3].value; addOutputArgument(func.arguments[3]); QList::const_iterator it=func.arguments.begin()+4, itEnd=func.arguments.end(); for(; it!=itEnd; ++it) { m_input += it->value; } } else if(stringType=="COMPARE") { if(func.arguments.count()!=5) return false; m_type=Compare; QString argumentType=func.arguments[1].value; if(argumentType=="EQUAL") m_cmdType=Equal; else if(argumentType=="NOTEQUAL") m_cmdType=NotEqual; else if(argumentType=="LESS") m_cmdType=Less; else if(argumentType=="GREATER") m_cmdType=Greater; m_input.append(func.arguments[2].value); m_input.append(func.arguments[3].value); m_outputVariable = func.arguments[4].value; addOutputArgument(func.arguments[4]); } else if(stringType=="ASCII") { m_type=Ascii; QList::const_iterator it=func.arguments.begin()+1; QList::const_iterator itEnd=func.arguments.end(); for(; it!=itEnd; ++it) { m_input += it->value; } m_input.pop_back(); //We remove the output var m_outputVariable = func.arguments.last().value; addOutputArgument(func.arguments.last()); } else if(stringType=="CONFIGURE") { m_type=Configure; if(func.arguments.isEmpty()) return false; m_input += func.arguments[1].value; m_outputVariable=func.arguments[2].value; addOutputArgument(func.arguments[2]); int i=3; if(func.arguments.count()>i) m_only = func.arguments[i].value=="@ONLY"; if(m_only) i++; if(func.arguments.count()>i) m_escapeQuotes = func.arguments[i].value=="ESCAPE_QUOTES"; } else if(stringType=="TOUPPER" && func.arguments.count()==3) { m_type=ToUpper; m_input.append(func.arguments[1].value); m_outputVariable = func.arguments[2].value; addOutputArgument(func.arguments[2]); } else if(stringType=="TOLOWER" && func.arguments.count()==3) { m_type=ToLower; m_input.append(func.arguments[1].value); m_outputVariable = func.arguments[2].value; addOutputArgument(func.arguments[2]); } else if(stringType=="LENGTH" && func.arguments.count()==3) { m_type=Length; m_input.append(func.arguments[1].value); m_outputVariable = func.arguments[2].value; addOutputArgument(func.arguments[2]); } else if(stringType=="SUBSTRING") { if(func.arguments.count()<5) return false; bool correctBegin, correctLength; m_type=Substring; m_input.append(func.arguments[1].value); m_begin = func.arguments[2].value.toInt(&correctBegin); m_length = func.arguments[3].value.toInt(&correctLength); m_outputVariable = func.arguments[4].value; addOutputArgument(func.arguments[4]); if(!correctBegin || !correctLength) return false; } else if(stringType=="STRIP") { m_type=Strip; if(func.arguments.count()!=3) return false; m_string = func.arguments[1].value; m_outputVariable = func.arguments.last().value; addOutputArgument(func.arguments.last()); } else if(stringType=="RANDOM") { if(func.arguments.count()>6 || func.arguments.count()<2) return false; m_type=Random; enum State { Alphabet, Length, None }; State s = None; m_length=5; m_string="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; bool first=true; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(first) { first=false; continue; } bool correct=true; switch(s) { case Alphabet: m_regex=arg.value; s=None; continue; case Length: m_length = arg.value.toInt(&correct); if(!correct) return false; s=None; continue; case None: break; } if(arg.value=="LENGTH") s = Length; else if(arg.value=="ALPHABET") s = Alphabet; else { s=None; if(!m_outputVariable.isEmpty()) { return false; } m_outputVariable = arg.value; addOutputArgument(arg); } } } else return false; return true; } SubdirDependsAst::SubdirDependsAst() { } SubdirDependsAst::~SubdirDependsAst() { } bool SubdirDependsAst::parseFunctionInfo( const CMakeFunctionDesc& func) { if ( func.name != "subdir_depends" || func.arguments.isEmpty()) return false; return true; } SubdirsAst::SubdirsAst() : m_preorder(false) { } SubdirsAst::~SubdirsAst() { } bool SubdirsAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "subdirs" ) return false; if ( func.arguments.isEmpty() ) return false; bool excludeFromAll=false; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(arg.value.toLower()=="exclude_from_all") excludeFromAll=true; else if(arg.value.toLower()=="preorder") m_preorder=true; else { if(excludeFromAll) m_exluceFromAll.append(arg.value); else m_directories.append(arg.value); } } return true; } TargetIncludeDirectoriesAst::TargetIncludeDirectoriesAst() : m_before(false) {} TargetIncludeDirectoriesAst::~TargetIncludeDirectoriesAst() {} bool TargetIncludeDirectoriesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "target_include_directories" ) return false; //we don't do variable expansion when parsing like CMake does, so we //need to have at least two arguments for target_link_libraries if ( func.arguments.size() < 2 ) return false; m_target = func.arguments[0].value; QList::const_iterator it = func.arguments.constBegin() + 1; QList::const_iterator itEnd = func.arguments.constEnd(); m_before = func.arguments[1].value == "BEFORE"; if(m_before) { ++it; } Item currentItem; for ( ; it != itEnd; ++it ) { QString visibility = it->value; if(visibility == "INTERFACE") currentItem.visibility = Interface; else if(visibility == "PUBLIC") currentItem.visibility = Public; else if(visibility == "PRIVATE") currentItem.visibility = Private; else return false; ++it; if(it==itEnd) return false; currentItem.item = it->value; m_items.append(currentItem); } return !m_items.isEmpty(); } TargetLinkLibrariesAst::TargetLinkLibrariesAst() { } TargetLinkLibrariesAst::~TargetLinkLibrariesAst() { } bool TargetLinkLibrariesAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "target_link_libraries" ) return false; //we don't do variable expansion when parsing like CMake does, so we //need to have at least two arguments for target_link_libraries if ( func.arguments.size() < 2 ) return false; m_target = func.arguments[0].value; Dependencies* current = &m_publicDependencies; QList::const_iterator it, itEnd; for (it = func.arguments.begin() + 1, itEnd = func.arguments.end(); it != itEnd; ++it ) { CMakeFunctionArgument arg = ( *it ); if ( arg.value == "LINK_PUBLIC" || arg.value == "PUBLIC" ) { current = &m_publicDependencies; continue; } else if ( arg.value == "LINK_PRIVATE" || arg.value == "PRIVATE" ) { current = &m_privateDependencies; continue; } else if ( arg.value == "LINK_INTERFACE_LIBRARIES") { current = &m_interfaceOnlyDependencies; continue; } else if ( arg.value == "debug" ) { ++it; if ( it == itEnd ) return false; else current->debug.append( it->value ); } else if ( arg.value == "optimized" ) { ++it; if ( it == itEnd ) return false; else current->optimized.append( it->value ); } else current->other.append( arg.value ); } return true; } QStringList TargetLinkLibrariesAst::Dependencies::retrieveTargets() const { return debug + optimized + other; } TryCompileAst::TryCompileAst() { } TryCompileAst::~TryCompileAst() { } bool TryCompileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if ( func.name != "try_compile" || func.arguments.size() < 3) return false; m_resultName=func.arguments[0].value; m_binDir=func.arguments[1].value; m_source=func.arguments[2].value; enum Param { None, CMakeFlags, CompileDefinitions, OutputVariable, CopyFile }; Param current=None; QList::const_iterator it, itEnd; it = func.arguments.begin() + 3; itEnd = func.arguments.end(); //FIXME: Should look for errors for ( ; it != itEnd; ++it ) { if(it->value=="CMAKE_FLAGS") current=CMakeFlags; else if(it->value=="COMPILE_DEFINITIONS") current=CompileDefinitions; else if(it->value=="OUTPUT_VARIABLE") current=OutputVariable; else if(it->value=="COPY_FILE") current=OutputVariable; else switch(current) { case None: if(m_projectName.isEmpty()) m_projectName=it->value; else m_targetName=it->value; current=None; break; case CMakeFlags: m_cmakeFlags.append(it->value); break; case CompileDefinitions: m_compileDefinitions.append(it->value); break; case OutputVariable: m_outputName=it->value; addOutputArgument(*it); current=None; break; case CopyFile: m_copyFile=it->value; current=None; break; } } return true; } TryRunAst::TryRunAst() { } TryRunAst::~TryRunAst() { } bool TryRunAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="try_run" || func.arguments.count()<4) return false; enum Actions { None, CMakeFlags, CompileDefs, OutputVariable, Args }; Actions act = None; unsigned int i=0; foreach(const CMakeFunctionArgument& arg, func.arguments) { QString val=arg.value.toLower(); if(i<4) act=None; if(i==0) m_runResultVar=arg.value; else if(i==1) { addOutputArgument(arg); m_compileResultVar=arg.value; } else if(i==2) m_binDir=arg.value; else if(i==3) m_srcFile=arg.value; else if(val=="cmake_flags") act=CMakeFlags; else if(val=="compile_definitions") act=CompileDefs; else if(val=="output_variable") act=OutputVariable; else if(val=="args") act=Args; else switch(act) { case None: return false; case CMakeFlags: m_cmakeFlags.append(arg.value); break; case CompileDefs: m_compileDefs.append(arg.value); case OutputVariable: m_outputVar=arg.value; break; case Args: m_args.append(arg.value); break; } i++; } return true; } UseMangledMesaAst::UseMangledMesaAst() { } UseMangledMesaAst::~UseMangledMesaAst() { } bool UseMangledMesaAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="path_to_mesa" || func.arguments.count()!=2) return false; m_pathToMesa=func.arguments[0].value; m_outputDir=func.arguments[1].value; return true; } UtilitySourceAst::UtilitySourceAst() { } UtilitySourceAst::~UtilitySourceAst() { } bool UtilitySourceAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="utility_source" || func.arguments.count()<3) return false; unsigned int i=0; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(i==0) m_cacheEntry=arg.value; else if(i==1) m_executableName=arg.value; else if(i==2) m_pathToSource=arg.value; else m_fileList.append(arg.value); } return true; } UnsetAst::UnsetAst() : m_cache(false) , m_env(false) { } UnsetAst::~UnsetAst() { } bool UnsetAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="unset" || func.arguments.count()<1 || func.arguments.count()>2) return false; m_variableName = func.arguments.first().value; addOutputArgument(func.arguments.first()); m_cache = func.arguments.count()==2 && func.arguments.last().value=="CACHE"; m_env = m_variableName.startsWith("ENV{"); if(m_env) { m_variableName = m_variableName.mid(4, -2); } return func.arguments.count()==1 || (m_cache && !m_env); } VariableRequiresAst::VariableRequiresAst() { } VariableRequiresAst::~VariableRequiresAst() { } bool VariableRequiresAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="variable_requires" || func.arguments.count()<2) return false; unsigned int i=0; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(i==0) m_testVariable=arg.value; else if(i==1) { addOutputArgument(arg); m_resultVariable=arg.value; } else m_requiredVariables.append(arg.value); i++; } return true; } VtkMakeInstantiatorAst::VtkMakeInstantiatorAst() { } VtkMakeInstantiatorAst::~VtkMakeInstantiatorAst() { } bool VtkMakeInstantiatorAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } VtkWrapJavaAst::VtkWrapJavaAst() { } VtkWrapJavaAst::~VtkWrapJavaAst() { } bool VtkWrapJavaAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } VtkWrapPythonAst::VtkWrapPythonAst() { } VtkWrapPythonAst::~VtkWrapPythonAst() { } bool VtkWrapPythonAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } VtkWrapTclAst::VtkWrapTclAst() { } VtkWrapTclAst::~VtkWrapTclAst() { } bool VtkWrapTclAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { Q_UNUSED(func); return false; } WhileAst::WhileAst() { } WhileAst::~WhileAst() { } bool WhileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="while" || func.arguments.isEmpty()) return false; foreach(const CMakeFunctionArgument& arg, func.arguments) { m_condition.append(arg.value); } return true; } WriteFileAst::WriteFileAst() : m_append(false) { } WriteFileAst::~WriteFileAst() { } bool WriteFileAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="write_file" || func.arguments.count()<2) return false; m_filename=func.arguments[0].value; m_message=func.arguments[1].value; if(func.arguments.count()>2) { if(func.arguments[2].value=="APPEND") { m_append=true; } if(func.arguments.count()>(2+m_append)) return false; } return true; } CustomInvokationAst::CustomInvokationAst() { } CustomInvokationAst::~CustomInvokationAst() { } bool CustomInvokationAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { m_function = func; m_arguments = func.arguments; return true; } BreakAst::BreakAst() { } BreakAst::~BreakAst() { } bool BreakAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { return func.name.toLower()=="break"; } CMakePolicyAst::CMakePolicyAst() : m_action(Version) , m_policyNum(0) , m_isNew(false) { } CMakePolicyAst::~CMakePolicyAst() { } bool CMakePolicyAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="cmake_policy" || func.arguments.isEmpty()) return false; const QString &first=func.arguments[0].value; if(first=="VERSION") { bool ok = false; m_version = CMakeParserUtils::parseVersion(func.arguments[1].value, &ok); return ok; } else if(first=="SET" && func.arguments.count()==3) { QRegExp rx("CMP([1-9]*)"); rx.indexIn(func.arguments[1].value); QStringList cmpValue=rx.capturedTexts(); cmpValue.erase(cmpValue.begin()); if(cmpValue.count()==1) { m_policyNum=cmpValue[0].toInt(); } else return false; if(func.arguments[2].value=="OLD") m_isNew=false; else if(func.arguments[2].value=="NEW") m_isNew=true; else return false; return true; } else if(first=="PUSH") { m_action=Push; return func.arguments.count()==1; } else if(first=="POP") { m_action=Pop; return func.arguments.count()==1; } return false; } ExportAst::ExportAst() : m_append(false) { } ExportAst::~ExportAst() { } /// @todo Implement EXPORT(PACKAGE name), introduced in CMake 2.8 bool ExportAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="export" || func.arguments.count() < 2 || func.arguments[0].value!="TARGETS") return false; enum Option { TARGETS, NAMESPACE, FILE }; Option opt=TARGETS; foreach(const CMakeFunctionArgument& arg, func.arguments) { if(arg.value=="TARGETS") { if(opt!=TARGETS) return false; } else if(arg.value=="NAMESPACE") { opt=NAMESPACE; } else if(arg.value=="FILE") { opt=FILE; } else if(arg.value=="APPEND") { m_append=true; } else { switch(opt) { case TARGETS: m_targets.append(arg.value); break; case NAMESPACE: m_targetNamespace=arg.value; break; case FILE: m_filename=arg.value; break; } opt=TARGETS; } } return !m_filename.isEmpty(); } ReturnAst::ReturnAst() { } ReturnAst::~ReturnAst() { } bool ReturnAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { return func.arguments.isEmpty() && func.name.toLower()=="return"; } SetPropertyAst::SetPropertyAst() : m_type(GlobalProperty) , m_append(false) { } SetPropertyAst::~SetPropertyAst() { } bool SetPropertyAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="set_property" || func.arguments.count() < 3) return false; QString propName=func.arguments.first().value; if(propName=="GLOBAL") m_type=GlobalProperty; else if(propName=="DIRECTORY") m_type=DirectoryProperty; else if(propName=="TARGET") m_type=TargetProperty; else if(propName=="CACHE") m_type=CacheProperty; else if(propName=="SOURCE") m_type=SourceProperty; else if(propName=="TEST") m_type=TestProperty; else return false; QList::const_iterator it=func.arguments.constBegin()+1, itEnd=func.arguments.constEnd(); for(; it!=itEnd && it->value!="PROPERTY" && it->value!="APPEND" && it->value!="APPEND_STRING"; ++it) { m_args.append(it->value); } m_append=it!=itEnd && it->value=="APPEND"; if(m_append) ++it; m_appendString=it!=itEnd && it->value=="APPEND_STRING"; if(m_appendString) ++it; if(it!=itEnd) ++it; //PROPERTY else return false; m_name=it->value; ++it; for(; it!=itEnd && it->value!="PROPERTY" && it->value!="APPEND"; ++it) { m_values.append(it->value); } return !m_name.isEmpty(); } GetPropertyAst::GetPropertyAst() : m_type(GlobalProperty) {} GetPropertyAst::~GetPropertyAst() {} bool GetPropertyAst::parseFunctionInfo( const CMakeFunctionDesc& func ) { if(func.name.toLower()!="get_property" || func.arguments.count() < 4 || func.arguments.count() > 6) return false; QList::const_iterator it=func.arguments.constBegin(), itEnd=func.arguments.constEnd(); m_outputVariable=it->value; addOutputArgument(*it); ++it; PropertyType t; QString propName=it->value; if(propName=="GLOBAL") t=GlobalProperty; else if(propName=="DIRECTORY") t=DirectoryProperty; else if(propName=="TARGET") t=TargetProperty; else if(propName=="SOURCE") t=SourceProperty; else if(propName=="CACHE") t=CacheProperty; else if(propName=="TEST") t=TestProperty; else if(propName=="VARIABLE") t=VariableProperty; else return false; m_type=t; ++it; if(it->value!="PROPERTY") { m_typeName=it->value; ++it; } if(it->value!="PROPERTY") return false; ++it; m_name=it->value; ++it; m_behaviour=None; if(it!=itEnd) { QString ee=it->value; if(ee=="SET") m_behaviour=Set; else if(ee=="DEFINED") m_behaviour=Defined; else if(ee=="BRIEF_DOCS") m_behaviour=BriefDocs; else if(ee=="FULL_DOCS") m_behaviour=FullDocs; } return !m_name.isEmpty(); }