From 18906ef111593a5987f4ea0d21ead60807a58463 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Fri, 6 Nov 2015 03:05:49 +0100 Subject: [PATCH] [4088fd] Added hexstring support --- src/lib/eval/eval.dox | 18 ++++++++++------ src/lib/eval/lexer.ll | 9 +++++++- src/lib/eval/parser.yy | 16 ++++++++++---- src/lib/eval/tests/context_unittest.cc | 29 ++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/lib/eval/eval.dox b/src/lib/eval/eval.dox index 4ffba5fc5c..95a0c53f2e 100644 --- a/src/lib/eval/eval.dox +++ b/src/lib/eval/eval.dox @@ -75,18 +75,24 @@ 09. TokenPtr str(new TokenString($1)); 10. ctx.expression.push_back(str); 11.} -12.| OPTION { -13. TokenPtr opt(new TokenOption($1)); -14. ctx.expression.push_back(opt); -15.}; +12. HEXSTRING { +13. TokenPtr hex(new TokenHexString($1)); +14. ctx.expression.push_back(hex); +15.} +16.| OPTION { +17. TokenPtr opt(new TokenOption($1)); +18. ctx.expression.push_back(opt); +19.} +20.; @endcode This code determines that the grammar starts from expression (line 1). The actual definition of expression (lines 3-5) may either be a single token or an expression "token == token" (EQUAL has been defined as "==" elsewhere). Token is further -defined in lines 7-15: it may either be a string (lines 8-11) or option -(lines 12-15). When the actual case is determined, the respective C++ action +defined in lines 7-15: it may either be a string (lines 8-11), +a hex string (lines 12-15) or option (lines 16-19). +When the actual case is determined, the respective C++ action is executed. For example, if the token is a string, the TokenString class is instantiated with the appropriate value and put onto the expression vector. diff --git a/src/lib/eval/lexer.ll b/src/lib/eval/lexer.ll index 9300b2d3f4..cd48835309 100644 --- a/src/lib/eval/lexer.ll +++ b/src/lib/eval/lexer.ll @@ -63,8 +63,9 @@ static isc::eval::location loc; /* These are not token expressions yet, just convenience expressions that can be used during actual token definitions. */ int [0-9]+ +hex [0-9a-fA-F]+ blank [ \t] -str [a-zA-Z_0-9]* +str [a-zA-Z_0-9]* %{ // This code run each time a pattern is matched. It updates the location @@ -100,6 +101,12 @@ str [a-zA-Z_0-9]* return isc::eval::EvalParser::make_STRING(tmp, loc); } +0[xX]{hex} { + // A hex string has been matched. It contains the '0x' or '0X' header + // followed by at least one hexadecimal digit. + return isc::eval::EvalParser::make_HEXSTRING(yytext, loc); +} + option\[{int}\] { // option[123] token found. Let's see if the numeric value can be // converted to integer and if it has a reasonable value. diff --git a/src/lib/eval/parser.yy b/src/lib/eval/parser.yy index f1b12044c0..ec76ec0f79 100644 --- a/src/lib/eval/parser.yy +++ b/src/lib/eval/parser.yy @@ -53,6 +53,7 @@ using namespace isc::eval; RPAREN ")" ; %token STRING "constant string" +%token HEXSTRING "constant hexstring" %token OPTION "option code" %printer { yyoutput << $$; } <*>; %% @@ -61,25 +62,32 @@ using namespace isc::eval; %start expression; // Expression can either be a single token or a (something == something) expression + expression: token EQUAL token { TokenPtr eq(new TokenEqual()); ctx.expression.push_back(eq); -} -| token; + } +| token +; token: STRING { TokenPtr str(new TokenString($1)); ctx.expression.push_back(str); -} + } +| HEXSTRING { + TokenPtr hex(new TokenHexString($1)); + ctx.expression.push_back(hex); + } | OPTION { TokenPtr opt(new TokenOption($1)); ctx.expression.push_back(opt); -} + } | SUBSTRING "(" token "," token "," token ")" { /* push back TokenSubstring */ } +; %% void diff --git a/src/lib/eval/tests/context_unittest.cc b/src/lib/eval/tests/context_unittest.cc index 75b949e10c..99ad7e4abb 100644 --- a/src/lib/eval/tests/context_unittest.cc +++ b/src/lib/eval/tests/context_unittest.cc @@ -45,6 +45,23 @@ public: EXPECT_EQ(expected, values.top()); } + void checkTokenHexString(const TokenPtr& token, + const std::string& expected) { + ASSERT_TRUE(token); + boost::shared_ptr hex = + boost::dynamic_pointer_cast(token); + ASSERT_TRUE(hex); + + Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345)); + ValueStack values; + + EXPECT_NO_THROW(token->evaluate(*pkt4, values)); + + ASSERT_EQ(1, values.size()); + + EXPECT_EQ(expected, values.top()); + } + void checkTokenEq(const TokenPtr& token) { ASSERT_TRUE(token); boost::shared_ptr eq = @@ -81,6 +98,18 @@ TEST_F(EvalContextTest, string) { checkTokenString(tmp, "foo"); } +TEST_F(EvalContextTest, hexstring) { + EvalContext eval; + + EXPECT_NO_THROW(eval.parseString("0x666f6f")); + + ASSERT_EQ(1, eval.expression.size()); + + TokenPtr tmp = eval.expression.at(0); + + checkTokenHexString(tmp, "foo"); +} + TEST_F(EvalContextTest, equal) { EvalContext eval; -- 2.47.3