cmMathCommand.cxx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 "cmMathCommand.h"
  4. #include "cmExprParserHelper.h"
  5. #include "cmMakefile.h"
  6. #include "cm_kwiml.h"
  7. #include <stdio.h>
  8. class cmExecutionStatus;
  9. bool cmMathCommand::InitialPass(std::vector<std::string> const& args,
  10. cmExecutionStatus&)
  11. {
  12. if (args.empty()) {
  13. this->SetError("must be called with at least one argument.");
  14. return false;
  15. }
  16. const std::string& subCommand = args[0];
  17. if (subCommand == "EXPR") {
  18. return this->HandleExprCommand(args);
  19. }
  20. std::string e = "does not recognize sub-command " + subCommand;
  21. this->SetError(e);
  22. return false;
  23. }
  24. bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
  25. {
  26. if ((args.size() != 3) && (args.size() != 5)) {
  27. this->SetError("EXPR called with incorrect arguments.");
  28. return false;
  29. }
  30. enum class NumericFormat
  31. {
  32. UNINITIALIZED,
  33. DECIMAL,
  34. HEXADECIMAL,
  35. };
  36. const std::string& outputVariable = args[1];
  37. const std::string& expression = args[2];
  38. size_t argumentIndex = 3;
  39. NumericFormat outputFormat = NumericFormat::UNINITIALIZED;
  40. this->Makefile->AddDefinition(outputVariable, "ERROR");
  41. if (argumentIndex < args.size()) {
  42. const std::string messageHint = "sub-command EXPR ";
  43. const std::string option = args[argumentIndex++];
  44. if (option == "OUTPUT_FORMAT") {
  45. if (argumentIndex < args.size()) {
  46. const std::string argument = args[argumentIndex++];
  47. if (argument == "DECIMAL") {
  48. outputFormat = NumericFormat::DECIMAL;
  49. } else if (argument == "HEXADECIMAL") {
  50. outputFormat = NumericFormat::HEXADECIMAL;
  51. } else {
  52. std::string error = messageHint + "value \"" + argument +
  53. "\" for option \"" + option + "\" is invalid.";
  54. this->SetError(error);
  55. return false;
  56. }
  57. } else {
  58. std::string error =
  59. messageHint + "missing argument for option \"" + option + "\".";
  60. this->SetError(error);
  61. return false;
  62. }
  63. } else {
  64. std::string error =
  65. messageHint + "option \"" + option + "\" is unknown.";
  66. this->SetError(error);
  67. return false;
  68. }
  69. }
  70. if (outputFormat == NumericFormat::UNINITIALIZED) {
  71. outputFormat = NumericFormat::DECIMAL;
  72. }
  73. cmExprParserHelper helper;
  74. if (!helper.ParseString(expression.c_str(), 0)) {
  75. this->SetError(helper.GetError());
  76. return false;
  77. }
  78. char buffer[1024];
  79. const char* fmt;
  80. switch (outputFormat) {
  81. case NumericFormat::HEXADECIMAL:
  82. fmt = "0x%" KWIML_INT_PRIx64;
  83. break;
  84. case NumericFormat::DECIMAL:
  85. CM_FALLTHROUGH;
  86. default:
  87. fmt = "%" KWIML_INT_PRId64;
  88. break;
  89. }
  90. sprintf(buffer, fmt, helper.GetResult());
  91. this->Makefile->AddDefinition(outputVariable, buffer);
  92. return true;
  93. }