Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmMathCommand.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmMathCommand.h"
4
5
#include <cstdio>
6
7
#include <cm3p/kwiml/int.h>
8
9
#include "cmExecutionStatus.h"
10
#include "cmExprParserHelper.h"
11
#include "cmMakefile.h"
12
#include "cmMessageType.h"
13
14
namespace {
15
bool HandleExprCommand(std::vector<std::string> const& args,
16
                       cmExecutionStatus& status);
17
}
18
19
bool cmMathCommand(std::vector<std::string> const& args,
20
                   cmExecutionStatus& status)
21
0
{
22
0
  if (args.empty()) {
23
0
    status.SetError("must be called with at least one argument.");
24
0
    return false;
25
0
  }
26
0
  std::string const& subCommand = args[0];
27
0
  if (subCommand == "EXPR") {
28
0
    return HandleExprCommand(args, status);
29
0
  }
30
0
  std::string e = "does not recognize sub-command " + subCommand;
31
0
  status.SetError(e);
32
0
  return false;
33
0
}
34
35
namespace {
36
bool HandleExprCommand(std::vector<std::string> const& args,
37
                       cmExecutionStatus& status)
38
0
{
39
0
  if ((args.size() != 3) && (args.size() != 5)) {
40
0
    status.SetError("EXPR called with incorrect arguments.");
41
0
    return false;
42
0
  }
43
44
0
  enum class NumericFormat
45
0
  {
46
0
    UNINITIALIZED,
47
0
    DECIMAL,
48
0
    HEXADECIMAL,
49
0
  };
50
51
0
  std::string const& outputVariable = args[1];
52
0
  std::string const& expression = args[2];
53
0
  size_t argumentIndex = 3;
54
0
  NumericFormat outputFormat = NumericFormat::UNINITIALIZED;
55
56
0
  status.GetMakefile().AddDefinition(outputVariable, "ERROR");
57
58
0
  if (argumentIndex < args.size()) {
59
0
    std::string const messageHint = "sub-command EXPR ";
60
0
    std::string const& option = args[argumentIndex++];
61
0
    if (option == "OUTPUT_FORMAT") {
62
0
      if (argumentIndex < args.size()) {
63
0
        std::string const& argument = args[argumentIndex++];
64
0
        if (argument == "DECIMAL") {
65
0
          outputFormat = NumericFormat::DECIMAL;
66
0
        } else if (argument == "HEXADECIMAL") {
67
0
          outputFormat = NumericFormat::HEXADECIMAL;
68
0
        } else {
69
0
          std::string error = messageHint + "value \"" + argument +
70
0
            "\" for option \"" + option + "\" is invalid.";
71
0
          status.SetError(error);
72
0
          return false;
73
0
        }
74
0
      } else {
75
0
        std::string error =
76
0
          messageHint + "missing argument for option \"" + option + "\".";
77
0
        status.SetError(error);
78
0
        return false;
79
0
      }
80
0
    } else {
81
0
      std::string error =
82
0
        messageHint + "option \"" + option + "\" is unknown.";
83
0
      status.SetError(error);
84
0
      return false;
85
0
    }
86
0
  }
87
88
0
  if (outputFormat == NumericFormat::UNINITIALIZED) {
89
0
    outputFormat = NumericFormat::DECIMAL;
90
0
  }
91
92
0
  cmExprParserHelper helper;
93
0
  if (!helper.ParseString(expression.c_str(), 0)) {
94
0
    status.SetError(helper.GetError());
95
0
    return false;
96
0
  }
97
98
0
  char buffer[1024];
99
0
  char const* fmt;
100
0
  switch (outputFormat) {
101
0
    case NumericFormat::HEXADECIMAL:
102
0
      fmt = "0x%" KWIML_INT_PRIx64;
103
0
      break;
104
0
    case NumericFormat::DECIMAL:
105
0
      CM_FALLTHROUGH;
106
0
    default:
107
0
      fmt = "%" KWIML_INT_PRId64;
108
0
      break;
109
0
  }
110
0
  snprintf(buffer, sizeof(buffer), fmt, helper.GetResult());
111
112
0
  std::string const& w = helper.GetWarning();
113
0
  if (!w.empty()) {
114
0
    status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, w);
115
0
  }
116
117
0
  status.GetMakefile().AddDefinition(outputVariable, buffer);
118
0
  return true;
119
0
}
120
}