blob: bb36db3f35043976f7a46a0db7cacb8d6457600a [file] [log] [blame]
Brad King86578ec2016-09-27 15:01:08 -04001/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
Brad King5b85a582009-07-29 11:29:08 -04003#include "cmIDEOptions.h"
4
NAKAMURA Takumi0e58a5e2021-11-14 19:58:11 +09005#include <algorithm>
Rose6f4727a2021-10-23 11:27:46 -04006#include <cstring>
Daniel Pfeifer66a70992016-11-25 22:54:58 +01007#include <iterator>
NAKAMURA Takumi0e58a5e2021-11-14 19:58:11 +09008#include <utility>
Kitware Roboted982092019-09-30 10:46:28 -04009
Marc Chevrierf7d12602019-12-09 17:39:29 +010010#include <cmext/algorithm>
11
Kitware Roboted982092019-09-30 10:46:28 -040012#include "cmsys/String.h"
13
Daniel Pfeifer66a70992016-11-25 22:54:58 +010014#include "cmIDEFlagTable.h"
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +020015#include "cmStringAlgorithms.h"
Brad King4ca9df82016-01-08 14:30:06 -050016
Brad King5b85a582009-07-29 11:29:08 -040017cmIDEOptions::cmIDEOptions()
18{
19 this->DoingDefine = false;
20 this->AllowDefine = true;
Marc Chevrier3073bd12017-12-19 16:03:41 +010021 this->DoingInclude = false;
Brad King5b85a582009-07-29 11:29:08 -040022 this->AllowSlash = false;
Ben Boeckel1b929ba2022-11-22 13:51:48 -050023 this->DoingFollowing = nullptr;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040024 for (int i = 0; i < FlagTableCount; ++i) {
Ben Boeckel1b929ba2022-11-22 13:51:48 -050025 this->FlagTable[i] = nullptr;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040026 }
Brad King5b85a582009-07-29 11:29:08 -040027}
28
Ben Boeckel83d685e2022-11-22 13:39:20 -050029cmIDEOptions::~cmIDEOptions() = default;
Brad King5b85a582009-07-29 11:29:08 -040030
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050031void cmIDEOptions::HandleFlag(std::string const& flag)
Brad King5b85a582009-07-29 11:29:08 -040032{
33 // If the last option was -D then this option is the definition.
Kitware Robotd9fd2f52016-05-16 10:34:04 -040034 if (this->DoingDefine) {
Brad King5b85a582009-07-29 11:29:08 -040035 this->DoingDefine = false;
36 this->Defines.push_back(flag);
37 return;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040038 }
Brad King5b85a582009-07-29 11:29:08 -040039
Marc Chevrier3073bd12017-12-19 16:03:41 +010040 // If the last option was -I then this option is the include directory.
41 if (this->DoingInclude) {
42 this->DoingInclude = false;
43 this->Includes.push_back(flag);
44 return;
45 }
46
Brad King650199e2014-04-01 14:56:08 -040047 // If the last option expected a following value, this is it.
Kitware Robotd9fd2f52016-05-16 10:34:04 -040048 if (this->DoingFollowing) {
Brad King650199e2014-04-01 14:56:08 -040049 this->FlagMapUpdate(this->DoingFollowing, flag);
Ben Boeckel1b929ba2022-11-22 13:51:48 -050050 this->DoingFollowing = nullptr;
Brad King650199e2014-04-01 14:56:08 -040051 return;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040052 }
Brad King650199e2014-04-01 14:56:08 -040053
Brad King5b85a582009-07-29 11:29:08 -040054 // Look for known arguments.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050055 size_t len = flag.length();
56 if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
Brad King5b85a582009-07-29 11:29:08 -040057 // Look for preprocessor definitions.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050058 if (this->AllowDefine && len > 1 && flag[1] == 'D') {
59 if (len <= 2) {
Brad King5b85a582009-07-29 11:29:08 -040060 // The next argument will have the definition.
61 this->DoingDefine = true;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040062 } else {
Brad King5b85a582009-07-29 11:29:08 -040063 // Store this definition.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050064 this->Defines.push_back(flag.substr(2));
Brad King5b85a582009-07-29 11:29:08 -040065 }
Kitware Robotd9fd2f52016-05-16 10:34:04 -040066 return;
67 }
Marc Chevrier3073bd12017-12-19 16:03:41 +010068 // Look for include directory.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050069 if (this->AllowInclude && len > 1 && flag[1] == 'I') {
70 if (len <= 2) {
Marc Chevrier3073bd12017-12-19 16:03:41 +010071 // The next argument will have the include directory.
72 this->DoingInclude = true;
73 } else {
74 // Store this include directory.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050075 this->Includes.push_back(flag.substr(2));
Marc Chevrier3073bd12017-12-19 16:03:41 +010076 }
77 return;
78 }
Brad King5b85a582009-07-29 11:29:08 -040079
80 // Look through the available flag tables.
81 bool flag_handled = false;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040082 for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) {
83 if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) {
Brad King5b85a582009-07-29 11:29:08 -040084 return;
Brad King5b85a582009-07-29 11:29:08 -040085 }
86 }
87
Kitware Robotd9fd2f52016-05-16 10:34:04 -040088 // If any map entry handled the flag we are done.
89 if (flag_handled) {
90 return;
91 }
92 }
93
Brad King5b85a582009-07-29 11:29:08 -040094 // This option is not known. Store it in the output flags.
95 this->StoreUnknownFlag(flag);
96}
97
Brad King5b85a582009-07-29 11:29:08 -040098bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050099 std::string const& flag, bool& flag_handled)
Brad King5b85a582009-07-29 11:29:08 -0400100{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500101 const char* pf = flag.c_str() + 1;
Brad King5b85a582009-07-29 11:29:08 -0400102 // Look for an entry in the flag table matching this flag.
Stephan Szabo82793022018-11-20 10:09:57 -0800103 for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) {
Brad King5b85a582009-07-29 11:29:08 -0400104 bool entry_found = false;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400105 if (entry->special & cmIDEFlagTable::UserValue) {
Brad King5b85a582009-07-29 11:29:08 -0400106 // This flag table entry accepts a user-specified value. If
107 // the entry specifies UserRequired we must match only if a
108 // non-empty value is given.
Stephan Szabo82793022018-11-20 10:09:57 -0800109 int n = static_cast<int>(entry->commandFlag.length());
110 if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 ||
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400111 (entry->special & cmIDEFlagTable::CaseInsensitive &&
Stephan Szabo82793022018-11-20 10:09:57 -0800112 cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) &&
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400113 (!(entry->special & cmIDEFlagTable::UserRequired) ||
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500114 static_cast<int>(strlen(pf)) > n)) {
115 this->FlagMapUpdate(entry, std::string(pf + n));
Brad King5b85a582009-07-29 11:29:08 -0400116 entry_found = true;
Brad King5b85a582009-07-29 11:29:08 -0400117 }
Stephan Szabo82793022018-11-20 10:09:57 -0800118 } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 ||
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400119 (entry->special & cmIDEFlagTable::CaseInsensitive &&
Stephan Szabo82793022018-11-20 10:09:57 -0800120 cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) {
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400121 if (entry->special & cmIDEFlagTable::UserFollowing) {
Brad King650199e2014-04-01 14:56:08 -0400122 // This flag expects a value in the following argument.
123 this->DoingFollowing = entry;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400124 } else {
Brad King650199e2014-04-01 14:56:08 -0400125 // This flag table entry provides a fixed value.
126 this->FlagMap[entry->IDEName] = entry->value;
Brad King5b85a582009-07-29 11:29:08 -0400127 }
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400128 entry_found = true;
129 }
Brad King5b85a582009-07-29 11:29:08 -0400130
131 // If the flag has been handled by an entry not requesting a
132 // search continuation we are done.
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400133 if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) {
Brad King5b85a582009-07-29 11:29:08 -0400134 return true;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400135 }
Brad King5b85a582009-07-29 11:29:08 -0400136
137 // If the entry was found the flag has been handled.
138 flag_handled = flag_handled || entry_found;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400139 }
Brad King5b85a582009-07-29 11:29:08 -0400140
141 return false;
142}
143
Brad Kingf2a3dd92014-04-01 14:54:28 -0400144void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500145 std::string const& new_value)
Brad Kingf2a3dd92014-04-01 14:54:28 -0400146{
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400147 if (entry->special & cmIDEFlagTable::UserIgnored) {
Brad Kingf2a3dd92014-04-01 14:54:28 -0400148 // Ignore the user-specified value.
149 this->FlagMap[entry->IDEName] = entry->value;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400150 } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
Brad King1c209ac2014-07-23 11:13:13 -0400151 this->FlagMap[entry->IDEName].push_back(new_value);
Brad King3936a282017-02-15 09:35:36 -0500152 } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
153 this->FlagMap[entry->IDEName].append_with_space(new_value);
Wil Stark82269792019-02-05 15:12:38 -0800154 } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
155 this->FlagMap[entry->IDEName].append_with_comma(new_value);
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400156 } else {
Brad Kingf2a3dd92014-04-01 14:54:28 -0400157 // Use the user-specified value.
158 this->FlagMap[entry->IDEName] = new_value;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400159 }
Brad Kingf2a3dd92014-04-01 14:54:28 -0400160}
161
Brad King5b85a582009-07-29 11:29:08 -0400162void cmIDEOptions::AddDefine(const std::string& def)
163{
164 this->Defines.push_back(def);
165}
166
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500167void cmIDEOptions::AddDefines(std::string const& defines)
Brad King5b85a582009-07-29 11:29:08 -0400168{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500169 if (!defines.empty()) {
Brad King5b85a582009-07-29 11:29:08 -0400170 // Expand the list of definitions.
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +0200171 cmExpandList(defines, this->Defines);
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400172 }
Brad King5b85a582009-07-29 11:29:08 -0400173}
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400174void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
Stephen Kellyafc9243c2013-07-10 15:22:59 +0200175{
Marc Chevrierf7d12602019-12-09 17:39:29 +0100176 cm::append(this->Defines, defines);
Stephen Kellyafc9243c2013-07-10 15:22:59 +0200177}
Brad King5b85a582009-07-29 11:29:08 -0400178
Brad King8a619e82017-03-28 12:55:14 -0400179std::vector<std::string> const& cmIDEOptions::GetDefines() const
180{
181 return this->Defines;
182}
183
Marc Chevrier3073bd12017-12-19 16:03:41 +0100184void cmIDEOptions::AddInclude(const std::string& include)
185{
186 this->Includes.push_back(include);
187}
188
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500189void cmIDEOptions::AddIncludes(std::string const& includes)
Marc Chevrier3073bd12017-12-19 16:03:41 +0100190{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500191 if (!includes.empty()) {
Marc Chevrier3073bd12017-12-19 16:03:41 +0100192 // Expand the list of includes.
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +0200193 cmExpandList(includes, this->Includes);
Marc Chevrier3073bd12017-12-19 16:03:41 +0100194 }
195}
196void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
197{
Marc Chevrierf7d12602019-12-09 17:39:29 +0100198 cm::append(this->Includes, includes);
Marc Chevrier3073bd12017-12-19 16:03:41 +0100199}
200
201std::vector<std::string> const& cmIDEOptions::GetIncludes() const
202{
203 return this->Includes;
204}
205
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500206void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
Brad King5b85a582009-07-29 11:29:08 -0400207{
208 this->FlagMap[flag] = value;
209}
David Cole98b448e2011-02-09 12:59:09 -0500210
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500211void cmIDEOptions::AddFlag(std::string const& flag,
Brad King1c209ac2014-07-23 11:13:13 -0400212 std::vector<std::string> const& value)
213{
214 this->FlagMap[flag] = value;
215}
216
Brad King29410df2014-07-31 14:02:03 -0400217void cmIDEOptions::AppendFlag(std::string const& flag,
218 std::string const& value)
219{
220 this->FlagMap[flag].push_back(value);
221}
222
Brad King84100102014-08-13 13:39:35 -0400223void cmIDEOptions::AppendFlag(std::string const& flag,
224 std::vector<std::string> const& value)
225{
226 FlagValue& fv = this->FlagMap[flag];
227 std::copy(value.begin(), value.end(), std::back_inserter(fv));
228}
229
Brad King3936a282017-02-15 09:35:36 -0500230void cmIDEOptions::AppendFlagString(std::string const& flag,
231 std::string const& value)
232{
233 this->FlagMap[flag].append_with_space(value);
234}
235
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500236void cmIDEOptions::RemoveFlag(std::string const& flag)
David Cole98b448e2011-02-09 12:59:09 -0500237{
238 this->FlagMap.erase(flag);
239}
Brad Kingc65a2ea2012-10-26 10:16:45 -0400240
Brad King9633d112014-08-13 14:07:07 -0400241bool cmIDEOptions::HasFlag(std::string const& flag) const
242{
243 return this->FlagMap.find(flag) != this->FlagMap.end();
244}
245
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500246const char* cmIDEOptions::GetFlag(std::string const& flag) const
Brad Kingc65a2ea2012-10-26 10:16:45 -0400247{
Brad King1c209ac2014-07-23 11:13:13 -0400248 // This method works only for single-valued flags!
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500249 std::map<std::string, FlagValue>::const_iterator i =
250 this->FlagMap.find(flag);
251 if (i != this->FlagMap.cend() && i->second.size() == 1) {
Brad King1c209ac2014-07-23 11:13:13 -0400252 return i->second[0].c_str();
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400253 }
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500254 return nullptr;
Brad Kingc65a2ea2012-10-26 10:16:45 -0400255}