cmIDEOptions.cxx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmIDEOptions.h"
  4. #include <cstring>
  5. #include <iterator>
  6. #include <cmext/algorithm>
  7. #include "cmsys/String.h"
  8. #include "cmAlgorithms.h"
  9. #include "cmIDEFlagTable.h"
  10. #include "cmStringAlgorithms.h"
  11. cmIDEOptions::cmIDEOptions()
  12. {
  13. this->DoingDefine = false;
  14. this->AllowDefine = true;
  15. this->DoingInclude = false;
  16. this->AllowSlash = false;
  17. this->DoingFollowing = 0;
  18. for (int i = 0; i < FlagTableCount; ++i) {
  19. this->FlagTable[i] = 0;
  20. }
  21. }
  22. cmIDEOptions::~cmIDEOptions()
  23. {
  24. }
  25. void cmIDEOptions::HandleFlag(std::string const& flag)
  26. {
  27. // If the last option was -D then this option is the definition.
  28. if (this->DoingDefine) {
  29. this->DoingDefine = false;
  30. this->Defines.push_back(flag);
  31. return;
  32. }
  33. // If the last option was -I then this option is the include directory.
  34. if (this->DoingInclude) {
  35. this->DoingInclude = false;
  36. this->Includes.push_back(flag);
  37. return;
  38. }
  39. // If the last option expected a following value, this is it.
  40. if (this->DoingFollowing) {
  41. this->FlagMapUpdate(this->DoingFollowing, flag);
  42. this->DoingFollowing = 0;
  43. return;
  44. }
  45. // Look for known arguments.
  46. size_t len = flag.length();
  47. if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
  48. // Look for preprocessor definitions.
  49. if (this->AllowDefine && len > 1 && flag[1] == 'D') {
  50. if (len <= 2) {
  51. // The next argument will have the definition.
  52. this->DoingDefine = true;
  53. } else {
  54. // Store this definition.
  55. this->Defines.push_back(flag.substr(2));
  56. }
  57. return;
  58. }
  59. // Look for include directory.
  60. if (this->AllowInclude && len > 1 && flag[1] == 'I') {
  61. if (len <= 2) {
  62. // The next argument will have the include directory.
  63. this->DoingInclude = true;
  64. } else {
  65. // Store this include directory.
  66. this->Includes.push_back(flag.substr(2));
  67. }
  68. return;
  69. }
  70. // Look through the available flag tables.
  71. bool flag_handled = false;
  72. for (int i = 0; i < FlagTableCount && this->FlagTable[i]; ++i) {
  73. if (this->CheckFlagTable(this->FlagTable[i], flag, flag_handled)) {
  74. return;
  75. }
  76. }
  77. // If any map entry handled the flag we are done.
  78. if (flag_handled) {
  79. return;
  80. }
  81. }
  82. // This option is not known. Store it in the output flags.
  83. this->StoreUnknownFlag(flag);
  84. }
  85. bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
  86. std::string const& flag, bool& flag_handled)
  87. {
  88. const char* pf = flag.c_str() + 1;
  89. // Look for an entry in the flag table matching this flag.
  90. for (cmIDEFlagTable const* entry = table; !entry->IDEName.empty(); ++entry) {
  91. bool entry_found = false;
  92. if (entry->special & cmIDEFlagTable::UserValue) {
  93. // This flag table entry accepts a user-specified value. If
  94. // the entry specifies UserRequired we must match only if a
  95. // non-empty value is given.
  96. int n = static_cast<int>(entry->commandFlag.length());
  97. if ((strncmp(pf, entry->commandFlag.c_str(), n) == 0 ||
  98. (entry->special & cmIDEFlagTable::CaseInsensitive &&
  99. cmsysString_strncasecmp(pf, entry->commandFlag.c_str(), n))) &&
  100. (!(entry->special & cmIDEFlagTable::UserRequired) ||
  101. static_cast<int>(strlen(pf)) > n)) {
  102. this->FlagMapUpdate(entry, std::string(pf + n));
  103. entry_found = true;
  104. }
  105. } else if (strcmp(pf, entry->commandFlag.c_str()) == 0 ||
  106. (entry->special & cmIDEFlagTable::CaseInsensitive &&
  107. cmsysString_strcasecmp(pf, entry->commandFlag.c_str()) == 0)) {
  108. if (entry->special & cmIDEFlagTable::UserFollowing) {
  109. // This flag expects a value in the following argument.
  110. this->DoingFollowing = entry;
  111. } else {
  112. // This flag table entry provides a fixed value.
  113. this->FlagMap[entry->IDEName] = entry->value;
  114. }
  115. entry_found = true;
  116. }
  117. // If the flag has been handled by an entry not requesting a
  118. // search continuation we are done.
  119. if (entry_found && !(entry->special & cmIDEFlagTable::Continue)) {
  120. return true;
  121. }
  122. // If the entry was found the flag has been handled.
  123. flag_handled = flag_handled || entry_found;
  124. }
  125. return false;
  126. }
  127. void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
  128. std::string const& new_value)
  129. {
  130. if (entry->special & cmIDEFlagTable::UserIgnored) {
  131. // Ignore the user-specified value.
  132. this->FlagMap[entry->IDEName] = entry->value;
  133. } else if (entry->special & cmIDEFlagTable::SemicolonAppendable) {
  134. this->FlagMap[entry->IDEName].push_back(new_value);
  135. } else if (entry->special & cmIDEFlagTable::SpaceAppendable) {
  136. this->FlagMap[entry->IDEName].append_with_space(new_value);
  137. } else if (entry->special & cmIDEFlagTable::CommaAppendable) {
  138. this->FlagMap[entry->IDEName].append_with_comma(new_value);
  139. } else {
  140. // Use the user-specified value.
  141. this->FlagMap[entry->IDEName] = new_value;
  142. }
  143. }
  144. void cmIDEOptions::AddDefine(const std::string& def)
  145. {
  146. this->Defines.push_back(def);
  147. }
  148. void cmIDEOptions::AddDefines(std::string const& defines)
  149. {
  150. if (!defines.empty()) {
  151. // Expand the list of definitions.
  152. cmExpandList(defines, this->Defines);
  153. }
  154. }
  155. void cmIDEOptions::AddDefines(const std::vector<std::string>& defines)
  156. {
  157. cm::append(this->Defines, defines);
  158. }
  159. std::vector<std::string> const& cmIDEOptions::GetDefines() const
  160. {
  161. return this->Defines;
  162. }
  163. void cmIDEOptions::AddInclude(const std::string& include)
  164. {
  165. this->Includes.push_back(include);
  166. }
  167. void cmIDEOptions::AddIncludes(std::string const& includes)
  168. {
  169. if (!includes.empty()) {
  170. // Expand the list of includes.
  171. cmExpandList(includes, this->Includes);
  172. }
  173. }
  174. void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
  175. {
  176. cm::append(this->Includes, includes);
  177. }
  178. std::vector<std::string> const& cmIDEOptions::GetIncludes() const
  179. {
  180. return this->Includes;
  181. }
  182. void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
  183. {
  184. this->FlagMap[flag] = value;
  185. }
  186. void cmIDEOptions::AddFlag(std::string const& flag,
  187. std::vector<std::string> const& value)
  188. {
  189. this->FlagMap[flag] = value;
  190. }
  191. void cmIDEOptions::AppendFlag(std::string const& flag,
  192. std::string const& value)
  193. {
  194. this->FlagMap[flag].push_back(value);
  195. }
  196. void cmIDEOptions::AppendFlag(std::string const& flag,
  197. std::vector<std::string> const& value)
  198. {
  199. FlagValue& fv = this->FlagMap[flag];
  200. std::copy(value.begin(), value.end(), std::back_inserter(fv));
  201. }
  202. void cmIDEOptions::AppendFlagString(std::string const& flag,
  203. std::string const& value)
  204. {
  205. this->FlagMap[flag].append_with_space(value);
  206. }
  207. void cmIDEOptions::RemoveFlag(std::string const& flag)
  208. {
  209. this->FlagMap.erase(flag);
  210. }
  211. bool cmIDEOptions::HasFlag(std::string const& flag) const
  212. {
  213. return this->FlagMap.find(flag) != this->FlagMap.end();
  214. }
  215. const char* cmIDEOptions::GetFlag(std::string const& flag) const
  216. {
  217. // This method works only for single-valued flags!
  218. std::map<std::string, FlagValue>::const_iterator i =
  219. this->FlagMap.find(flag);
  220. if (i != this->FlagMap.cend() && i->second.size() == 1) {
  221. return i->second[0].c_str();
  222. }
  223. return nullptr;
  224. }