cmIDEOptions.cxx 6.0 KB

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