/* 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 "cmExprParserHelper.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cm_kwiml.h" #include class cmExecutionStatus; bool cmMathCommand::InitialPass(std::vector const& args, cmExecutionStatus&) { if (args.empty()) { this->SetError("must be called with at least one argument."); return false; } const std::string& subCommand = args[0]; if (subCommand == "EXPR") { return this->HandleExprCommand(args); } std::string e = "does not recognize sub-command " + subCommand; this->SetError(e); return false; } bool cmMathCommand::HandleExprCommand(std::vector const& args) { if ((args.size() != 3) && (args.size() != 5)) { this->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; this->Makefile->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."; this->SetError(error); return false; } } else { std::string error = messageHint + "missing argument for option \"" + option + "\"."; this->SetError(error); return false; } } else { std::string error = messageHint + "option \"" + option + "\" is unknown."; this->SetError(error); return false; } } if (outputFormat == NumericFormat::UNINITIALIZED) { outputFormat = NumericFormat::DECIMAL; } cmExprParserHelper helper; if (!helper.ParseString(expression.c_str(), 0)) { this->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()) { this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w); } this->Makefile->AddDefinition(outputVariable, buffer); return true; }