cmSeparateArgumentsCommand.cxx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 "cmSeparateArgumentsCommand.h"
  4. #include <algorithm>
  5. #include "cmExecutionStatus.h"
  6. #include "cmMakefile.h"
  7. #include "cmProperty.h"
  8. #include "cmStringAlgorithms.h"
  9. #include "cmSystemTools.h"
  10. // cmSeparateArgumentsCommand
  11. bool cmSeparateArgumentsCommand(std::vector<std::string> const& args,
  12. cmExecutionStatus& status)
  13. {
  14. if (args.empty()) {
  15. status.SetError("must be given at least one argument.");
  16. return false;
  17. }
  18. std::string var;
  19. std::string command;
  20. enum Mode
  21. {
  22. ModeOld,
  23. ModeUnix,
  24. ModeWindows
  25. };
  26. Mode mode = ModeOld;
  27. enum Doing
  28. {
  29. DoingNone,
  30. DoingVariable,
  31. DoingMode,
  32. DoingCommand
  33. };
  34. Doing doing = DoingVariable;
  35. for (std::string const& arg : args) {
  36. if (doing == DoingVariable) {
  37. var = arg;
  38. doing = DoingMode;
  39. // This will always clone one of the other blocks.
  40. // NOLINTNEXTLINE(bugprone-branch-clone)
  41. } else if (doing == DoingMode && arg == "NATIVE_COMMAND") {
  42. #ifdef _WIN32
  43. mode = ModeWindows;
  44. #else
  45. mode = ModeUnix;
  46. #endif
  47. doing = DoingCommand;
  48. } else if (doing == DoingMode && arg == "UNIX_COMMAND") {
  49. mode = ModeUnix;
  50. doing = DoingCommand;
  51. } else if (doing == DoingMode && arg == "WINDOWS_COMMAND") {
  52. mode = ModeWindows;
  53. doing = DoingCommand;
  54. } else if (doing == DoingCommand) {
  55. command = arg;
  56. doing = DoingNone;
  57. } else {
  58. status.SetError(cmStrCat("given unknown argument ", arg));
  59. return false;
  60. }
  61. }
  62. if (mode == ModeOld) {
  63. // Original space-replacement version of command.
  64. if (cmProp def = status.GetMakefile().GetDefinition(var)) {
  65. std::string value = *def;
  66. std::replace(value.begin(), value.end(), ' ', ';');
  67. status.GetMakefile().AddDefinition(var, value);
  68. }
  69. } else {
  70. // Parse the command line.
  71. std::vector<std::string> vec;
  72. if (mode == ModeUnix) {
  73. cmSystemTools::ParseUnixCommandLine(command.c_str(), vec);
  74. } else // if(mode == ModeWindows)
  75. {
  76. cmSystemTools::ParseWindowsCommandLine(command.c_str(), vec);
  77. }
  78. // Construct the result list value.
  79. std::string value;
  80. const char* sep = "";
  81. for (std::string const& vi : vec) {
  82. // Separate from the previous argument.
  83. value += sep;
  84. sep = ";";
  85. // Preserve semicolons.
  86. for (char si : vi) {
  87. if (si == ';') {
  88. value += '\\';
  89. }
  90. value += si;
  91. }
  92. }
  93. status.GetMakefile().AddDefinition(var, value);
  94. }
  95. return true;
  96. }