kde-extraapps/kdevelop/projectmanagers/cmake/parser/cmakeast.cpp
2015-07-26 14:23:17 +03:00

3973 lines
100 KiB
C++

/* KDevelop CMake Support
*
* Copyright 2006 Matt Rogers <mattr@kde.org>
* Copyright 2007-2009 Aleix Pol <aleixpol@kde.org>
*
* Some parts of this code are based on CMake
* Copyright 2002 Kitware, Inc. Insight Consortium <kitware@kitware.com>
*
* 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 <QString>
#include <KDebug>
#include "astfactory.h"
#include "cmakelistsparser.h"
#include "cmakeparserutils.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;
}
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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument> args = func.arguments;
m_target = args.front().value;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument> args = func.arguments;
QList<CMakeFunctionArgument>::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<QString, AddLibraryAst::LibraryType> 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<CMakeFunctionArgument> args = func.arguments;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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()<min_args)
return false;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.constBegin()+1;
QList<CMakeFunctionArgument>::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 {
kWarning() << "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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<func.arguments.size() && func.arguments[i].value=="SYSTEM") {
m_isSystem = true;
i++;
}
if ( func.arguments.size() <= i )
return false;
QList<CMakeFunctionArgument>::const_iterator it=func.arguments.constBegin() + i;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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));
kDebug(9042) << "???" << 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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument> args = func.arguments;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin()+1;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin();
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin();
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin();
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin()+1;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin()+outpos+1;
QList<CMakeFunctionArgument>::const_iterator itEnd=func.arguments.end();
for(; it!=itEnd; ++it)
{
m_input += it->value;
}
kDebug(9042) << "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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it=func.arguments.begin()+1;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::const_iterator it = func.arguments.constBegin() + 1;
QList<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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<CMakeFunctionArgument>::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();
}