math: Add options to calculate and format output as hexadecimal

This commit is contained in:
Daniel Franke
2018-05-18 21:59:46 +02:00
committed by Brad King
parent 8661e7052c
commit 5dbee9d2d0
18 changed files with 221 additions and 69 deletions

View File

@@ -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;

View File

@@ -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; }

View File

@@ -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;