summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Franke <franke@edf-online.de>2018-05-18 21:59:46 +0200
committerBrad King <brad.king@kitware.com>2018-07-03 09:55:58 -0400
commit5dbee9d2d0f68e1fc343d04ac00a4a35d43df6fa (patch)
tree85375da2fabdfbc7982fe4ba58a76acc3167c71e
parent8661e7052c4f711f13e7168231276e23c4c0defd (diff)
downloadcmake-5dbee9d2d0f68e1fc343d04ac00a4a35d43df6fa.tar.gz
math: Add options to calculate and format output as hexadecimal
-rw-r--r--Help/command/math.rst18
-rw-r--r--Help/release/dev/math-hex.rst4
-rw-r--r--Source/LexerParser/cmExprLexer.cxx112
-rw-r--r--Source/LexerParser/cmExprLexer.in.l1
-rw-r--r--Source/cmMathCommand.cxx58
-rw-r--r--Tests/MathTest/CMakeLists.txt33
-rw-r--r--Tests/MathTest/MathTestExec.cxx40
-rw-r--r--Tests/RunCMake/math/MATH-DoubleOption-result.txt1
-rw-r--r--Tests/RunCMake/math/MATH-DoubleOption-stderr.txt4
-rw-r--r--Tests/RunCMake/math/MATH-DoubleOption.cmake1
-rw-r--r--Tests/RunCMake/math/MATH-TooManyArguments-result.txt1
-rw-r--r--Tests/RunCMake/math/MATH-TooManyArguments-stderr.txt4
-rw-r--r--Tests/RunCMake/math/MATH-TooManyArguments.cmake1
-rw-r--r--Tests/RunCMake/math/MATH-WrongArgument-result.txt1
-rw-r--r--Tests/RunCMake/math/MATH-WrongArgument-stderr.txt4
-rw-r--r--Tests/RunCMake/math/MATH-WrongArgument.cmake1
-rw-r--r--Tests/RunCMake/math/MATH.cmake3
-rw-r--r--Tests/RunCMake/math/RunCMakeTest.cmake3
18 files changed, 221 insertions, 69 deletions
diff --git a/Help/command/math.rst b/Help/command/math.rst
index f99dc3db3d..63af931d8a 100644
--- a/Help/command/math.rst
+++ b/Help/command/math.rst
@@ -5,10 +5,26 @@ Mathematical expressions.
::
- math(EXPR <output-variable> <math-expression>)
+ math(EXPR <output-variable> <math-expression> [OUTPUT_FORMAT <format>])
``EXPR`` evaluates mathematical expression and returns result in the
output variable. Example mathematical expression is ``5 * (10 + 13)``.
Supported operators are ``+``, ``-``, ``*``, ``/``, ``%``, ``|``, ``&``,
``^``, ``~``, ``<<``, ``>>``, and ``(...)``. They have the same meaning
as they do in C code.
+
+Numeric constants are evaluated in decimal or hexadecimal representation.
+
+The result is formatted according to the option "OUTPUT_FORMAT" ,
+where ``<format>`` is one of:
+::
+
+ HEXADECIMAL = Result in output variable will be formatted in C code
+ Hexadecimal notation.
+ DECIMAL = Result in output variable will be formatted in decimal notation.
+
+
+For example::
+
+ math(EXPR value "100 * 0xA" DECIMAL) results in value is set to "1000"
+ math(EXPR value "100 * 0xA" HEXADECIMAL) results in value is set to "0x3e8"
diff --git a/Help/release/dev/math-hex.rst b/Help/release/dev/math-hex.rst
new file mode 100644
index 0000000000..16e21ecb18
--- /dev/null
+++ b/Help/release/dev/math-hex.rst
@@ -0,0 +1,4 @@
+math-hex
+--------
+
+* The :command:`math` command gained options for hexadecimal.
diff --git a/Source/LexerParser/cmExprLexer.cxx b/Source/LexerParser/cmExprLexer.cxx
index 93b3ffd43c..1548daf94e 100644
--- a/Source/LexerParser/cmExprLexer.cxx
+++ b/Source/LexerParser/cmExprLexer.cxx
@@ -548,8 +548,8 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 18
+#define YY_END_OF_BUFFER 19
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -557,11 +557,11 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static const flex_int16_t yy_accept[25] =
+static const flex_int16_t yy_accept[29] =
{ 0,
- 0, 0, 18, 16, 1, 17, 7, 9, 14, 15,
- 5, 3, 4, 6, 2, 16, 16, 10, 8, 11,
- 2, 12, 13, 0
+ 0, 0, 19, 17, 1, 18, 8, 10, 15, 16,
+ 6, 4, 5, 7, 2, 2, 17, 17, 11, 9,
+ 12, 2, 0, 13, 14, 3, 3, 0
} ;
static const YY_CHAR yy_ec[256] =
@@ -570,16 +570,16 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 4, 5, 1, 6,
- 7, 8, 9, 1, 10, 1, 11, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 1, 1, 13,
- 1, 14, 1, 1, 1, 1, 1, 1, 1, 1,
+ 7, 8, 9, 1, 10, 1, 11, 12, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 1, 1, 14,
+ 1, 15, 1, 1, 16, 16, 16, 16, 16, 16,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 15, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 17, 1, 1,
+ 1, 1, 1, 18, 1, 1, 16, 16, 16, 16,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 16, 1, 17, 1, 1, 1, 1,
+ 16, 16, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 17,
+ 1, 1, 1, 19, 1, 20, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -596,40 +596,46 @@ static const YY_CHAR yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static const YY_CHAR yy_meta[18] =
+static const YY_CHAR yy_meta[21] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1
+ 1, 2, 2, 1, 1, 3, 4, 1, 1, 1
} ;
-static const flex_int16_t yy_base[25] =
+static const flex_int16_t yy_base[32] =
{ 0,
- 0, 0, 22, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 9, 7, 5, 23, 23, 23,
- 6, 23, 23, 23
+ 0, 0, 34, 35, 35, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 16, 9, 18, 11, 35, 35,
+ 35, 11, 0, 35, 35, 0, 0, 35, 23, 26,
+ 28
} ;
-static const flex_int16_t yy_def[25] =
+static const flex_int16_t yy_def[32] =
{ 0,
- 24, 1, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 0
+ 28, 1, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 29, 28, 28, 28, 28, 28,
+ 28, 28, 30, 28, 28, 31, 31, 0, 28, 28,
+ 28
} ;
-static const flex_int16_t yy_nxt[41] =
+static const flex_int16_t yy_nxt[56] =
{ 0,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 23, 22,
- 21, 24, 3, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
+ 14, 15, 16, 17, 18, 4, 4, 19, 20, 21,
+ 22, 22, 22, 22, 22, 25, 22, 26, 26, 27,
+ 27, 24, 23, 28, 3, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
-static const flex_int16_t yy_chk[41] =
+static const flex_int16_t yy_chk[56] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 21, 17, 16,
- 15, 3, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 16, 16, 22, 22, 29, 18, 29, 30, 30, 31,
+ 31, 17, 15, 3, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28
} ;
/* The intent behind this definition is that it'll catch
@@ -948,13 +954,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 25 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 23 );
+ while ( yy_base[yy_current_state] != 35 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -988,62 +994,66 @@ YY_RULE_SETUP
YY_BREAK
case 3:
YY_RULE_SETUP
-{ return exp_PLUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
YY_BREAK
case 4:
YY_RULE_SETUP
-{ return exp_MINUS; }
+{ return exp_PLUS; }
YY_BREAK
case 5:
YY_RULE_SETUP
-{ return exp_TIMES; }
+{ return exp_MINUS; }
YY_BREAK
case 6:
YY_RULE_SETUP
-{ return exp_DIVIDE; }
+{ return exp_TIMES; }
YY_BREAK
case 7:
YY_RULE_SETUP
-{ return exp_MOD; }
+{ return exp_DIVIDE; }
YY_BREAK
case 8:
YY_RULE_SETUP
-{ return exp_OR; }
+{ return exp_MOD; }
YY_BREAK
case 9:
YY_RULE_SETUP
-{ return exp_AND; }
+{ return exp_OR; }
YY_BREAK
case 10:
YY_RULE_SETUP
-{ return exp_XOR; }
+{ return exp_AND; }
YY_BREAK
case 11:
YY_RULE_SETUP
-{ return exp_NOT; }
+{ return exp_XOR; }
YY_BREAK
case 12:
YY_RULE_SETUP
-{ return exp_SHIFTLEFT; }
+{ return exp_NOT; }
YY_BREAK
case 13:
YY_RULE_SETUP
-{ return exp_SHIFTRIGHT; }
+{ return exp_SHIFTLEFT; }
YY_BREAK
case 14:
YY_RULE_SETUP
-{ return exp_OPENPARENT; }
+{ return exp_SHIFTRIGHT; }
YY_BREAK
case 15:
YY_RULE_SETUP
-{ return exp_CLOSEPARENT; }
+{ return exp_OPENPARENT; }
YY_BREAK
case 16:
YY_RULE_SETUP
-{return exp_UNEXPECTED;}
+{ return exp_CLOSEPARENT; }
YY_BREAK
case 17:
YY_RULE_SETUP
+{return exp_UNEXPECTED;}
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
ECHO;
YY_BREAK
case YY_STATE_EOF(INITIAL):
@@ -1344,7 +1354,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 25 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1373,11 +1383,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 25 )
+ if ( yy_current_state >= 29 )
yy_c = yy_meta[yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
- yy_is_jam = (yy_current_state == 24);
+ yy_is_jam = (yy_current_state == 28);
(void)yyg;
return yy_is_jam ? 0 : yy_current_state;
diff --git a/Source/LexerParser/cmExprLexer.in.l b/Source/LexerParser/cmExprLexer.in.l
index 0c4eb9e6c6..87237d1ab0 100644
--- a/Source/LexerParser/cmExprLexer.in.l
+++ b/Source/LexerParser/cmExprLexer.in.l
@@ -43,6 +43,7 @@ Modify cmExprLexer.cxx:
[ \t] {}
[0-9][0-9]* { yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
+0[xX][0-9a-fA-F][0-9a-fA-F]* { yylvalp->Number = std::stoll(yytext, nullptr, 16); return exp_NUMBER; }
"+" { return exp_PLUS; }
"-" { return exp_MINUS; }
diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx
index ab77dc36f8..5d1b099505 100644
--- a/Source/cmMathCommand.cxx
+++ b/Source/cmMathCommand.cxx
@@ -28,16 +28,59 @@ bool cmMathCommand::InitialPass(std::vector<std::string> const& args,
bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
{
- if (args.size() != 3) {
+ 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());
@@ -45,7 +88,18 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
}
char buffer[1024];
- sprintf(buffer, "%" KWIML_INT_PRId64, helper.GetResult());
+ 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());
this->Makefile->AddDefinition(outputVariable, buffer);
return true;
diff --git a/Tests/MathTest/CMakeLists.txt b/Tests/MathTest/CMakeLists.txt
index f764b3a4fd..5403d297cb 100644
--- a/Tests/MathTest/CMakeLists.txt
+++ b/Tests/MathTest/CMakeLists.txt
@@ -13,14 +13,35 @@ set(expressions
"-1 + +1"
"+1 - -1"
"+1 - - + + -(-3 + - - +1)"
+ "1000 -12*5"
+ "1000 +12*-5"
+ "1000 -12*-5"
)
-set(FILE_EXPRESSIONS "")
-foreach(expression
- ${expressions})
- math(EXPR expr "${expression}")
- string(APPEND FILE_EXPRESSIONS "TEST_EXPRESSION(${expression}, ${expr})\n")
-endforeach()
+set(FILE_EXPRESSIONS "extern void test_expression(int x, int y, const char * text);\n")
+
+
+macro(add_math_test expression)
+ math(EXPR result ${expression} ${ARGV1} ${ARGV2})
+ set(CODE "test_expression(${expression}, ${result}, \"${expression}\");")
+ string(APPEND FILE_EXPRESSIONS "${CODE}\n")
+endmacro()
+
+macro(add_math_tests)
+ foreach (expression ${expressions})
+ add_math_test(${expression} ${ARGV0} ${ARGV1})
+ endforeach ()
+endmacro()
+
+add_math_tests()
+add_math_tests("OUTPUT_FORMAT" "DECIMAL")
+add_math_tests("OUTPUT_FORMAT" "HEXADECIMAL")
+
+# Avoid the test with negative result and hexadecimal formatting
+# therefore more tests with a negative result
+add_math_test("-12*5")
+add_math_test("12*-5")
+
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/MathTestTests.h.in"
diff --git a/Tests/MathTest/MathTestExec.cxx b/Tests/MathTest/MathTestExec.cxx
index 124eba46f9..fbcddc4ed4 100644
--- a/Tests/MathTest/MathTestExec.cxx
+++ b/Tests/MathTest/MathTestExec.cxx
@@ -1,21 +1,43 @@
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-#define TEST_EXPRESSION(x, y) \
- if ((x) != (y)) { \
- printf("Problem with EXPR: Expression: \"%s\" in C returns %d while in " \
- "CMake returns: %d\n", \
- #x, (x), (y)); \
- res++; \
+int res = 0;
+bool print = false;
+
+void test_expression(int x, int y, const char* text)
+{
+ bool fail = (x) != (y);
+ if (fail) {
+ res++;
+ printf("Problem with EXPR:");
+ }
+ if (fail || print) {
+ printf("Expression: \"%s\" in CMake returns %d", text, (y));
+ if (fail) {
+ printf(" while in C returns: %d", (x));
+ }
+ printf("\n");
}
+}
int main(int argc, char* argv[])
{
- if (argc > 1) {
- printf("Usage: %s\n", argv[0]);
+ if (argc > 2) {
+ printf("Usage: %s [print]\n", argv[0]);
return 1;
}
- int res = 0;
+
+ if (argc > 1) {
+ if (strcmp(argv[1], "print") != 0) {
+ printf("Usage: %s [print]\n", argv[0]);
+ return 1;
+ }
+ print = true;
+ }
+
#include "MathTestTests.h"
+
if (res != 0) {
printf("%s: %d math tests failed\n", argv[0], res);
return 1;
diff --git a/Tests/RunCMake/math/MATH-DoubleOption-result.txt b/Tests/RunCMake/math/MATH-DoubleOption-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-DoubleOption-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/math/MATH-DoubleOption-stderr.txt b/Tests/RunCMake/math/MATH-DoubleOption-stderr.txt
new file mode 100644
index 0000000000..767a060fc7
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-DoubleOption-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at MATH-DoubleOption.cmake:1 \(math\):
+ math EXPR called with incorrect arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/math/MATH-DoubleOption.cmake b/Tests/RunCMake/math/MATH-DoubleOption.cmake
new file mode 100644
index 0000000000..7bcb78ec2a
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-DoubleOption.cmake
@@ -0,0 +1 @@
+math(EXPR var "10*10" OUTPUT_FORMAT DECIMAL OUTPUT_FORMAT HEXADECIMAL)
diff --git a/Tests/RunCMake/math/MATH-TooManyArguments-result.txt b/Tests/RunCMake/math/MATH-TooManyArguments-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-TooManyArguments-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/math/MATH-TooManyArguments-stderr.txt b/Tests/RunCMake/math/MATH-TooManyArguments-stderr.txt
new file mode 100644
index 0000000000..fdcfecf7f6
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-TooManyArguments-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at MATH-TooManyArguments.cmake:1 \(math\):
+ math EXPR called with incorrect arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/math/MATH-TooManyArguments.cmake b/Tests/RunCMake/math/MATH-TooManyArguments.cmake
new file mode 100644
index 0000000000..969dc80f0c
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-TooManyArguments.cmake
@@ -0,0 +1 @@
+math(EXPR var "10*10" OUTPUT_FORMAT DECIMAL OUTPUT_FORMAT )
diff --git a/Tests/RunCMake/math/MATH-WrongArgument-result.txt b/Tests/RunCMake/math/MATH-WrongArgument-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-WrongArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/math/MATH-WrongArgument-stderr.txt b/Tests/RunCMake/math/MATH-WrongArgument-stderr.txt
new file mode 100644
index 0000000000..bbe54bf1fc
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-WrongArgument-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at MATH-WrongArgument.cmake:1 \(math\):
+ math sub-command EXPR option "OUT" is unknown.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/math/MATH-WrongArgument.cmake b/Tests/RunCMake/math/MATH-WrongArgument.cmake
new file mode 100644
index 0000000000..fb6d2e725d
--- /dev/null
+++ b/Tests/RunCMake/math/MATH-WrongArgument.cmake
@@ -0,0 +1 @@
+math(EXPR var "10*10" OUT HEX )
diff --git a/Tests/RunCMake/math/MATH.cmake b/Tests/RunCMake/math/MATH.cmake
index 4ec7f9c57f..a5f50cd903 100644
--- a/Tests/RunCMake/math/MATH.cmake
+++ b/Tests/RunCMake/math/MATH.cmake
@@ -7,3 +7,6 @@ endmacro()
math_test("100 * 10" 1000)
+math_test("100 * 10" 1000 OUTPUT_FORMAT DECIMAL)
+math_test("100 * 0xA" 1000 OUTPUT_FORMAT DECIMAL)
+math_test("100 * 0xA" 0x3e8 OUTPUT_FORMAT HEXADECIMAL)
diff --git a/Tests/RunCMake/math/RunCMakeTest.cmake b/Tests/RunCMake/math/RunCMakeTest.cmake
index 4c4b725973..494b813765 100644
--- a/Tests/RunCMake/math/RunCMakeTest.cmake
+++ b/Tests/RunCMake/math/RunCMakeTest.cmake
@@ -1,5 +1,8 @@
include(RunCMake)
run_cmake(MATH)
+run_cmake(MATH-WrongArgument)
+run_cmake(MATH-DoubleOption)
+run_cmake(MATH-TooManyArguments)
run_cmake(MATH-InvalidExpression)
run_cmake(MATH-DivideByZero)