cmIDEOptions.cxx 7.1 KB

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