blob: f94faf88b8536d2256581e76e1731a4f38ef5895 [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"
Marc Chevrier24130412023-04-25 19:54:23 +020015#include "cmList.h"
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +020016#include "cmStringAlgorithms.h"
Brad King4ca9df82016-01-08 14:30:06 -050017
Brad King5b85a582009-07-29 11:29:08 -040018cmIDEOptions::cmIDEOptions()
19{
20 this->DoingDefine = false;
21 this->AllowDefine = true;
Marc Chevrier3073bd12017-12-19 16:03:41 +010022 this->DoingInclude = false;
Brad King5b85a582009-07-29 11:29:08 -040023 this->AllowSlash = false;
Ben Boeckel1b929ba2022-11-22 13:51:48 -050024 this->DoingFollowing = nullptr;
Ben Boeckel1f893e52022-11-23 08:31:18 -050025 for (auto& flag : this->FlagTable) {
26 flag = nullptr;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040027 }
Brad King5b85a582009-07-29 11:29:08 -040028}
29
Ben Boeckel83d685e2022-11-22 13:39:20 -050030cmIDEOptions::~cmIDEOptions() = default;
Brad King5b85a582009-07-29 11:29:08 -040031
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050032void cmIDEOptions::HandleFlag(std::string const& flag)
Brad King5b85a582009-07-29 11:29:08 -040033{
34 // If the last option was -D then this option is the definition.
Kitware Robotd9fd2f52016-05-16 10:34:04 -040035 if (this->DoingDefine) {
Brad King5b85a582009-07-29 11:29:08 -040036 this->DoingDefine = false;
37 this->Defines.push_back(flag);
38 return;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040039 }
Brad King5b85a582009-07-29 11:29:08 -040040
Marc Chevrier3073bd12017-12-19 16:03:41 +010041 // If the last option was -I then this option is the include directory.
42 if (this->DoingInclude) {
43 this->DoingInclude = false;
44 this->Includes.push_back(flag);
45 return;
46 }
47
Brad King650199e2014-04-01 14:56:08 -040048 // If the last option expected a following value, this is it.
Kitware Robotd9fd2f52016-05-16 10:34:04 -040049 if (this->DoingFollowing) {
Brad King650199e2014-04-01 14:56:08 -040050 this->FlagMapUpdate(this->DoingFollowing, flag);
Ben Boeckel1b929ba2022-11-22 13:51:48 -050051 this->DoingFollowing = nullptr;
Brad King650199e2014-04-01 14:56:08 -040052 return;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040053 }
Brad King650199e2014-04-01 14:56:08 -040054
Brad King5b85a582009-07-29 11:29:08 -040055 // Look for known arguments.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050056 size_t len = flag.length();
57 if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
Brad King5b85a582009-07-29 11:29:08 -040058 // Look for preprocessor definitions.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050059 if (this->AllowDefine && len > 1 && flag[1] == 'D') {
60 if (len <= 2) {
Brad King5b85a582009-07-29 11:29:08 -040061 // The next argument will have the definition.
62 this->DoingDefine = true;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040063 } else {
Brad King5b85a582009-07-29 11:29:08 -040064 // Store this definition.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050065 this->Defines.push_back(flag.substr(2));
Brad King5b85a582009-07-29 11:29:08 -040066 }
Kitware Robotd9fd2f52016-05-16 10:34:04 -040067 return;
68 }
Marc Chevrier3073bd12017-12-19 16:03:41 +010069 // Look for include directory.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050070 if (this->AllowInclude && len > 1 && flag[1] == 'I') {
71 if (len <= 2) {
Marc Chevrier3073bd12017-12-19 16:03:41 +010072 // The next argument will have the include directory.
73 this->DoingInclude = true;
74 } else {
75 // Store this include directory.
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -050076 this->Includes.push_back(flag.substr(2));
Marc Chevrier3073bd12017-12-19 16:03:41 +010077 }
78 return;
79 }
Brad King5b85a582009-07-29 11:29:08 -040080
81 // Look through the available flag tables.
82 bool flag_handled = false;
Kitware Robotd9fd2f52016-05-16 10:34:04 -040083 for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) {
84 if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) {
Brad King5b85a582009-07-29 11:29:08 -040085 return;
Brad King5b85a582009-07-29 11:29:08 -040086 }
87 }
88
Kitware Robotd9fd2f52016-05-16 10:34:04 -040089 // If any map entry handled the flag we are done.
90 if (flag_handled) {
91 return;
92 }
93 }
94
Brad King5b85a582009-07-29 11:29:08 -040095 // This option is not known. Store it in the output flags.
96 this->StoreUnknownFlag(flag);
97}
98
Brad King5b85a582009-07-29 11:29:08 -040099bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500100 std::string const& flag, bool& flag_handled)
Brad King5b85a582009-07-29 11:29:08 -0400101{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500102 const char* pf = flag.c_str() + 1;
Brad King5b85a582009-07-29 11:29:08 -0400103 // Look for an entry in the flag table matching this flag.
Stephan Szabo82793022018-11-20 10:09:57 -0800104 for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) {
Brad King5b85a582009-07-29 11:29:08 -0400105 bool entry_found = false;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400106 if (entry->special & cmIDEFlagTable::UserValue) {
Brad King5b85a582009-07-29 11:29:08 -0400107 // This flag table entry accepts a user-specified value. If
108 // the entry specifies UserRequired we must match only if a
109 // non-empty value is given.
Stephan Szabo82793022018-11-20 10:09:57 -0800110 int n = static_cast<int>(entry->commandFlag.length());
111 if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 ||
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400112 (entry->special & cmIDEFlagTable::CaseInsensitive &&
Stephan Szabo82793022018-11-20 10:09:57 -0800113 cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) &&
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400114 (!(entry->special & cmIDEFlagTable::UserRequired) ||
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500115 static_cast<int>(strlen(pf)) > n)) {
116 this->FlagMapUpdate(entry, std::string(pf + n));
Brad King5b85a582009-07-29 11:29:08 -0400117 entry_found = true;
Brad King5b85a582009-07-29 11:29:08 -0400118 }
Stephan Szabo82793022018-11-20 10:09:57 -0800119 } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 ||
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400120 (entry->special & cmIDEFlagTable::CaseInsensitive &&
Stephan Szabo82793022018-11-20 10:09:57 -0800121 cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) {
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400122 if (entry->special & cmIDEFlagTable::UserFollowing) {
Brad King650199e2014-04-01 14:56:08 -0400123 // This flag expects a value in the following argument.
124 this->DoingFollowing = entry;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400125 } else {
Brad King650199e2014-04-01 14:56:08 -0400126 // This flag table entry provides a fixed value.
127 this->FlagMap[entry->IDEName] = entry->value;
Brad King5b85a582009-07-29 11:29:08 -0400128 }
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400129 entry_found = true;
130 }
Brad King5b85a582009-07-29 11:29:08 -0400131
132 // If the flag has been handled by an entry not requesting a
133 // search continuation we are done.
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400134 if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) {
Brad King5b85a582009-07-29 11:29:08 -0400135 return true;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400136 }
Brad King5b85a582009-07-29 11:29:08 -0400137
138 // If the entry was found the flag has been handled.
139 flag_handled = flag_handled || entry_found;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400140 }
Brad King5b85a582009-07-29 11:29:08 -0400141
142 return false;
143}
144
Brad Kingf2a3dd92014-04-01 14:54:28 -0400145void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500146 std::string const& new_value)
Brad Kingf2a3dd92014-04-01 14:54:28 -0400147{
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400148 if (entry->special & cmIDEFlagTable::UserIgnored) {
Brad Kingf2a3dd92014-04-01 14:54:28 -0400149 // Ignore the user-specified value.
150 this->FlagMap[entry->IDEName] = entry->value;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400151 } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
Brad King1c209ac2014-07-23 11:13:13 -0400152 this->FlagMap[entry->IDEName].push_back(new_value);
Brad King3936a282017-02-15 09:35:36 -0500153 } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
154 this->FlagMap[entry->IDEName].append_with_space(new_value);
Wil Stark82269792019-02-05 15:12:38 -0800155 } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
156 this->FlagMap[entry->IDEName].append_with_comma(new_value);
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400157 } else {
Brad Kingf2a3dd92014-04-01 14:54:28 -0400158 // Use the user-specified value.
159 this->FlagMap[entry->IDEName] = new_value;
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400160 }
Brad Kingf2a3dd92014-04-01 14:54:28 -0400161}
162
Brad King5b85a582009-07-29 11:29:08 -0400163void cmIDEOptions::AddDefine(const std::string& def)
164{
165 this->Defines.push_back(def);
166}
167
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500168void cmIDEOptions::AddDefines(std::string const& defines)
Brad King5b85a582009-07-29 11:29:08 -0400169{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500170 if (!defines.empty()) {
Brad King5b85a582009-07-29 11:29:08 -0400171 // Expand the list of definitions.
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +0200172 cmExpandList(defines, this->Defines);
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400173 }
Brad King5b85a582009-07-29 11:29:08 -0400174}
Kitware Robotd9fd2f52016-05-16 10:34:04 -0400175void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
Stephen Kellyafc9243c2013-07-10 15:22:59 +0200176{
Marc Chevrierf7d12602019-12-09 17:39:29 +0100177 cm::append(this->Defines, defines);
Stephen Kellyafc9243c2013-07-10 15:22:59 +0200178}
Brad King5b85a582009-07-29 11:29:08 -0400179
Brad King8a619e82017-03-28 12:55:14 -0400180std::vector<std::string> const& cmIDEOptions::GetDefines() const
181{
182 return this->Defines;
183}
184
Marc Chevrier3073bd12017-12-19 16:03:41 +0100185void cmIDEOptions::AddInclude(const std::string& include)
186{
187 this->Includes.push_back(include);
188}
189
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500190void cmIDEOptions::AddIncludes(std::string const& includes)
Marc Chevrier3073bd12017-12-19 16:03:41 +0100191{
Vitaly Stakhovsky8182ebc2018-02-26 11:24:45 -0500192 if (!includes.empty()) {
Marc Chevrier3073bd12017-12-19 16:03:41 +0100193 // Expand the list of includes.
Sebastian Holtermannf4f3c682019-08-11 11:56:59 +0200194 cmExpandList(includes, this->Includes);
Marc Chevrier3073bd12017-12-19 16:03:41 +0100195 }
196}
197void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
198{
Marc Chevrierf7d12602019-12-09 17:39:29 +0100199 cm::append(this->Includes, includes);
Marc Chevrier3073bd12017-12-19 16:03:41 +0100200}
201
202std::vector<std::string> const& cmIDEOptions::GetIncludes() const
203{
204 return this->Includes;
205}
206
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500207void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
Brad King5b85a582009-07-29 11:29:08 -0400208{
209 this->FlagMap[flag] = value;
210}
David Cole98b448e2011-02-09 12:59:09 -0500211
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500212void cmIDEOptions::AddFlag(std::string const& flag,
Brad King1c209ac2014-07-23 11:13:13 -0400213 std::vector<std::string> const& value)
214{
215 this->FlagMap[flag] = value;
216}
217
Brad King29410df2014-07-31 14:02:03 -0400218void cmIDEOptions::AppendFlag(std::string const& flag,
219 std::string const& value)
220{
221 this->FlagMap[flag].push_back(value);
222}
223
Brad King84100102014-08-13 13:39:35 -0400224void cmIDEOptions::AppendFlag(std::string const& flag,
225 std::vector<std::string> const& value)
226{
227 FlagValue& fv = this->FlagMap[flag];
228 std::copy(value.begin(), value.end(), std::back_inserter(fv));
229}
230
Brad King3936a282017-02-15 09:35:36 -0500231void cmIDEOptions::AppendFlagString(std::string const& flag,
232 std::string const& value)
233{
234 this->FlagMap[flag].append_with_space(value);
235}
236
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500237void cmIDEOptions::RemoveFlag(std::string const& flag)
David Cole98b448e2011-02-09 12:59:09 -0500238{
239 this->FlagMap.erase(flag);
240}
Brad Kingc65a2ea2012-10-26 10:16:45 -0400241
Brad King9633d112014-08-13 14:07:07 -0400242bool cmIDEOptions::HasFlag(std::string const& flag) const
243{
244 return this->FlagMap.find(flag) != this->FlagMap.end();
245}
246
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500247const char* cmIDEOptions::GetFlag(std::string const& flag) const
Brad Kingc65a2ea2012-10-26 10:16:45 -0400248{
Brad King1c209ac2014-07-23 11:13:13 -0400249 // This method works only for single-valued flags!
Ben Boeckelc61ece52022-11-22 13:56:03 -0500250 auto i = this->FlagMap.find(flag);
Vitaly Stakhovskyc62ffdc2017-12-08 22:30:16 -0500251 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}