diff options
Diffstat (limited to 'Source/cmIDEOptions.cxx')
-rw-r--r-- | Source/cmIDEOptions.cxx | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx new file mode 100644 index 0000000..9468d4a --- /dev/null +++ b/Source/cmIDEOptions.cxx @@ -0,0 +1,254 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmIDEOptions.h" + +#include <algorithm> +#include <cstring> +#include <iterator> +#include <utility> + +#include <cmext/algorithm> + +#include "cmsys/String.h" + +#include "cmIDEFlagTable.h" +#include "cmStringAlgorithms.h" + +cmIDEOptions::cmIDEOptions() +{ + this->DoingDefine = false; + this->AllowDefine = true; + this->DoingInclude = false; + this->AllowSlash = false; + this->DoingFollowing = nullptr; + for (auto& flag : this->FlagTable) { + flag = nullptr; + } +} + +cmIDEOptions::~cmIDEOptions() = default; + +void cmIDEOptions::HandleFlag(std::string const& flag) +{ + // If the last option was -D then this option is the definition. + if (this->DoingDefine) { + this->DoingDefine = false; + this->Defines.push_back(flag); + return; + } + + // If the last option was -I then this option is the include directory. + if (this->DoingInclude) { + this->DoingInclude = false; + this->Includes.push_back(flag); + return; + } + + // If the last option expected a following value, this is it. + if (this->DoingFollowing) { + this->FlagMapUpdate(this->DoingFollowing, flag); + this->DoingFollowing = nullptr; + return; + } + + // Look for known arguments. + size_t len = flag.length(); + if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) { + // Look for preprocessor definitions. + if (this->AllowDefine && len > 1 && flag[1] == 'D') { + if (len <= 2) { + // The next argument will have the definition. + this->DoingDefine = true; + } else { + // Store this definition. + this->Defines.push_back(flag.substr(2)); + } + return; + } + // Look for include directory. + if (this->AllowInclude && len > 1 && flag[1] == 'I') { + if (len <= 2) { + // The next argument will have the include directory. + this->DoingInclude = true; + } else { + // Store this include directory. + this->Includes.push_back(flag.substr(2)); + } + return; + } + + // Look through the available flag tables. + bool flag_handled = false; + for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) { + if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) { + return; + } + } + + // If any map entry handled the flag we are done. + if (flag_handled) { + return; + } + } + + // This option is not known. Store it in the output flags. + this->StoreUnknownFlag(flag); +} + +bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table, + std::string const& flag, bool& flag_handled) +{ + const char* pf = flag.c_str() + 1; + // Look for an entry in the flag table matching this flag. + for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) { + bool entry_found = false; + if (entry->special & cmIDEFlagTable::UserValue) { + // This flag table entry accepts a user-specified value. If + // the entry specifies UserRequired we must match only if a + // non-empty value is given. + int n = static_cast<int>(entry->commandFlag.length()); + if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 || + (entry->special & cmIDEFlagTable::CaseInsensitive && + cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) && + (!(entry->special & cmIDEFlagTable::UserRequired) || + static_cast<int>(strlen(pf)) > n)) { + this->FlagMapUpdate(entry, std::string(pf + n)); + entry_found = true; + } + } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 || + (entry->special & cmIDEFlagTable::CaseInsensitive && + cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) { + if (entry->special & cmIDEFlagTable::UserFollowing) { + // This flag expects a value in the following argument. + this->DoingFollowing = entry; + } else { + // This flag table entry provides a fixed value. + this->FlagMap[entry->IDEName] = entry->value; + } + entry_found = true; + } + + // If the flag has been handled by an entry not requesting a + // search continuation we are done. + if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) { + return true; + } + + // If the entry was found the flag has been handled. + flag_handled = flag_handled || entry_found; + } + + return false; +} + +void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, + std::string const& new_value) +{ + if (entry->special & cmIDEFlagTable::UserIgnored) { + // Ignore the user-specified value. + this->FlagMap[entry->IDEName] = entry->value; + } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) { + this->FlagMap[entry->IDEName].push_back(new_value); + } else if (entry->special & cmIDEFlagTable::SpaceAppendable) { + this->FlagMap[entry->IDEName].append_with_space(new_value); + } else if (entry->special & cmIDEFlagTable::CommaAppendable) { + this->FlagMap[entry->IDEName].append_with_comma(new_value); + } else { + // Use the user-specified value. + this->FlagMap[entry->IDEName] = new_value; + } +} + +void cmIDEOptions::AddDefine(const std::string& def) +{ + this->Defines.push_back(def); +} + +void cmIDEOptions::AddDefines(std::string const& defines) +{ + if (!defines.empty()) { + // Expand the list of definitions. + cmExpandList(defines, this->Defines); + } +} +void cmIDEOptions::AddDefines(const std::vector<std::string>& defines) +{ + cm::append(this->Defines, defines); +} + +std::vector<std::string> const& cmIDEOptions::GetDefines() const +{ + return this->Defines; +} + +void cmIDEOptions::AddInclude(const std::string& include) +{ + this->Includes.push_back(include); +} + +void cmIDEOptions::AddIncludes(std::string const& includes) +{ + if (!includes.empty()) { + // Expand the list of includes. + cmExpandList(includes, this->Includes); + } +} +void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes) +{ + cm::append(this->Includes, includes); +} + +std::vector<std::string> const& cmIDEOptions::GetIncludes() const +{ + return this->Includes; +} + +void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value) +{ + this->FlagMap[flag] = value; +} + +void cmIDEOptions::AddFlag(std::string const& flag, + std::vector<std::string> const& value) +{ + this->FlagMap[flag] = value; +} + +void cmIDEOptions::AppendFlag(std::string const& flag, + std::string const& value) +{ + this->FlagMap[flag].push_back(value); +} + +void cmIDEOptions::AppendFlag(std::string const& flag, + std::vector<std::string> const& value) +{ + FlagValue& fv = this->FlagMap[flag]; + std::copy(value.begin(), value.end(), std::back_inserter(fv)); +} + +void cmIDEOptions::AppendFlagString(std::string const& flag, + std::string const& value) +{ + this->FlagMap[flag].append_with_space(value); +} + +void cmIDEOptions::RemoveFlag(std::string const& flag) +{ + this->FlagMap.erase(flag); +} + +bool cmIDEOptions::HasFlag(std::string const& flag) const +{ + return this->FlagMap.find(flag) != this->FlagMap.end(); +} + +const char* cmIDEOptions::GetFlag(std::string const& flag) const +{ + // This method works only for single-valued flags! + auto i = this->FlagMap.find(flag); + if (i != this->FlagMap.cend() && i->second.size() == 1) { + return i->second[0].c_str(); + } + return nullptr; +} |