cmIDEOptions.cxx 7.3 KB

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