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"
7 #include <cm3p/kwiml/int.h>
9 #include "cmExecutionStatus.h"
10 #include "cmExprParserHelper.h"
11 #include "cmMakefile.h"
12 #include "cmMessageType.h"
15 bool HandleExprCommand(std::vector<std::string> const& args,
16 cmExecutionStatus& status);
19 bool cmMathCommand(std::vector<std::string> const& args,
20 cmExecutionStatus& status)
23 status.SetError("must be called with at least one argument.");
26 const std::string& subCommand = args[0];
27 if (subCommand == "EXPR") {
28 return HandleExprCommand(args, status);
30 std::string e = "does not recognize sub-command " + subCommand;
36 bool HandleExprCommand(std::vector<std::string> const& args,
37 cmExecutionStatus& status)
39 if ((args.size() != 3) && (args.size() != 5)) {
40 status.SetError("EXPR called with incorrect arguments.");
44 enum class NumericFormat
51 const std::string& outputVariable = args[1];
52 const std::string& expression = args[2];
53 size_t argumentIndex = 3;
54 NumericFormat outputFormat = NumericFormat::UNINITIALIZED;
56 status.GetMakefile().AddDefinition(outputVariable, "ERROR");
58 if (argumentIndex < args.size()) {
59 const std::string messageHint = "sub-command EXPR ";
60 std::string const& option = args[argumentIndex++];
61 if (option == "OUTPUT_FORMAT") {
62 if (argumentIndex < args.size()) {
63 std::string const& argument = args[argumentIndex++];
64 if (argument == "DECIMAL") {
65 outputFormat = NumericFormat::DECIMAL;
66 } else if (argument == "HEXADECIMAL") {
67 outputFormat = NumericFormat::HEXADECIMAL;
69 std::string error = messageHint + "value \"" + argument +
70 "\" for option \"" + option + "\" is invalid.";
71 status.SetError(error);
76 messageHint + "missing argument for option \"" + option + "\".";
77 status.SetError(error);
82 messageHint + "option \"" + option + "\" is unknown.";
83 status.SetError(error);
88 if (outputFormat == NumericFormat::UNINITIALIZED) {
89 outputFormat = NumericFormat::DECIMAL;
92 cmExprParserHelper helper;
93 if (!helper.ParseString(expression.c_str(), 0)) {
94 status.SetError(helper.GetError());
100 switch (outputFormat) {
101 case NumericFormat::HEXADECIMAL:
102 fmt = "0x%" KWIML_INT_PRIx64;
104 case NumericFormat::DECIMAL:
107 fmt = "%" KWIML_INT_PRId64;
110 snprintf(buffer, sizeof(buffer), fmt, helper.GetResult());
112 std::string const& w = helper.GetWarning();
114 status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w);
117 status.GetMakefile().AddDefinition(outputVariable, buffer);