| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file Copyright.txt or https://cmake.org/licensing for details. */ | |
| #include "cmMathCommand.h" | |
| #include <cstdio> | |
| #include <cm3p/kwiml/int.h> | |
| #include "cmExecutionStatus.h" | |
| #include "cmExprParserHelper.h" | |
| #include "cmMakefile.h" | |
| #include "cmMessageType.h" | |
| namespace { | |
| bool HandleExprCommand(std::vector<std::string> const& args, | |
| cmExecutionStatus& status); | |
| } | |
| bool cmMathCommand(std::vector<std::string> const& args, | |
| cmExecutionStatus& status) | |
| { | |
| if (args.empty()) { | |
| status.SetError("must be called with at least one argument."); | |
| return false; | |
| } | |
| const std::string& subCommand = args[0]; | |
| if (subCommand == "EXPR") { | |
| return HandleExprCommand(args, status); | |
| } | |
| std::string e = "does not recognize sub-command " + subCommand; | |
| status.SetError(e); | |
| return false; | |
| } | |
| namespace { | |
| bool HandleExprCommand(std::vector<std::string> const& args, | |
| cmExecutionStatus& status) | |
| { | |
| if ((args.size() != 3) && (args.size() != 5)) { | |
| status.SetError("EXPR called with incorrect arguments."); | |
| return false; | |
| } | |
| enum class NumericFormat | |
| { | |
| UNINITIALIZED, | |
| DECIMAL, | |
| HEXADECIMAL, | |
| }; | |
| const std::string& outputVariable = args[1]; | |
| const std::string& expression = args[2]; | |
| size_t argumentIndex = 3; | |
| NumericFormat outputFormat = NumericFormat::UNINITIALIZED; | |
| status.GetMakefile().AddDefinition(outputVariable, "ERROR"); | |
| if (argumentIndex < args.size()) { | |
| const std::string messageHint = "sub-command EXPR "; | |
| const std::string option = args[argumentIndex++]; | |
| if (option == "OUTPUT_FORMAT") { | |
| if (argumentIndex < args.size()) { | |
| const std::string argument = args[argumentIndex++]; | |
| if (argument == "DECIMAL") { | |
| outputFormat = NumericFormat::DECIMAL; | |
| } else if (argument == "HEXADECIMAL") { | |
| outputFormat = NumericFormat::HEXADECIMAL; | |
| } else { | |
| std::string error = messageHint + "value \"" + argument + | |
| "\" for option \"" + option + "\" is invalid."; | |
| status.SetError(error); | |
| return false; | |
| } | |
| } else { | |
| std::string error = | |
| messageHint + "missing argument for option \"" + option + "\"."; | |
| status.SetError(error); | |
| return false; | |
| } | |
| } else { | |
| std::string error = | |
| messageHint + "option \"" + option + "\" is unknown."; | |
| status.SetError(error); | |
| return false; | |
| } | |
| } | |
| if (outputFormat == NumericFormat::UNINITIALIZED) { | |
| outputFormat = NumericFormat::DECIMAL; | |
| } | |
| cmExprParserHelper helper; | |
| if (!helper.ParseString(expression.c_str(), 0)) { | |
| status.SetError(helper.GetError()); | |
| return false; | |
| } | |
| char buffer[1024]; | |
| const char* fmt; | |
| switch (outputFormat) { | |
| case NumericFormat::HEXADECIMAL: | |
| fmt = "0x%" KWIML_INT_PRIx64; | |
| break; | |
| case NumericFormat::DECIMAL: | |
| CM_FALLTHROUGH; | |
| default: | |
| fmt = "%" KWIML_INT_PRId64; | |
| break; | |
| } | |
| sprintf(buffer, fmt, helper.GetResult()); | |
| std::string const& w = helper.GetWarning(); | |
| if (!w.empty()) { | |
| status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w); | |
| } | |
| status.GetMakefile().AddDefinition(outputVariable, buffer); | |
| return true; | |
| } | |
| } |