]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3048] added the lcase and ucase operators
authorRazvan Becheriu <razvan@isc.org>
Thu, 21 Sep 2023 13:45:32 +0000 (16:45 +0300)
committerRazvan Becheriu <razvan@isc.org>
Fri, 22 Sep 2023 13:29:59 +0000 (16:29 +0300)
14 files changed:
doc/sphinx/arm/classify.rst
src/lib/eval/eval.dox
src/lib/eval/eval_messages.cc
src/lib/eval/eval_messages.h
src/lib/eval/eval_messages.mes
src/lib/eval/lexer.cc
src/lib/eval/lexer.ll
src/lib/eval/parser.cc
src/lib/eval/parser.h
src/lib/eval/parser.yy
src/lib/eval/tests/context_unittest.cc
src/lib/eval/tests/token_unittest.cc
src/lib/eval/token.cc
src/lib/eval/token.h

index 9ecf9a964e87a430fca23782b7dd695388fa3385..0ee18dc4ed399cde2b9ae01cf52c974bcede6c23 100644 (file)
@@ -521,7 +521,17 @@ Notes:
    +-----------------------+-------------------------+-----------------------+
    | Hexstring             | hexstring('foo', '-')   | Converts the value to |
    |                       |                         | a hexadecimal string, |
-   |                       |                         | e.g. 0a:1b:2c:3e      |
+   |                       |                         | e.g. 66-6F-6F         |
+   +-----------------------+-------------------------+-----------------------+
+   | Lcase                 | lcase('LoWeR')          | Converts the value of |
+   |                       |                         | a string expression   |
+   |                       |                         | to lower case e.g.    |
+   |                       |                         | 'lower'               |
+   +-----------------------+-------------------------+-----------------------+
+   | Ucase                 | ucase('uPpEr')          | Converts the value of |
+   |                       |                         | a string expression   |
+   |                       |                         | to upper case e.g.    |
+   |                       |                         | 'UPPER'               |
    +-----------------------+-------------------------+-----------------------+
    | Split                 | split('foo.bar', '.', 2)| Return the second     |
    |                       |                         | field, splitting on   |
index e72800630c5af1af21c8b7e397e1c70f0b1bbc6a..f1ee0de068cee3cc6d2cfd1f1012267eb1b115eb 100644 (file)
@@ -142,26 +142,32 @@ instantiated with the appropriate value and put onto the expression vector.
  - isc::dhcp::TokenString -- represents a constant string, e.g. "MSFT".
  - isc::dhcp::TokenHexString -- represents a constant string, encoded as
    hex string, e.g. 0x666f6f which is actually "foo".
+ - isc::dhcp::TokenLowerCase -- represents an operator which converts a string
+   expression to the corresponding lower case string.
+ - isc::dhcp::TokenUpperCase -- represents an operator which converts a string
+   expression to the corresponding upper case string.
  - isc::dhcp::TokenIpAddress -- represents a constant IP address, encoded as
    a 4 or 16 byte binary string, e.g., 10.0.0.1 is 0x10000001.
  - isc::dhcp::TokenIpAddressToText -- represents an IP address in text format.
  - isc::dhcp::TokenOption -- represents an option in a packet, e.g.
-                    option[123].text.
+   option[123].text.
  - isc::dhcp::TokenRelay4Option -- represents a sub-option inserted by the
-                    DHCPv4 relay, e.g. relay[123].text or relay[123].hex
+   DHCPv4 relay, e.g. relay[123].text or relay[123].hex
  - isc::dhcp::TokenRelay6Option -- represents a sub-option inserted by
    a DHCPv6 relay
  - isc::dhcp::TokenPkt -- represents a DHCP packet meta data (incoming
    interface name, source/remote or destination/local IP address, length).
  - isc::dhcp::TokenPkt4 -- represents a DHCPv4 packet field.
- - isc::dhcp::TokenPkt6 -- represents a DHCPv6 packet field (message type
-   or transaction id).
+ - isc::dhcp::TokenPkt6 -- represents a DHCPv6 packet field (message type or
+   transaction id).
  - isc::dhcp::TokenRelay6Field -- represents a DHCPv6 relay information field.
  - isc::dhcp::TokenEqual -- represents the equal (==) operator.
- - isc::dhcp::TokenSubstring -- represents the substring(text, start, length) operator.
- - isc::dhcp::TokenConcat -- represents the concat operator which
-   concatenate two other tokens.
- - isc::dhcp::TokenIfElse -- represents the ifelse(cond, iftrue, ifelse) operator.
+ - isc::dhcp::TokenSubstring -- represents the substring(text, start, length)
+   operator.
+ - isc::dhcp::TokenConcat -- represents the concat operator which concatenate
+   two other tokens.
+ - isc::dhcp::TokenIfElse -- represents the ifelse(cond, iftrue, ifelse)
+   operator.
  - isc::dhcp::TokenToHexString -- represents the hexstring operator which
    converts a binary value to its hexadecimal string representation.
  - isc::dhcp::TokenInt8ToText -- represents the signed 8 bit integer in string
@@ -170,21 +176,23 @@ instantiated with the appropriate value and put onto the expression vector.
    representation.
  - isc::dhcp::TokenInt32ToText -- represents the signed 32 bit integer in string
    representation.
- - isc::dhcp::TokenUInt8ToText -- represents the unsigned 8 bit integer in string
-   representation.
- - isc::dhcp::TokenUInt16ToText -- represents the unsigned 16 bit integer in string
-   representation.
- - isc::dhcp::TokenUInt32ToText -- represents the unsigned 32 bit integer in string
-   representation.
+ - isc::dhcp::TokenUInt8ToText -- represents the unsigned 8 bit integer in
+   string representation.
+ - isc::dhcp::TokenUInt16ToText -- represents the unsigned 16 bit integer in
+   string representation.
+ - isc::dhcp::TokenUInt32ToText -- represents the unsigned 32 bit integer in
+   string representation.
  - isc::dhcp::TokenNot -- the logical not operator.
  - isc::dhcp::TokenAnd -- the logical and (strict) operator.
  - isc::dhcp::TokenOr -- the logical or (strict) operator (strict means
    it always evaluates its operands).
  - isc::dhcp::TokenVendor -- represents vendor information option's existence,
    enterprise-id field and possible sub-options. (e.g. vendor[1234].exists,
-   vendor[*].enterprise-id, vendor[1234].option[1].exists, vendor[1234].option[1].hex)
- - isc::dhcp::TokenVendorClass -- represents vendor information option's existence,
-   enterprise-id and included data chunks. (e.g. vendor-class[1234].exists,
+   vendor[*].enterprise-id, vendor[1234].option[1].exists,
+   vendor[1234].option[1].hex)
+ - isc::dhcp::TokenVendorClass -- represents vendor information option's
+   existence, enterprise-id and included data chunks. (e.g.
+   vendor-class[1234].exists,
    vendor-class[*].enterprise-id, vendor-class[*].data[3])
 
 More operators are expected to be implemented in upcoming releases.
index 7dfeba1fd8bc61a7c3e76d2169403283dc863f5c..cd9aae000e38243aa345cc3e2a0d36b0e9f8c5ba 100644 (file)
@@ -18,6 +18,7 @@ extern const isc::log::MessageID EVAL_DEBUG_INT32TOTEXT = "EVAL_DEBUG_INT32TOTEX
 extern const isc::log::MessageID EVAL_DEBUG_INT8TOTEXT = "EVAL_DEBUG_INT8TOTEXT";
 extern const isc::log::MessageID EVAL_DEBUG_IPADDRESS = "EVAL_DEBUG_IPADDRESS";
 extern const isc::log::MessageID EVAL_DEBUG_IPADDRESSTOTEXT = "EVAL_DEBUG_IPADDRESSTOTEXT";
+extern const isc::log::MessageID EVAL_DEBUG_LCASE = "EVAL_DEBUG_LCASE";
 extern const isc::log::MessageID EVAL_DEBUG_MEMBER = "EVAL_DEBUG_MEMBER";
 extern const isc::log::MessageID EVAL_DEBUG_NOT = "EVAL_DEBUG_NOT";
 extern const isc::log::MessageID EVAL_DEBUG_OPTION = "EVAL_DEBUG_OPTION";
@@ -38,6 +39,7 @@ extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE = "EVAL_DEBUG_SUBSTR
 extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION = "EVAL_DEBUG_SUB_OPTION";
 extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION = "EVAL_DEBUG_SUB_OPTION_NO_OPTION";
 extern const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING = "EVAL_DEBUG_TOHEXSTRING";
+extern const isc::log::MessageID EVAL_DEBUG_UCASE = "EVAL_DEBUG_UCASE";
 extern const isc::log::MessageID EVAL_DEBUG_UINT16TOTEXT = "EVAL_DEBUG_UINT16TOTEXT";
 extern const isc::log::MessageID EVAL_DEBUG_UINT32TOTEXT = "EVAL_DEBUG_UINT32TOTEXT";
 extern const isc::log::MessageID EVAL_DEBUG_UINT8TOTEXT = "EVAL_DEBUG_UINT8TOTEXT";
@@ -70,6 +72,7 @@ const char* values[] = {
     "EVAL_DEBUG_INT8TOTEXT", "Pushing Int8 %1",
     "EVAL_DEBUG_IPADDRESS", "Pushing IPAddress %1",
     "EVAL_DEBUG_IPADDRESSTOTEXT", "Pushing IPAddress %1",
+    "EVAL_DEBUG_LCASE", "Poping string %1 and pushing converted value to lower case %2",
     "EVAL_DEBUG_MEMBER", "Checking membership of '%1', pushing result %2",
     "EVAL_DEBUG_NOT", "Popping %1 pushing %2",
     "EVAL_DEBUG_OPTION", "Pushing option %1 with value %2",
@@ -90,6 +93,7 @@ const char* values[] = {
     "EVAL_DEBUG_SUB_OPTION", "Pushing option %1 sub-option %2 with value %3",
     "EVAL_DEBUG_SUB_OPTION_NO_OPTION", "Requested option %1 sub-option %2, but the parent option is not present, pushing result %3",
     "EVAL_DEBUG_TOHEXSTRING", "Popping binary value %1 and separator %2, pushing result %3",
+    "EVAL_DEBUG_UCASE", "Poping string %1 and pushing converted value to upper case %2",
     "EVAL_DEBUG_UINT16TOTEXT", "Pushing UInt16 %1",
     "EVAL_DEBUG_UINT32TOTEXT", "Pushing UInt32 %1",
     "EVAL_DEBUG_UINT8TOTEXT", "Pushing UInt8 %1",
index 6353ab21b661fab12dec76c15a3b32f54cd35883..6bb42ebc3952c854befcb507f4c4e600075c786e 100644 (file)
@@ -19,6 +19,7 @@ extern const isc::log::MessageID EVAL_DEBUG_INT32TOTEXT;
 extern const isc::log::MessageID EVAL_DEBUG_INT8TOTEXT;
 extern const isc::log::MessageID EVAL_DEBUG_IPADDRESS;
 extern const isc::log::MessageID EVAL_DEBUG_IPADDRESSTOTEXT;
+extern const isc::log::MessageID EVAL_DEBUG_LCASE;
 extern const isc::log::MessageID EVAL_DEBUG_MEMBER;
 extern const isc::log::MessageID EVAL_DEBUG_NOT;
 extern const isc::log::MessageID EVAL_DEBUG_OPTION;
@@ -39,6 +40,7 @@ extern const isc::log::MessageID EVAL_DEBUG_SUBSTRING_RANGE;
 extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION;
 extern const isc::log::MessageID EVAL_DEBUG_SUB_OPTION_NO_OPTION;
 extern const isc::log::MessageID EVAL_DEBUG_TOHEXSTRING;
+extern const isc::log::MessageID EVAL_DEBUG_UCASE;
 extern const isc::log::MessageID EVAL_DEBUG_UINT16TOTEXT;
 extern const isc::log::MessageID EVAL_DEBUG_UINT32TOTEXT;
 extern const isc::log::MessageID EVAL_DEBUG_UINT8TOTEXT;
index 1cace9a0a14b456156b6bc186a161a692a2a64fc..7738f28812dc825b6123aca65189b490c47a4d2b 100644 (file)
@@ -34,6 +34,18 @@ the value stack.  The strings are displayed in hex.
 This debug message indicates that the given binary string is being pushed
 onto the value stack.  The string is displayed in hex.
 
+# For use with TokenLowerCase
+
+% EVAL_DEBUG_LCASE Poping string %1 and pushing converted value to lower case %2
+This debug message indicates that the given string representation is being
+converted to lower case and pushed onto the value stack.
+
+# For use with TokenUpperCase
+
+% EVAL_DEBUG_UCASE Poping string %1 and pushing converted value to upper case %2
+This debug message indicates that the given string representation is being
+converted to upper case and pushed onto the value stack.
+
 # For use with TokenIfElse
 
 % EVAL_DEBUG_IFELSE_FALSE Popping %1 (false) and %2, leaving %3
index ab42b71a86a06a2d74385dcafd9e06e5bb4c5bf1..989b9d25e1fae1efd90285c8c35b582fdbe7a44b 100644 (file)
@@ -1,6 +1,6 @@
-#line 1 "lexer.cc"
+#line 2 "lexer.cc"
 
-#line 3 "lexer.cc"
+#line 4 "lexer.cc"
 
 #define  YY_INT_ALIGNED short int
 
@@ -710,8 +710,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
 /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
        (yy_c_buf_p) = yy_cp;
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 63
-#define YY_END_OF_BUFFER 64
+#define YY_NUM_RULES 65
+#define YY_END_OF_BUFFER 66
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -719,38 +719,39 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static const flex_int16_t yy_accept[279] =
+static const flex_int16_t yy_accept[287] =
     {   0,
-        0,    0,   64,   62,    1,    2,   62,   55,   56,   60,
-       61,   59,   62,   54,    5,    5,   62,   62,   62,   62,
-       57,   58,   62,   62,   62,   62,   62,   62,   62,   62,
-       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+        0,    0,   66,   64,    1,    2,   64,   57,   58,   62,
+       63,   61,   64,   56,    5,    5,   64,   64,   64,   64,
+       59,   60,   64,   64,   64,   64,   64,   64,   64,   64,
+       64,   64,   64,   64,   64,   64,   64,   64,   64,   64,
         1,    2,    0,    3,    5,    0,    5,    0,    0,    0,
         0,    7,    8,    0,    0,    0,    0,    6,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       52,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    4,    7,    0,   39,   51,    0,
-
-        0,    0,   20,    0,    0,    0,   15,    0,    0,    0,
-        0,    0,   21,    0,   23,    0,    0,   50,    0,    0,
-       17,    0,    0,    0,   19,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,   35,    0,    0,    0,    0,
-       24,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   22,   30,    0,    0,    0,    0,   14,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   25,   18,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,   38,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,   26,   40,    0,   16,   27,    0,
-
-       41,    0,    0,    0,    0,   53,    0,    9,    0,   10,
-       11,   29,    0,    0,    0,    0,    0,   33,   28,    7,
-        0,    0,    0,    0,    0,    0,    0,   31,    0,    0,
-       32,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   13,   12,    0,    0,    0,    0,    0,    0,    0,
-       42,    0,    0,    0,   37,    0,    0,    0,    0,   43,
-       36,    0,    0,   44,    0,    0,    0,    0,   45,   46,
-        0,    0,   47,    0,   48,   49,   34,    0
+        0,   54,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    4,    7,    0,   41,
+
+       53,    0,    0,    0,   20,    0,    0,    0,   15,    0,
+        0,    0,    0,    0,    0,   21,    0,   23,    0,    0,
+       52,    0,    0,   17,    0,    0,    0,   19,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   35,
+        0,    0,    0,    0,   24,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   22,   30,    0,
+        0,    0,    0,   14,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   25,   18,    0,
+        0,    0,    0,   38,    0,    0,    0,    0,    0,    0,
+        0,   40,    0,    0,   39,    0,    0,    0,    0,    0,
+
+        0,    0,   26,   42,    0,   16,   27,    0,   43,    0,
+        0,    0,    0,   55,    0,    9,    0,   10,   11,   29,
+        0,    0,    0,    0,    0,   33,   28,    7,    0,    0,
+        0,    0,    0,    0,    0,   31,    0,    0,   32,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   13,
+       12,    0,    0,    0,    0,    0,    0,    0,   44,    0,
+        0,    0,   37,    0,    0,    0,    0,   45,   36,    0,
+        0,   46,    0,    0,    0,    0,   47,   48,    0,    0,
+       49,    0,   50,   51,   34,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
@@ -794,129 +795,134 @@ static const YY_CHAR yy_meta[50] =
         1,    1,    1,    1,    1,    1,    1,    1,    1
     } ;
 
-static const flex_int16_t yy_base[288] =
+static const flex_int16_t yy_base[296] =
     {   0,
-        0,    0,  383,  384,  380,  378,  376,  384,  384,  384,
-      384,  384,    0,  384,   39,   36,  359,  357,   86,  124,
-      384,  384,   35,   38,   34,   37,  341,   48,   43,   58,
-       63,  335,   22,   60,  343,  122,  116,  338,  341,  336,
-      369,  367,  365,  384,    0,    0,  121,  348,  347,    0,
-      346,    0,  384,  147,  158,    0,    0,  384,  334,  326,
-      332,  334,  321,  315,  314,  313,  321,  328,  307,  322,
-      304,  119,  307,  311,  310,  319,  309,  313,  301,  300,
-        0,  312,  298,  304,  313,  302,  309,  309,  289,  308,
-      295,  294,  305,  321,    0,    0,  288,    0,    0,  299,
-
-      299,  300,    0,  295,  282,  294,  280,  283,  280,  291,
-      282,  157,    0,  282,    0,  289,  272,    0,  280,  272,
-      159,  286,  282,  276,    0,  267,  265,  269,  263,  276,
-      275,    0,  260,  273,  275,    0,  259,  256,  269,  254,
-        0,  266,  265,  252,  277,  280,  248,  264,  259,  241,
-      248,  260,    0,    0,  238,  255,  240,  239,    0,  239,
-      166,  241,  250,  269,  238,  235,  232,  234,  231,  231,
-      230,    0,    0,  240,  226,  225,  228,  237,  224,  224,
-      225,  233,  162,  220,    0,  219,  225,  242,  245,  213,
-      214,  213,    0,  210,    0,    0,  211,    0,    0,  217,
-
-        0,  211,  210,  205,  218,    0,  216,    0,  216,    0,
-        0,    0,  210,  214,  199,  198,  201,  231,    0,    0,
-      208,  203,  198,  192,  191,  203,  191,    0,  190,  192,
-        0,  190,  189,  184,  160,  180,  183,  192,  193,  192,
-      175,    0,    0,  188,  176,  175,  187,  180,  172,  184,
-        0,  167,  166,  168,    0,  180,  179,  162,  176,    0,
-        0,  147,  144,    0,  140,  139,  138,  138,    0,    0,
-      129,  126,    0,  123,    0,    0,    0,  384,  190,  162,
-      193,  107,  196,  199,  203,   78,   77
+        0,    0,  391,  392,  388,  386,  384,  392,  392,  392,
+      392,  392,    0,  392,   39,   36,  367,  365,   86,  124,
+      392,  392,   35,   38,   34,   37,  349,   48,   43,  115,
+       63,  343,   22,   60,  351,  122,  116,  130,  350,  345,
+      378,  376,  374,  392,    0,    0,  125,  357,  356,    0,
+      355,    0,  392,  159,  167,    0,    0,  392,  343,  335,
+      341,  343,  330,  324,  323,  322,  330,  337,  316,  331,
+      313,   62,  316,  332,  319,  318,  327,  317,  321,  309,
+      308,    0,  320,  306,  312,  321,  310,  317,  317,  297,
+      316,  315,  302,  301,  312,  328,    0,    0,  295,    0,
+
+        0,  306,  306,  307,    0,  302,  289,  301,  287,  290,
+      287,  298,  289,  159,  282,    0,  288,    0,  295,  278,
+        0,  286,  278,  159,  292,  288,  282,    0,  273,  271,
+      275,  270,  268,  281,  280,    0,  265,  278,  280,    0,
+      264,  261,  274,  259,    0,  271,  270,  257,  282,  285,
+      253,  265,  268,  263,  245,  252,  264,    0,    0,  242,
+      259,  244,  243,    0,  243,  254,  167,  244,  253,  272,
+      241,  238,  235,  237,  234,  234,  233,    0,    0,  243,
+      229,  228,  231,    0,  240,  227,  227,  228,  236,  163,
+      223,    0,  222,  228,    0,  245,  248,  216,  217,  216,
+
+        0,  213,    0,    0,  214,    0,    0,  220,    0,  214,
+      213,  208,  221,    0,  219,    0,  219,    0,    0,    0,
+      213,  217,  202,  201,  204,  234,    0,    0,  211,  206,
+      201,  195,  194,  206,  194,    0,  193,  195,    0,  193,
+      192,  187,  181,  183,  181,  179,  178,  177,  160,    0,
+        0,  172,  160,  159,  171,  164,  156,  168,    0,  151,
+      150,  152,    0,  164,  163,  146,  164,    0,    0,  146,
+      145,    0,  141,  140,  142,  132,    0,    0,  126,  122,
+        0,  119,    0,    0,    0,  392,  211,  146,  214,  107,
+      217,  220,  224,   78,   77
+
     } ;
 
-static const flex_int16_t yy_def[288] =
+static const flex_int16_t yy_def[296] =
     {   0,
-      278,    1,  278,  278,  278,  278,  279,  278,  278,  278,
-      278,  278,  280,  278,  278,   15,  281,  278,  278,   19,
-      278,  278,   19,   19,   19,   19,   20,   20,   20,   20,
+      286,    1,  286,  286,  286,  286,  287,  286,  286,  286,
+      286,  286,  288,  286,  286,   15,  289,  286,  286,   19,
+      286,  286,   19,   19,   19,   19,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-      278,  278,  279,  278,  280,  282,   15,  281,  283,  284,
-      281,  285,  278,  278,   20,   19,   20,  278,   19,   20,
+      286,  286,  287,  286,  288,  290,   15,  289,  291,  292,
+      289,  293,  286,  286,   20,   19,   20,  286,   19,   20,
        20,   20,   20,   19,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,  282,  284,  285,   19,   20,   20,   20,
+       20,   20,   20,   20,   20,  290,  292,  293,   19,   20,
 
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,  286,   20,   20,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,  294,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,  286,   20,   20,   20,   20,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,  294,
+       20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,  287,   20,   20,   20,   20,   20,   20,   20,
 
+      295,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,   20,   20,  287,
+       20,   20,   20,   20,   20,   20,   20,  295,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
        20,   20,   20,   20,   20,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   20,   20,   20,    0,  278,  278,
-      278,  278,  278,  278,  278,  278,  278
+       20,   20,   20,   20,   20,    0,  286,  286,  286,  286,
+      286,  286,  286,  286,  286
+
     } ;
 
-static const flex_int16_t yy_nxt[434] =
+static const flex_int16_t yy_nxt[442] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
        14,   15,   16,   16,   16,   16,   16,   16,   16,   17,
        18,   19,   20,   20,   21,   22,    4,   23,   19,   24,
        25,   26,   19,   27,   28,   29,   20,   30,   31,   32,
        33,   34,   35,   36,   37,   38,   39,   20,   40,   46,
-       47,   47,   47,   47,   47,   47,   47,   47,   48,  278,
-       49,   64,   50,   80,   81,   59,   49,   49,   49,   49,
+       47,   47,   47,   47,   47,   47,   47,   47,   48,  286,
+       49,   64,   50,   81,   82,   59,   49,   49,   49,   49,
        49,   49,   60,   62,   61,   72,   66,   65,   63,   69,
-      220,  164,   73,  278,   67,   70,   50,   54,   54,   74,
-       76,   82,   71,   75,   77,   55,   83,   56,   56,   56,
+      228,  170,   73,  286,   67,   70,   50,   54,   54,  112,
+       77,   83,   71,  113,   78,   55,   84,   56,   56,   56,
 
-       56,   56,   56,   56,   56,   48,   78,   56,   57,   57,
-       94,   58,   55,   56,   56,   56,   56,   56,   56,   57,
+       56,   56,   56,   56,   56,   48,   79,   56,   57,   57,
+       96,   58,   55,   56,   56,   56,   56,   56,   56,   57,
        57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
        57,   57,   57,   57,   57,   57,   57,   57,   57,   57,
-       57,   57,   57,  278,  278,   57,  110,   89,   54,   54,
-      111,   57,   57,   57,   57,   57,   57,   85,   90,  278,
-      278,  278,  278,   86,   87,   45,  277,   88,  278,  145,
-      276,  146,   58,  275,  153,  147,  154,  210,  188,  211,
-      189,  274,  273,  278,  190,  278,  272,  271,  270,  248,
-       43,  269,   43,   43,   43,   43,   51,   51,   51,   49,
-
-       49,   49,   95,  268,   95,   96,   96,   96,   96,  267,
-      266,  265,  264,  263,  262,  261,  260,  259,  258,  257,
-      256,  255,  254,  253,  252,  251,  250,  249,  247,  246,
-      245,  244,  243,  242,  241,  240,  239,  238,  237,  236,
-      235,  234,  233,  232,  231,  230,  229,  228,  227,  226,
-      225,  224,  223,  222,  221,  219,  218,  217,  216,  215,
-      214,  213,  212,  209,  208,  207,  206,  205,  204,  203,
-      202,  201,  200,  199,  198,  197,  196,  195,  194,  193,
-      192,  191,  187,  186,  185,  184,  183,  182,  181,  180,
-      179,  178,  177,  176,  175,  174,  173,  172,  171,  170,
-
-      169,  168,  167,  166,  165,  163,  162,  161,  160,  159,
-      158,  157,  156,  155,  152,  151,  150,  149,  148,  144,
-      143,  142,  141,  140,  139,  138,  137,  136,  135,  134,
-      133,  132,  131,  130,  129,  128,  127,  126,  125,  124,
-      123,  122,  121,  120,  119,  118,  117,  116,  115,  114,
-      113,  112,  109,  108,  107,  106,  105,  104,  103,  102,
-      101,  100,   99,   98,   97,   52,   48,   52,   44,   42,
-       41,   93,   92,   91,   84,   79,   68,   53,   52,   44,
-       42,   41,  278,    3,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278
+       57,   57,   57,  286,   74,   57,   75,   90,  286,   45,
+       76,   57,   57,   57,   57,   57,   57,   86,   91,   92,
+       54,   54,  285,   87,   88,   93,  284,   89,  286,  286,
+      283,  149,  286,  150,  158,  282,  159,  151,  218,  196,
+      219,  197,  286,  286,   58,  198,  281,  280,  279,  278,
+      277,  276,  286,  275,  274,  273,  272,  271,  270,  269,
+
+      268,  267,  266,  265,  264,  263,  286,  262,  261,  260,
+      256,   43,  259,   43,   43,   43,   43,   51,   51,   51,
+       49,   49,   49,   97,  258,   97,   98,   98,   98,   98,
+      257,  255,  254,  253,  252,  251,  250,  249,  248,  247,
+      246,  245,  244,  243,  242,  241,  240,  239,  238,  237,
+      236,  235,  234,  233,  232,  231,  230,  229,  227,  226,
+      225,  224,  223,  222,  221,  220,  217,  216,  215,  214,
+      213,  212,  211,  210,  209,  208,  207,  206,  205,  204,
+      203,  202,  201,  200,  199,  195,  194,  193,  192,  191,
+      190,  189,  188,  187,  186,  185,  184,  183,  182,  181,
+
+      180,  179,  178,  177,  176,  175,  174,  173,  172,  171,
+      169,  168,  167,  166,  165,  164,  163,  162,  161,  160,
+      157,  156,  155,  154,  153,  152,  148,  147,  146,  145,
+      144,  143,  142,  141,  140,  139,  138,  137,  136,  135,
+      134,  133,  132,  131,  130,  129,  128,  127,  126,  125,
+      124,  123,  122,  121,  120,  119,  118,  117,  116,  115,
+      114,  111,  110,  109,  108,  107,  106,  105,  104,  103,
+      102,  101,  100,   99,   52,   48,   52,   44,   42,   41,
+       95,   94,   85,   80,   68,   53,   52,   44,   42,   41,
+      286,    3,  286,  286,  286,  286,  286,  286,  286,  286,
+
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286
     } ;
 
-static const flex_int16_t yy_chk[434] =
+static const flex_int16_t yy_chk[442] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -926,55 +932,56 @@ static const flex_int16_t yy_chk[434] =
        15,   15,   15,   15,   15,   15,   15,   15,   15,   16,
        15,   25,   15,   33,   33,   23,   15,   15,   15,   15,
        15,   15,   23,   24,   23,   29,   26,   25,   24,   28,
-      287,  286,   29,   16,   26,   28,   15,   19,   19,   30,
-       31,   34,   28,   30,   31,   19,   34,   19,   19,   19,
+      295,  294,   29,   16,   26,   28,   15,   19,   19,   72,
+       31,   34,   28,   72,   31,   19,   34,   19,   19,   19,
 
        19,   19,   19,   19,   19,   19,   31,   19,   19,   19,
-      282,   19,   19,   19,   19,   19,   19,   19,   19,   19,
+      290,   19,   19,   19,   19,   19,   19,   19,   19,   19,
        19,   19,   19,   19,   19,   19,   19,   19,   19,   19,
        19,   19,   19,   19,   19,   20,   20,   20,   20,   20,
-       20,   20,   20,   20,   47,   20,   72,   37,   54,   54,
-       72,   20,   20,   20,   20,   20,   20,   36,   37,   55,
-       55,  235,  235,   36,   36,  280,  274,   36,   47,  112,
-      272,  112,   54,  271,  121,  112,  121,  183,  161,  183,
-      161,  268,  267,   55,  161,  235,  266,  265,  263,  235,
-      279,  262,  279,  279,  279,  279,  281,  281,  281,  283,
-
-      283,  283,  284,  259,  284,  285,  285,  285,  285,  258,
-      257,  256,  254,  253,  252,  250,  249,  248,  247,  246,
-      245,  244,  241,  240,  239,  238,  237,  236,  234,  233,
-      232,  230,  229,  227,  226,  225,  224,  223,  222,  221,
-      218,  217,  216,  215,  214,  213,  209,  207,  205,  204,
-      203,  202,  200,  197,  194,  192,  191,  190,  189,  188,
-      187,  186,  184,  182,  181,  180,  179,  178,  177,  176,
-      175,  174,  171,  170,  169,  168,  167,  166,  165,  164,
-      163,  162,  160,  158,  157,  156,  155,  152,  151,  150,
-      149,  148,  147,  146,  145,  144,  143,  142,  140,  139,
-
-      138,  137,  135,  134,  133,  131,  130,  129,  128,  127,
-      126,  124,  123,  122,  120,  119,  117,  116,  114,  111,
-      110,  109,  108,  107,  106,  105,  104,  102,  101,  100,
-       97,   94,   93,   92,   91,   90,   89,   88,   87,   86,
-       85,   84,   83,   82,   80,   79,   78,   77,   76,   75,
-       74,   73,   71,   70,   69,   68,   67,   66,   65,   64,
-       63,   62,   61,   60,   59,   51,   49,   48,   43,   42,
-       41,   40,   39,   38,   35,   32,   27,   18,   17,    7,
-        6,    5,    3,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278,  278,  278,  278,  278,  278,  278,  278,
-      278,  278,  278
+       20,   20,   20,   20,   30,   20,   30,   37,   47,  288,
+       30,   20,   20,   20,   20,   20,   20,   36,   37,   38,
+       54,   54,  282,   36,   36,   38,  280,   36,   55,   55,
+      279,  114,   47,  114,  124,  276,  124,  114,  190,  167,
+      190,  167,  243,  243,   54,  167,  275,  274,  273,  271,
+      270,  267,   55,  266,  265,  264,  262,  261,  260,  258,
+
+      257,  256,  255,  254,  253,  252,  243,  249,  248,  247,
+      243,  287,  246,  287,  287,  287,  287,  289,  289,  289,
+      291,  291,  291,  292,  245,  292,  293,  293,  293,  293,
+      244,  242,  241,  240,  238,  237,  235,  234,  233,  232,
+      231,  230,  229,  226,  225,  224,  223,  222,  221,  217,
+      215,  213,  212,  211,  210,  208,  205,  202,  200,  199,
+      198,  197,  196,  194,  193,  191,  189,  188,  187,  186,
+      185,  183,  182,  181,  180,  177,  176,  175,  174,  173,
+      172,  171,  170,  169,  168,  166,  165,  163,  162,  161,
+      160,  157,  156,  155,  154,  153,  152,  151,  150,  149,
+
+      148,  147,  146,  144,  143,  142,  141,  139,  138,  137,
+      135,  134,  133,  132,  131,  130,  129,  127,  126,  125,
+      123,  122,  120,  119,  117,  115,  113,  112,  111,  110,
+      109,  108,  107,  106,  104,  103,  102,   99,   96,   95,
+       94,   93,   92,   91,   90,   89,   88,   87,   86,   85,
+       84,   83,   81,   80,   79,   78,   77,   76,   75,   74,
+       73,   71,   70,   69,   68,   67,   66,   65,   64,   63,
+       62,   61,   60,   59,   51,   49,   48,   43,   42,   41,
+       40,   39,   35,   32,   27,   18,   17,    7,    6,    5,
+        3,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286,  286,  286,  286,  286,  286,  286,  286,  286,  286,
+      286
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static const flex_int32_t yy_rule_can_match_eol[64] =
+static const flex_int32_t yy_rule_can_match_eol[66] =
     {   0,
 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-    0, 0, 0, 0,     };
+    0, 0, 0, 0, 0, 0,     };
 
 static yy_state_type yy_last_accepting_state;
 static char *yy_last_accepting_cpos;
@@ -982,7 +989,7 @@ static char *yy_last_accepting_cpos;
 extern int yy_flex_debug;
 int yy_flex_debug = 1;
 
-static const flex_int16_t yy_rule_linenum[63] =
+static const flex_int16_t yy_rule_linenum[65] =
     {   0,
       107,  112,  118,  128,  134,  152,  176,  190,  191,  192,
       193,  194,  195,  196,  197,  198,  199,  200,  201,  202,
@@ -990,7 +997,7 @@ static const flex_int16_t yy_rule_linenum[63] =
       213,  214,  215,  216,  217,  218,  219,  220,  221,  222,
       223,  224,  225,  226,  227,  228,  229,  230,  231,  232,
       233,  234,  235,  236,  237,  238,  239,  240,  241,  242,
-      243,  244
+      243,  244,  245,  246
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -1042,7 +1049,7 @@ namespace {
 
 /* To avoid the call to exit... oops! */
 #define YY_FATAL_ERROR(msg) isc::eval::EvalContext::fatal(msg)
-#line 1045 "lexer.cc"
+#line 1053 "lexer.cc"
 /* noyywrap disables automatic rewinding for the next file to parse. Since we
    always parse only a single string, there's no need to do any wraps. And
    using yywrap requires linking with -lfl, which provides the default yywrap
@@ -1067,8 +1074,8 @@ namespace {
    by moving it ahead by yyleng bytes. yyleng specifies the length of the
    currently matched token. */
 #define YY_USER_ACTION  loc.columns(evalleng);
-#line 1070 "lexer.cc"
-#line 1071 "lexer.cc"
+#line 1078 "lexer.cc"
+#line 1079 "lexer.cc"
 
 #define INITIAL 0
 
@@ -1367,7 +1374,7 @@ YY_DECL
 
 
 
-#line 1370 "lexer.cc"
+#line 1378 "lexer.cc"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -1396,13 +1403,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 >= 279 )
+                               if ( yy_current_state >= 287 )
                                        yy_c = yy_meta[yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
                        ++yy_cp;
                        }
-               while ( yy_current_state != 278 );
+               while ( yy_current_state != 286 );
                yy_cp = (yy_last_accepting_cpos);
                yy_current_state = (yy_last_accepting_state);
 
@@ -1431,13 +1438,13 @@ do_action:      /* This label is used only to access EOF actions. */
                        {
                        if ( yy_act == 0 )
                                fprintf( stderr, "--scanner backing up\n" );
-                       else if ( yy_act < 63 )
+                       else if ( yy_act < 65 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], yytext );
-                       else if ( yy_act == 63 )
+                       else if ( yy_act == 65 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         yytext );
-                       else if ( yy_act == 64 )
+                       else if ( yy_act == 66 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1716,138 +1723,148 @@ return isc::eval::EvalParser::make_SUBSTRING(loc);
 case 38:
 YY_RULE_SETUP
 #line 220 "lexer.ll"
-return isc::eval::EvalParser::make_SPLIT(loc);
+return isc::eval::EvalParser::make_LCASE(loc);
        YY_BREAK
 case 39:
 YY_RULE_SETUP
 #line 221 "lexer.ll"
-return isc::eval::EvalParser::make_ALL(loc);
+return isc::eval::EvalParser::make_UCASE(loc);
        YY_BREAK
 case 40:
 YY_RULE_SETUP
 #line 222 "lexer.ll"
-return isc::eval::EvalParser::make_CONCAT(loc);
+return isc::eval::EvalParser::make_SPLIT(loc);
        YY_BREAK
 case 41:
 YY_RULE_SETUP
 #line 223 "lexer.ll"
-return isc::eval::EvalParser::make_IFELSE(loc);
+return isc::eval::EvalParser::make_ALL(loc);
        YY_BREAK
 case 42:
 YY_RULE_SETUP
 #line 224 "lexer.ll"
-return isc::eval::EvalParser::make_TOHEXSTRING(loc);
+return isc::eval::EvalParser::make_CONCAT(loc);
        YY_BREAK
 case 43:
 YY_RULE_SETUP
 #line 225 "lexer.ll"
-return isc::eval::EvalParser::make_ADDRTOTEXT(loc);
+return isc::eval::EvalParser::make_IFELSE(loc);
        YY_BREAK
 case 44:
 YY_RULE_SETUP
 #line 226 "lexer.ll"
-return isc::eval::EvalParser::make_INT8TOTEXT(loc);
+return isc::eval::EvalParser::make_TOHEXSTRING(loc);
        YY_BREAK
 case 45:
 YY_RULE_SETUP
 #line 227 "lexer.ll"
-return isc::eval::EvalParser::make_INT16TOTEXT(loc);
+return isc::eval::EvalParser::make_ADDRTOTEXT(loc);
        YY_BREAK
 case 46:
 YY_RULE_SETUP
 #line 228 "lexer.ll"
-return isc::eval::EvalParser::make_INT32TOTEXT(loc);
+return isc::eval::EvalParser::make_INT8TOTEXT(loc);
        YY_BREAK
 case 47:
 YY_RULE_SETUP
 #line 229 "lexer.ll"
-return isc::eval::EvalParser::make_UINT8TOTEXT(loc);
+return isc::eval::EvalParser::make_INT16TOTEXT(loc);
        YY_BREAK
 case 48:
 YY_RULE_SETUP
 #line 230 "lexer.ll"
-return isc::eval::EvalParser::make_UINT16TOTEXT(loc);
+return isc::eval::EvalParser::make_INT32TOTEXT(loc);
        YY_BREAK
 case 49:
 YY_RULE_SETUP
 #line 231 "lexer.ll"
-return isc::eval::EvalParser::make_UINT32TOTEXT(loc);
+return isc::eval::EvalParser::make_UINT8TOTEXT(loc);
        YY_BREAK
 case 50:
 YY_RULE_SETUP
 #line 232 "lexer.ll"
-return isc::eval::EvalParser::make_NOT(loc);
+return isc::eval::EvalParser::make_UINT16TOTEXT(loc);
        YY_BREAK
 case 51:
 YY_RULE_SETUP
 #line 233 "lexer.ll"
-return isc::eval::EvalParser::make_AND(loc);
+return isc::eval::EvalParser::make_UINT32TOTEXT(loc);
        YY_BREAK
 case 52:
 YY_RULE_SETUP
 #line 234 "lexer.ll"
-return isc::eval::EvalParser::make_OR(loc);
+return isc::eval::EvalParser::make_NOT(loc);
        YY_BREAK
 case 53:
 YY_RULE_SETUP
 #line 235 "lexer.ll"
-return isc::eval::EvalParser::make_MEMBER(loc);
+return isc::eval::EvalParser::make_AND(loc);
        YY_BREAK
 case 54:
 YY_RULE_SETUP
 #line 236 "lexer.ll"
-return isc::eval::EvalParser::make_DOT(loc);
+return isc::eval::EvalParser::make_OR(loc);
        YY_BREAK
 case 55:
 YY_RULE_SETUP
 #line 237 "lexer.ll"
-return isc::eval::EvalParser::make_LPAREN(loc);
+return isc::eval::EvalParser::make_MEMBER(loc);
        YY_BREAK
 case 56:
 YY_RULE_SETUP
 #line 238 "lexer.ll"
-return isc::eval::EvalParser::make_RPAREN(loc);
+return isc::eval::EvalParser::make_DOT(loc);
        YY_BREAK
 case 57:
 YY_RULE_SETUP
 #line 239 "lexer.ll"
-return isc::eval::EvalParser::make_LBRACKET(loc);
+return isc::eval::EvalParser::make_LPAREN(loc);
        YY_BREAK
 case 58:
 YY_RULE_SETUP
 #line 240 "lexer.ll"
-return isc::eval::EvalParser::make_RBRACKET(loc);
+return isc::eval::EvalParser::make_RPAREN(loc);
        YY_BREAK
 case 59:
 YY_RULE_SETUP
 #line 241 "lexer.ll"
-return isc::eval::EvalParser::make_COMA(loc);
+return isc::eval::EvalParser::make_LBRACKET(loc);
        YY_BREAK
 case 60:
 YY_RULE_SETUP
 #line 242 "lexer.ll"
-return isc::eval::EvalParser::make_ANY(loc);
+return isc::eval::EvalParser::make_RBRACKET(loc);
        YY_BREAK
 case 61:
 YY_RULE_SETUP
 #line 243 "lexer.ll"
-return isc::eval::EvalParser::make_PLUS(loc);
+return isc::eval::EvalParser::make_COMA(loc);
        YY_BREAK
 case 62:
 YY_RULE_SETUP
 #line 244 "lexer.ll"
+return isc::eval::EvalParser::make_ANY(loc);
+       YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 245 "lexer.ll"
+return isc::eval::EvalParser::make_PLUS(loc);
+       YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 246 "lexer.ll"
 driver.error (loc, "Invalid character: " + std::string(evaltext));
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 245 "lexer.ll"
+#line 247 "lexer.ll"
 return isc::eval::EvalParser::make_END(loc);
        YY_BREAK
-case 63:
+case 65:
 YY_RULE_SETUP
-#line 246 "lexer.ll"
+#line 248 "lexer.ll"
 ECHO;
        YY_BREAK
-#line 1850 "lexer.cc"
+#line 1868 "lexer.cc"
 
        case YY_END_OF_BUFFER:
                {
@@ -2166,7 +2183,7 @@ static int yy_get_next_buffer (void)
                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 >= 279 )
+                       if ( yy_current_state >= 287 )
                                yy_c = yy_meta[yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -2199,11 +2216,11 @@ static int yy_get_next_buffer (void)
        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 >= 279 )
+               if ( yy_current_state >= 287 )
                        yy_c = yy_meta[yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-       yy_is_jam = (yy_current_state == 278);
+       yy_is_jam = (yy_current_state == 286);
 
                return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2959,7 +2976,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 246 "lexer.ll"
+#line 248 "lexer.ll"
 
 
 using namespace isc::eval;
index b7e83a450c025b8e0774550ab47b705cc0322080..27fcef9971dcfb836d889f703749a2b586e91c41 100644 (file)
@@ -216,6 +216,8 @@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a-fA-F:.]*
 "data"         return isc::eval::EvalParser::make_DATA(loc);
 "enterprise"   return isc::eval::EvalParser::make_ENTERPRISE(loc);
 "substring"    return isc::eval::EvalParser::make_SUBSTRING(loc);
+"lcase"        return isc::eval::EvalParser::make_LCASE(loc);
+"ucase"        return isc::eval::EvalParser::make_UCASE(loc);
 "split"        return isc::eval::EvalParser::make_SPLIT(loc);
 "all"          return isc::eval::EvalParser::make_ALL(loc);
 "concat"       return isc::eval::EvalParser::make_CONCAT(loc);
index e73d694df43595b2512e8a7595cbef097f3547e2..fedafab4ad54e76f7ac53020a52623147a60bdfe 100644 (file)
@@ -463,91 +463,91 @@ namespace isc { namespace eval {
         switch (yykind)
     {
       case symbol_kind::S_STRING: // "constant string"
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < std::string > (); }
 #line 469 "parser.cc"
         break;
 
       case symbol_kind::S_INTEGER: // "integer"
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < std::string > (); }
 #line 475 "parser.cc"
         break;
 
       case symbol_kind::S_HEXSTRING: // "constant hexstring"
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < std::string > (); }
 #line 481 "parser.cc"
         break;
 
       case symbol_kind::S_OPTION_NAME: // "option name"
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < std::string > (); }
 #line 487 "parser.cc"
         break;
 
       case symbol_kind::S_IP_ADDRESS: // "ip address"
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < std::string > (); }
 #line 493 "parser.cc"
         break;
 
       case symbol_kind::S_integer_expr: // integer_expr
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < uint32_t > (); }
 #line 499 "parser.cc"
         break;
 
       case symbol_kind::S_option_code: // option_code
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < uint16_t > (); }
 #line 505 "parser.cc"
         break;
 
       case symbol_kind::S_sub_option_code: // sub_option_code
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < uint16_t > (); }
 #line 511 "parser.cc"
         break;
 
       case symbol_kind::S_option_repr_type: // option_repr_type
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < TokenOption::RepresentationType > (); }
 #line 517 "parser.cc"
         break;
 
       case symbol_kind::S_nest_level: // nest_level
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < int8_t > (); }
 #line 523 "parser.cc"
         break;
 
       case symbol_kind::S_pkt_metadata: // pkt_metadata
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < TokenPkt::MetadataType > (); }
 #line 529 "parser.cc"
         break;
 
       case symbol_kind::S_enterprise_id: // enterprise_id
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < uint32_t > (); }
 #line 535 "parser.cc"
         break;
 
       case symbol_kind::S_pkt4_field: // pkt4_field
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < TokenPkt4::FieldType > (); }
 #line 541 "parser.cc"
         break;
 
       case symbol_kind::S_pkt6_field: // pkt6_field
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < TokenPkt6::FieldType > (); }
 #line 547 "parser.cc"
         break;
 
       case symbol_kind::S_relay6_field: // relay6_field
-#line 127 "parser.yy"
+#line 129 "parser.yy"
                  { yyoutput << yysym.value.template as < TokenRelay6Field::FieldType > (); }
 #line 553 "parser.cc"
         break;
@@ -842,7 +842,7 @@ namespace isc { namespace eval {
           switch (yyn)
             {
   case 6: // bool_expr: "not" bool_expr
-#line 147 "parser.yy"
+#line 149 "parser.yy"
                 {
                     TokenPtr neg(new TokenNot());
                     ctx.expression.push_back(neg);
@@ -851,7 +851,7 @@ namespace isc { namespace eval {
     break;
 
   case 7: // bool_expr: bool_expr "and" bool_expr
-#line 152 "parser.yy"
+#line 154 "parser.yy"
                 {
                     TokenPtr neg(new TokenAnd());
                     ctx.expression.push_back(neg);
@@ -860,7 +860,7 @@ namespace isc { namespace eval {
     break;
 
   case 8: // bool_expr: bool_expr "or" bool_expr
-#line 157 "parser.yy"
+#line 159 "parser.yy"
                 {
                     TokenPtr neg(new TokenOr());
                     ctx.expression.push_back(neg);
@@ -869,7 +869,7 @@ namespace isc { namespace eval {
     break;
 
   case 9: // bool_expr: string_expr "==" string_expr
-#line 162 "parser.yy"
+#line 164 "parser.yy"
                 {
                     TokenPtr eq(new TokenEqual());
                     ctx.expression.push_back(eq);
@@ -878,7 +878,7 @@ namespace isc { namespace eval {
     break;
 
   case 10: // bool_expr: "option" "[" option_code "]" "." "exists"
-#line 167 "parser.yy"
+#line 169 "parser.yy"
                 {
                     TokenPtr opt(new TokenOption(yystack_[3].value.as < uint16_t > (), TokenOption::EXISTS));
                     ctx.expression.push_back(opt);
@@ -887,7 +887,7 @@ namespace isc { namespace eval {
     break;
 
   case 11: // bool_expr: "option" "[" option_code "]" "." "option" "[" sub_option_code "]" "." "exists"
-#line 172 "parser.yy"
+#line 174 "parser.yy"
                 {
                     TokenPtr opt(new TokenSubOption(yystack_[8].value.as < uint16_t > (), yystack_[3].value.as < uint16_t > (), TokenOption::EXISTS));
                     ctx.expression.push_back(opt);
@@ -896,7 +896,7 @@ namespace isc { namespace eval {
     break;
 
   case 12: // bool_expr: "relay4" "[" sub_option_code "]" "." "exists"
-#line 177 "parser.yy"
+#line 179 "parser.yy"
                 {
                    switch (ctx.getUniverse()) {
                    case Option::V4:
@@ -920,7 +920,7 @@ namespace isc { namespace eval {
     break;
 
   case 13: // bool_expr: "relay6" "[" nest_level "]" "." "option" "[" sub_option_code "]" "." "exists"
-#line 197 "parser.yy"
+#line 199 "parser.yy"
                 {
                     switch (ctx.getUniverse()) {
                     case Option::V6:
@@ -938,7 +938,7 @@ namespace isc { namespace eval {
     break;
 
   case 14: // bool_expr: "vendor-class" "[" enterprise_id "]" "." "exists"
-#line 211 "parser.yy"
+#line 213 "parser.yy"
               {
                   // Expression: vendor-class[1234].exists
                   //
@@ -951,7 +951,7 @@ namespace isc { namespace eval {
     break;
 
   case 15: // bool_expr: "vendor" "[" enterprise_id "]" "." "exists"
-#line 220 "parser.yy"
+#line 222 "parser.yy"
               {
                   // Expression: vendor[1234].exists
                   //
@@ -964,7 +964,7 @@ namespace isc { namespace eval {
     break;
 
   case 16: // bool_expr: "vendor" "[" enterprise_id "]" "." "option" "[" sub_option_code "]" "." "exists"
-#line 229 "parser.yy"
+#line 231 "parser.yy"
               {
                   // Expression vendor[1234].option[123].exists
                   //
@@ -978,7 +978,7 @@ namespace isc { namespace eval {
     break;
 
   case 17: // bool_expr: "member" "(" "constant string" ")"
-#line 239 "parser.yy"
+#line 241 "parser.yy"
               {
                   // Expression member('foo')
                   //
@@ -997,7 +997,7 @@ namespace isc { namespace eval {
     break;
 
   case 18: // string_expr: "constant string"
-#line 256 "parser.yy"
+#line 258 "parser.yy"
                   {
                       TokenPtr str(new TokenString(yystack_[0].value.as < std::string > ()));
                       ctx.expression.push_back(str);
@@ -1006,7 +1006,7 @@ namespace isc { namespace eval {
     break;
 
   case 19: // string_expr: "constant hexstring"
-#line 261 "parser.yy"
+#line 263 "parser.yy"
                   {
                       TokenPtr hex(new TokenHexString(yystack_[0].value.as < std::string > ()));
                       ctx.expression.push_back(hex);
@@ -1015,7 +1015,7 @@ namespace isc { namespace eval {
     break;
 
   case 20: // string_expr: "ip address"
-#line 266 "parser.yy"
+#line 268 "parser.yy"
                   {
                       TokenPtr ip(new TokenIpAddress(yystack_[0].value.as < std::string > ()));
                       ctx.expression.push_back(ip);
@@ -1024,7 +1024,7 @@ namespace isc { namespace eval {
     break;
 
   case 21: // string_expr: "option" "[" option_code "]" "." option_repr_type
-#line 271 "parser.yy"
+#line 273 "parser.yy"
                   {
                       TokenPtr opt(new TokenOption(yystack_[3].value.as < uint16_t > (), yystack_[0].value.as < TokenOption::RepresentationType > ()));
                       ctx.expression.push_back(opt);
@@ -1033,7 +1033,7 @@ namespace isc { namespace eval {
     break;
 
   case 22: // string_expr: "option" "[" option_code "]" "." "option" "[" sub_option_code "]" "." option_repr_type
-#line 276 "parser.yy"
+#line 278 "parser.yy"
                   {
                       TokenPtr opt(new TokenSubOption(yystack_[8].value.as < uint16_t > (), yystack_[3].value.as < uint16_t > (), yystack_[0].value.as < TokenOption::RepresentationType > ()));
                       ctx.expression.push_back(opt);
@@ -1042,7 +1042,7 @@ namespace isc { namespace eval {
     break;
 
   case 23: // string_expr: "relay4" "[" sub_option_code "]" "." option_repr_type
-#line 281 "parser.yy"
+#line 283 "parser.yy"
                   {
                      switch (ctx.getUniverse()) {
                      case Option::V4:
@@ -1066,7 +1066,7 @@ namespace isc { namespace eval {
     break;
 
   case 24: // string_expr: "relay6" "[" nest_level "]" "." "option" "[" sub_option_code "]" "." option_repr_type
-#line 302 "parser.yy"
+#line 304 "parser.yy"
                   {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
@@ -1084,7 +1084,7 @@ namespace isc { namespace eval {
     break;
 
   case 25: // string_expr: "pkt" "." pkt_metadata
-#line 317 "parser.yy"
+#line 319 "parser.yy"
                   {
                       TokenPtr pkt_metadata(new TokenPkt(yystack_[0].value.as < TokenPkt::MetadataType > ()));
                       ctx.expression.push_back(pkt_metadata);
@@ -1093,7 +1093,7 @@ namespace isc { namespace eval {
     break;
 
   case 26: // string_expr: "pkt4" "." pkt4_field
-#line 322 "parser.yy"
+#line 324 "parser.yy"
                   {
                      switch (ctx.getUniverse()) {
                      case Option::V4:
@@ -1111,7 +1111,7 @@ namespace isc { namespace eval {
     break;
 
   case 27: // string_expr: "pkt6" "." pkt6_field
-#line 336 "parser.yy"
+#line 338 "parser.yy"
                   {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
@@ -1129,7 +1129,7 @@ namespace isc { namespace eval {
     break;
 
   case 28: // string_expr: "relay6" "[" nest_level "]" "." relay6_field
-#line 350 "parser.yy"
+#line 352 "parser.yy"
                   {
                      switch (ctx.getUniverse()) {
                      case Option::V6:
@@ -1147,7 +1147,7 @@ namespace isc { namespace eval {
     break;
 
   case 29: // string_expr: "substring" "(" string_expr "," start_expr "," length_expr ")"
-#line 365 "parser.yy"
+#line 367 "parser.yy"
                   {
                       TokenPtr sub(new TokenSubstring());
                       ctx.expression.push_back(sub);
@@ -1156,7 +1156,7 @@ namespace isc { namespace eval {
     break;
 
   case 30: // string_expr: "split" "(" string_expr "," string_expr "," int_expr ")"
-#line 370 "parser.yy"
+#line 372 "parser.yy"
                   {
                       TokenPtr split(new TokenSplit());
                       ctx.expression.push_back(split);
@@ -1165,7 +1165,7 @@ namespace isc { namespace eval {
     break;
 
   case 31: // string_expr: "concat" "(" string_expr "," string_expr ")"
-#line 375 "parser.yy"
+#line 377 "parser.yy"
                   {
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
@@ -1174,7 +1174,7 @@ namespace isc { namespace eval {
     break;
 
   case 32: // string_expr: string_expr "+" string_expr
-#line 380 "parser.yy"
+#line 382 "parser.yy"
                   {
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
@@ -1182,89 +1182,107 @@ namespace isc { namespace eval {
 #line 1183 "parser.cc"
     break;
 
-  case 33: // string_expr: "ifelse" "(" bool_expr "," string_expr "," string_expr ")"
-#line 385 "parser.yy"
+  case 33: // string_expr: "lcase" "(" string_expr ")"
+#line 387 "parser.yy"
+                  {
+                      TokenPtr lcase(new TokenLowerCase());
+                      ctx.expression.push_back(lcase);
+                  }
+#line 1192 "parser.cc"
+    break;
+
+  case 34: // string_expr: "ucase" "(" string_expr ")"
+#line 392 "parser.yy"
+                  {
+                      TokenPtr ucase(new TokenUpperCase());
+                      ctx.expression.push_back(ucase);
+                  }
+#line 1201 "parser.cc"
+    break;
+
+  case 35: // string_expr: "ifelse" "(" bool_expr "," string_expr "," string_expr ")"
+#line 397 "parser.yy"
                   {
                       TokenPtr cond(new TokenIfElse());
                       ctx.expression.push_back(cond);
                   }
-#line 1192 "parser.cc"
+#line 1210 "parser.cc"
     break;
 
-  case 34: // string_expr: "hexstring" "(" string_expr "," string_expr ")"
-#line 390 "parser.yy"
+  case 36: // string_expr: "hexstring" "(" string_expr "," string_expr ")"
+#line 402 "parser.yy"
                   {
                       TokenPtr tohex(new TokenToHexString());
                       ctx.expression.push_back(tohex);
                   }
-#line 1201 "parser.cc"
+#line 1219 "parser.cc"
     break;
 
-  case 35: // string_expr: "addrtotext" "(" string_expr ")"
-#line 395 "parser.yy"
+  case 37: // string_expr: "addrtotext" "(" string_expr ")"
+#line 407 "parser.yy"
                   {
                       TokenPtr addrtotext(new TokenIpAddressToText());
                       ctx.expression.push_back(addrtotext);
                   }
-#line 1210 "parser.cc"
+#line 1228 "parser.cc"
     break;
 
-  case 36: // string_expr: "int8totext" "(" string_expr ")"
-#line 400 "parser.yy"
+  case 38: // string_expr: "int8totext" "(" string_expr ")"
+#line 412 "parser.yy"
                   {
                       TokenPtr int8totext(new TokenInt8ToText());
                       ctx.expression.push_back(int8totext);
                   }
-#line 1219 "parser.cc"
+#line 1237 "parser.cc"
     break;
 
-  case 37: // string_expr: "int16totext" "(" string_expr ")"
-#line 405 "parser.yy"
+  case 39: // string_expr: "int16totext" "(" string_expr ")"
+#line 417 "parser.yy"
                   {
                       TokenPtr int16totext(new TokenInt16ToText());
                       ctx.expression.push_back(int16totext);
                   }
-#line 1228 "parser.cc"
+#line 1246 "parser.cc"
     break;
 
-  case 38: // string_expr: "int32totext" "(" string_expr ")"
-#line 410 "parser.yy"
+  case 40: // string_expr: "int32totext" "(" string_expr ")"
+#line 422 "parser.yy"
                   {
                       TokenPtr int32totext(new TokenInt32ToText());
                       ctx.expression.push_back(int32totext);
                   }
-#line 1237 "parser.cc"
+#line 1255 "parser.cc"
     break;
 
-  case 39: // string_expr: "uint8totext" "(" string_expr ")"
-#line 415 "parser.yy"
+  case 41: // string_expr: "uint8totext" "(" string_expr ")"
+#line 427 "parser.yy"
                   {
                       TokenPtr uint8totext(new TokenUInt8ToText());
                       ctx.expression.push_back(uint8totext);
                   }
-#line 1246 "parser.cc"
+#line 1264 "parser.cc"
     break;
 
-  case 40: // string_expr: "uint16totext" "(" string_expr ")"
-#line 420 "parser.yy"
+  case 42: // string_expr: "uint16totext" "(" string_expr ")"
+#line 432 "parser.yy"
                   {
                       TokenPtr uint16totext(new TokenUInt16ToText());
                       ctx.expression.push_back(uint16totext);
                   }
-#line 1255 "parser.cc"
+#line 1273 "parser.cc"
     break;
 
-  case 41: // string_expr: "uint32totext" "(" string_expr ")"
-#line 425 "parser.yy"
+  case 43: // string_expr: "uint32totext" "(" string_expr ")"
+#line 437 "parser.yy"
                   {
                       TokenPtr uint32totext(new TokenUInt32ToText());
                       ctx.expression.push_back(uint32totext);
                   }
-#line 1264 "parser.cc"
+#line 1282 "parser.cc"
     break;
 
-  case 42: // string_expr: "vendor" "." "enterprise"
-#line 430 "parser.yy"
+  case 44: // string_expr: "vendor" "." "enterprise"
+#line 442 "parser.yy"
                 {
                     // expression: vendor.enterprise
                     //
@@ -1273,11 +1291,11 @@ namespace isc { namespace eval {
                     TokenPtr vendor(new TokenVendor(ctx.getUniverse(), 0, TokenVendor::ENTERPRISE_ID));
                     ctx.expression.push_back(vendor);
                 }
-#line 1277 "parser.cc"
+#line 1295 "parser.cc"
     break;
 
-  case 43: // string_expr: "vendor-class" "." "enterprise"
-#line 439 "parser.yy"
+  case 45: // string_expr: "vendor-class" "." "enterprise"
+#line 451 "parser.yy"
                 {
                     // expression: vendor-class.enterprise
                     //
@@ -1287,11 +1305,11 @@ namespace isc { namespace eval {
                                                          TokenVendor::ENTERPRISE_ID));
                     ctx.expression.push_back(vendor);
                 }
-#line 1291 "parser.cc"
+#line 1309 "parser.cc"
     break;
 
-  case 44: // string_expr: "vendor" "[" enterprise_id "]" "." "option" "[" sub_option_code "]" "." option_repr_type
-#line 449 "parser.yy"
+  case 46: // string_expr: "vendor" "[" enterprise_id "]" "." "option" "[" sub_option_code "]" "." option_repr_type
+#line 461 "parser.yy"
                 {
                     // This token will search for vendor option with
                     // specified enterprise-id.  If found, will search
@@ -1300,11 +1318,11 @@ namespace isc { namespace eval {
                     TokenPtr opt(new TokenVendor(ctx.getUniverse(), yystack_[8].value.as < uint32_t > (), yystack_[0].value.as < TokenOption::RepresentationType > (), yystack_[3].value.as < uint16_t > ()));
                     ctx.expression.push_back(opt);
                 }
-#line 1304 "parser.cc"
+#line 1322 "parser.cc"
     break;
 
-  case 45: // string_expr: "vendor-class" "[" enterprise_id "]" "." "data"
-#line 458 "parser.yy"
+  case 47: // string_expr: "vendor-class" "[" enterprise_id "]" "." "data"
+#line 470 "parser.yy"
                 {
                     // expression: vendor-class[1234].data
                     //
@@ -1317,11 +1335,11 @@ namespace isc { namespace eval {
                                                                TokenVendor::DATA, 0));
                     ctx.expression.push_back(vendor_class);
                 }
-#line 1321 "parser.cc"
+#line 1339 "parser.cc"
     break;
 
-  case 46: // string_expr: "vendor-class" "[" enterprise_id "]" "." "data" "[" "integer" "]"
-#line 471 "parser.yy"
+  case 48: // string_expr: "vendor-class" "[" enterprise_id "]" "." "data" "[" "integer" "]"
+#line 483 "parser.yy"
                 {
                     // expression: vendor-class[1234].data[5]
                     //
@@ -1334,264 +1352,264 @@ namespace isc { namespace eval {
                                                                TokenVendor::DATA, index));
                     ctx.expression.push_back(vendor_class);
                 }
-#line 1338 "parser.cc"
+#line 1356 "parser.cc"
     break;
 
-  case 47: // string_expr: integer_expr
-#line 484 "parser.yy"
+  case 49: // string_expr: integer_expr
+#line 496 "parser.yy"
                 {
                     TokenPtr integer(new TokenInteger(yystack_[0].value.as < uint32_t > ()));
                     ctx.expression.push_back(integer);
                 }
-#line 1347 "parser.cc"
+#line 1365 "parser.cc"
     break;
 
-  case 49: // integer_expr: "integer"
-#line 492 "parser.yy"
+  case 51: // integer_expr: "integer"
+#line 504 "parser.yy"
                  {
                      yylhs.value.as < uint32_t > () = ctx.convertUint32(yystack_[0].value.as < std::string > (), yystack_[0].location);
                  }
-#line 1355 "parser.cc"
+#line 1373 "parser.cc"
     break;
 
-  case 50: // option_code: "integer"
-#line 498 "parser.yy"
+  case 52: // option_code: "integer"
+#line 510 "parser.yy"
                  {
                      yylhs.value.as < uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as < std::string > (), yystack_[0].location);
                  }
-#line 1363 "parser.cc"
+#line 1381 "parser.cc"
     break;
 
-  case 51: // option_code: "option name"
-#line 502 "parser.yy"
+  case 53: // option_code: "option name"
+#line 514 "parser.yy"
                  {
                      yylhs.value.as < uint16_t > () = ctx.convertOptionName(yystack_[0].value.as < std::string > (), yystack_[0].location);
                  }
-#line 1371 "parser.cc"
+#line 1389 "parser.cc"
     break;
 
-  case 52: // sub_option_code: "integer"
-#line 508 "parser.yy"
+  case 54: // sub_option_code: "integer"
+#line 520 "parser.yy"
                  {
                      yylhs.value.as < uint16_t > () = ctx.convertOptionCode(yystack_[0].value.as < std::string > (), yystack_[0].location);
                  }
-#line 1379 "parser.cc"
+#line 1397 "parser.cc"
     break;
 
-  case 53: // option_repr_type: "text"
-#line 514 "parser.yy"
+  case 55: // option_repr_type: "text"
+#line 526 "parser.yy"
                       {
                           yylhs.value.as < TokenOption::RepresentationType > () = TokenOption::TEXTUAL;
                       }
-#line 1387 "parser.cc"
+#line 1405 "parser.cc"
     break;
 
-  case 54: // option_repr_type: "hex"
-#line 518 "parser.yy"
+  case 56: // option_repr_type: "hex"
+#line 530 "parser.yy"
                       {
                           yylhs.value.as < TokenOption::RepresentationType > () = TokenOption::HEXADECIMAL;
                       }
-#line 1395 "parser.cc"
+#line 1413 "parser.cc"
     break;
 
-  case 55: // nest_level: "integer"
-#line 524 "parser.yy"
+  case 57: // nest_level: "integer"
+#line 536 "parser.yy"
                  {
                      yylhs.value.as < int8_t > () = ctx.convertNestLevelNumber(yystack_[0].value.as < std::string > (), yystack_[0].location);
                  }
-#line 1403 "parser.cc"
+#line 1421 "parser.cc"
     break;
 
-  case 56: // pkt_metadata: "iface"
-#line 533 "parser.yy"
+  case 58: // pkt_metadata: "iface"
+#line 545 "parser.yy"
                   {
                       yylhs.value.as < TokenPkt::MetadataType > () = TokenPkt::IFACE;
                   }
-#line 1411 "parser.cc"
+#line 1429 "parser.cc"
     break;
 
-  case 57: // pkt_metadata: "src"
-#line 537 "parser.yy"
+  case 59: // pkt_metadata: "src"
+#line 549 "parser.yy"
                   {
                       yylhs.value.as < TokenPkt::MetadataType > () = TokenPkt::SRC;
                   }
-#line 1419 "parser.cc"
+#line 1437 "parser.cc"
     break;
 
-  case 58: // pkt_metadata: "dst"
-#line 541 "parser.yy"
+  case 60: // pkt_metadata: "dst"
+#line 553 "parser.yy"
                   {
                       yylhs.value.as < TokenPkt::MetadataType > () = TokenPkt::DST;
                   }
-#line 1427 "parser.cc"
+#line 1445 "parser.cc"
     break;
 
-  case 59: // pkt_metadata: "len"
-#line 545 "parser.yy"
+  case 61: // pkt_metadata: "len"
+#line 557 "parser.yy"
                   {
                       yylhs.value.as < TokenPkt::MetadataType > () = TokenPkt::LEN;
                   }
-#line 1435 "parser.cc"
+#line 1453 "parser.cc"
     break;
 
-  case 60: // enterprise_id: "integer"
-#line 551 "parser.yy"
+  case 62: // enterprise_id: "integer"
+#line 563 "parser.yy"
                    {
                        yylhs.value.as < uint32_t > () = ctx.convertUint32(yystack_[0].value.as < std::string > (), yystack_[0].location);
                    }
-#line 1443 "parser.cc"
+#line 1461 "parser.cc"
     break;
 
-  case 61: // enterprise_id: "*"
-#line 555 "parser.yy"
+  case 63: // enterprise_id: "*"
+#line 567 "parser.yy"
                    {
                        yylhs.value.as < uint32_t > () = 0;
                    }
-#line 1451 "parser.cc"
+#line 1469 "parser.cc"
     break;
 
-  case 62: // pkt4_field: "mac"
-#line 561 "parser.yy"
+  case 64: // pkt4_field: "mac"
+#line 573 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::CHADDR;
                 }
-#line 1459 "parser.cc"
+#line 1477 "parser.cc"
     break;
 
-  case 63: // pkt4_field: "hlen"
-#line 565 "parser.yy"
+  case 65: // pkt4_field: "hlen"
+#line 577 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::HLEN;
                 }
-#line 1467 "parser.cc"
+#line 1485 "parser.cc"
     break;
 
-  case 64: // pkt4_field: "htype"
-#line 569 "parser.yy"
+  case 66: // pkt4_field: "htype"
+#line 581 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::HTYPE;
                 }
-#line 1475 "parser.cc"
+#line 1493 "parser.cc"
     break;
 
-  case 65: // pkt4_field: "ciaddr"
-#line 573 "parser.yy"
+  case 67: // pkt4_field: "ciaddr"
+#line 585 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::CIADDR;
                 }
-#line 1483 "parser.cc"
+#line 1501 "parser.cc"
     break;
 
-  case 66: // pkt4_field: "giaddr"
-#line 577 "parser.yy"
+  case 68: // pkt4_field: "giaddr"
+#line 589 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::GIADDR;
                 }
-#line 1491 "parser.cc"
+#line 1509 "parser.cc"
     break;
 
-  case 67: // pkt4_field: "yiaddr"
-#line 581 "parser.yy"
+  case 69: // pkt4_field: "yiaddr"
+#line 593 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::YIADDR;
                 }
-#line 1499 "parser.cc"
+#line 1517 "parser.cc"
     break;
 
-  case 68: // pkt4_field: "siaddr"
-#line 585 "parser.yy"
+  case 70: // pkt4_field: "siaddr"
+#line 597 "parser.yy"
                 {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::SIADDR;
                 }
-#line 1507 "parser.cc"
+#line 1525 "parser.cc"
     break;
 
-  case 69: // pkt4_field: "msgtype"
-#line 589 "parser.yy"
+  case 71: // pkt4_field: "msgtype"
+#line 601 "parser.yy"
                  {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::MSGTYPE;
                  }
-#line 1515 "parser.cc"
+#line 1533 "parser.cc"
     break;
 
-  case 70: // pkt4_field: "transid"
-#line 593 "parser.yy"
+  case 72: // pkt4_field: "transid"
+#line 605 "parser.yy"
                  {
                     yylhs.value.as < TokenPkt4::FieldType > () = TokenPkt4::TRANSID;
                  }
-#line 1523 "parser.cc"
+#line 1541 "parser.cc"
     break;
 
-  case 71: // pkt6_field: "msgtype"
-#line 599 "parser.yy"
+  case 73: // pkt6_field: "msgtype"
+#line 611 "parser.yy"
                  {
                      yylhs.value.as < TokenPkt6::FieldType > () = TokenPkt6::MSGTYPE;
                  }
-#line 1531 "parser.cc"
+#line 1549 "parser.cc"
     break;
 
-  case 72: // pkt6_field: "transid"
-#line 603 "parser.yy"
+  case 74: // pkt6_field: "transid"
+#line 615 "parser.yy"
                  {
                      yylhs.value.as < TokenPkt6::FieldType > () = TokenPkt6::TRANSID;
                  }
-#line 1539 "parser.cc"
+#line 1557 "parser.cc"
     break;
 
-  case 73: // relay6_field: "peeraddr"
-#line 609 "parser.yy"
+  case 75: // relay6_field: "peeraddr"
+#line 621 "parser.yy"
                    {
                        yylhs.value.as < TokenRelay6Field::FieldType > () = TokenRelay6Field::PEERADDR;
                    }
-#line 1547 "parser.cc"
+#line 1565 "parser.cc"
     break;
 
-  case 74: // relay6_field: "linkaddr"
-#line 613 "parser.yy"
+  case 76: // relay6_field: "linkaddr"
+#line 625 "parser.yy"
                    {
                        yylhs.value.as < TokenRelay6Field::FieldType > () = TokenRelay6Field::LINKADDR;
                    }
-#line 1555 "parser.cc"
+#line 1573 "parser.cc"
     break;
 
-  case 75: // start_expr: "integer"
-#line 619 "parser.yy"
+  case 77: // start_expr: "integer"
+#line 631 "parser.yy"
                 {
                     TokenPtr str(new TokenString(yystack_[0].value.as < std::string > ()));
                     ctx.expression.push_back(str);
                 }
-#line 1564 "parser.cc"
+#line 1582 "parser.cc"
     break;
 
-  case 76: // length_expr: "integer"
-#line 626 "parser.yy"
+  case 78: // length_expr: "integer"
+#line 638 "parser.yy"
                  {
                      TokenPtr str(new TokenString(yystack_[0].value.as < std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 1573 "parser.cc"
+#line 1591 "parser.cc"
     break;
 
-  case 77: // length_expr: "all"
-#line 631 "parser.yy"
+  case 79: // length_expr: "all"
+#line 643 "parser.yy"
                  {
                      TokenPtr str(new TokenString("all"));
                      ctx.expression.push_back(str);
                  }
-#line 1582 "parser.cc"
+#line 1600 "parser.cc"
     break;
 
-  case 78: // int_expr: "integer"
-#line 637 "parser.yy"
+  case 80: // int_expr: "integer"
+#line 649 "parser.yy"
                  {
                      TokenPtr str(new TokenString(yystack_[0].value.as < std::string > ()));
                      ctx.expression.push_back(str);
                  }
-#line 1591 "parser.cc"
+#line 1609 "parser.cc"
     break;
 
 
-#line 1595 "parser.cc"
+#line 1613 "parser.cc"
 
             default:
               break;
@@ -1943,37 +1961,38 @@ namespace isc { namespace eval {
   }
 
 
-  const short EvalParser::yypact_ninf_ = -156;
+  const short EvalParser::yypact_ninf_ = -160;
 
   const signed char EvalParser::yytable_ninf_ = -1;
 
   const short
   EvalParser::yypact_[] =
   {
-      43,   109,   156,    20,   109,   109,    73,    94,    98,    90,
-      79,   111,   133,   142,   157,   168,   177,   180,   185,   189,
-     190,   192,   211,   219,   207,   112,   131,  -156,  -156,  -156,
-    -156,  -156,   135,    29,  -156,   156,   210,   212,   213,   161,
-     164,   187,  -156,   104,     0,  -156,   -34,   169,   170,   172,
-      82,    52,   156,   156,   156,   109,   156,   156,   156,   156,
-     156,   156,   156,   156,   113,   -39,   176,   -39,   178,   109,
-     109,   156,   156,     1,   -34,   169,   170,   -39,   -39,  -156,
-    -156,  -156,  -156,   217,  -156,   220,  -156,   221,   231,  -156,
-    -156,  -156,  -156,  -156,  -156,  -156,  -156,  -156,  -156,  -156,
-    -156,  -156,  -156,  -156,   147,   150,   173,    10,   174,     2,
-       3,     5,     6,     7,    14,    23,  -156,  -156,  -156,  -156,
-    -156,   222,  -156,   223,  -156,  -156,   234,   187,  -156,   225,
-     226,   227,   228,   229,   230,   232,   233,  -156,   186,   156,
-     156,   156,   156,  -156,  -156,  -156,  -156,  -156,  -156,  -156,
-     235,   236,   237,   238,   239,   240,   241,    16,     4,    78,
-    -156,   214,   181,    25,   184,    26,    11,    77,    80,   188,
-      81,   193,   250,   245,  -156,  -156,  -156,  -156,  -156,  -156,
-     246,  -156,  -156,  -156,   -17,   202,  -156,   156,  -156,  -156,
-     248,   249,  -156,   251,   252,   253,   169,   169,  -156,  -156,
-     261,  -156,   265,    28,   215,   169,   169,   169,   169,   254,
-     255,  -156,  -156,  -156,   256,   257,   258,   260,   262,   263,
-     264,  -156,   266,   267,   268,   269,    97,   106,   155,   188,
-     188,   188,  -156,  -156,  -156,  -156,  -156,  -156
+     -38,   113,   162,    17,   113,   113,    23,    73,    88,   126,
+     100,   132,   163,   166,   183,   191,   195,   198,   211,   212,
+     219,   231,   233,   234,   235,   236,   153,   135,   167,  -160,
+    -160,  -160,  -160,  -160,    36,    62,  -160,   162,   180,   184,
+     225,   170,   174,   138,  -160,   124,     0,  -160,   128,   179,
+     185,   187,    86,    -4,   162,   162,   162,   113,   162,   162,
+     162,   162,   162,   162,   162,   162,   162,   162,    42,    31,
+     186,    31,   188,   113,   113,   162,   162,     2,   128,   179,
+     185,    31,    31,  -160,  -160,  -160,  -160,   226,  -160,   227,
+    -160,   229,   245,  -160,  -160,  -160,  -160,  -160,  -160,  -160,
+    -160,  -160,  -160,  -160,  -160,  -160,  -160,  -160,   181,   182,
+     189,    78,   192,     5,     6,     7,     8,    11,    12,    16,
+      28,    29,  -160,  -160,  -160,  -160,  -160,   237,  -160,   238,
+    -160,  -160,   244,   138,  -160,   239,   240,   241,   242,   243,
+     246,   247,   248,  -160,   190,   162,   162,   162,   162,  -160,
+    -160,  -160,  -160,  -160,  -160,  -160,  -160,  -160,   249,   250,
+     251,   252,   253,   254,   255,    72,    94,    91,  -160,   214,
+     193,    30,   196,    32,   -17,    10,    80,   114,    93,   203,
+     264,   259,  -160,  -160,  -160,  -160,  -160,  -160,   260,  -160,
+    -160,  -160,   -31,   199,  -160,   162,  -160,  -160,   261,   262,
+    -160,   263,   265,   266,   179,   179,  -160,  -160,   258,  -160,
+     275,    33,   220,   179,   179,   179,   179,   267,   268,  -160,
+    -160,  -160,   269,   270,   271,   272,   273,   274,   276,  -160,
+     277,   278,   279,   280,   101,   122,   161,   114,   114,   114,
+    -160,  -160,  -160,  -160,  -160,  -160
   };
 
   const signed char
@@ -1981,152 +2000,157 @@ namespace isc { namespace eval {
   {
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    18,    49,    19,
-      20,     2,     4,     0,    47,     0,     0,     0,     0,     0,
-       0,     3,     1,     0,     0,     6,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    18,
+      51,    19,    20,     2,     4,     0,    49,     0,     0,     0,
+       0,     0,     0,     3,     1,     0,     0,     6,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     5,
-      48,    50,    51,     0,    52,     0,    55,     0,     0,    56,
-      57,    58,    59,    25,    62,    63,    64,    65,    66,    67,
-      68,    69,    70,    26,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,    71,    72,    27,    61,
-      60,     0,    43,     0,    42,     7,     8,     9,    32,     0,
-       0,     0,     0,     0,     0,     0,     0,    17,     0,     0,
-       0,     0,     0,    35,    36,    37,    38,    39,    40,    41,
+       0,     0,     0,     5,    50,    52,    53,     0,    54,     0,
+      57,     0,     0,    58,    59,    60,    61,    25,    64,    65,
+      66,    67,    68,    69,    70,    71,    72,    26,     0,     0,
        0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-      75,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    53,    54,    10,    21,    12,    23,
-       0,    73,    74,    28,     0,     0,    31,     0,    34,    14,
-      45,     0,    15,     0,     0,     0,     0,     0,    77,    76,
-       0,    78,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,    29,    30,    33,     0,     0,     0,     0,     0,     0,
-       0,    46,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    11,    22,    13,    24,    16,    44
+       0,     0,    73,    74,    27,    63,    62,     0,    45,     0,
+      44,     7,     8,     9,    32,     0,     0,     0,     0,     0,
+       0,     0,     0,    17,     0,     0,     0,     0,     0,    37,
+      38,    39,    40,    41,    42,    43,    33,    34,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    77,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    55,    56,    10,    21,    12,    23,     0,    75,
+      76,    28,     0,     0,    31,     0,    36,    14,    47,     0,
+      15,     0,     0,     0,     0,     0,    79,    78,     0,    80,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    29,
+      30,    35,     0,     0,     0,     0,     0,     0,     0,    48,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      11,    22,    13,    24,    16,    46
   };
 
   const short
   EvalParser::yypgoto_[] =
   {
-    -156,  -156,  -156,     8,    -2,  -156,   203,   -74,  -155,   206,
-    -156,   -29,  -156,  -156,  -156,  -156,  -156,  -156
+    -160,  -160,  -160,     9,    -2,  -160,   221,   -78,  -159,   210,
+    -160,    15,  -160,  -160,  -160,  -160,  -160,  -160
   };
 
   const unsigned char
   EvalParser::yydefgoto_[] =
   {
-       0,     3,    31,    32,    33,    34,    83,    85,   177,    87,
-      93,   121,   103,   118,   183,   161,   200,   202
+       0,     3,    33,    34,    35,    36,    87,    89,   185,    91,
+      97,   127,   107,   124,   191,   169,   208,   210
   };
 
   const unsigned char
   EvalParser::yytable_[] =
   {
-      41,   130,    44,   179,    80,    80,   143,   144,    71,   145,
-     146,   147,    43,    45,   179,   119,    69,    70,   148,   198,
-      42,   120,   174,   175,   178,   173,    81,   149,    82,   186,
-     188,   189,   213,    73,   174,   175,   176,    71,   123,    72,
-      72,    72,    72,   199,    72,    72,    72,   141,   132,   133,
-     104,   105,   106,    72,   108,   109,   110,   111,   112,   113,
-     114,   115,    72,   107,    72,    72,   190,    72,    72,   127,
-     128,   233,   235,   237,   233,   235,   237,   125,   126,    94,
-      95,    96,    97,    98,    99,   100,   191,   180,    46,   193,
-     194,   181,   182,    49,   181,   182,    50,   192,   174,   175,
-       1,     2,   101,   102,    89,    90,    91,    92,    79,    47,
-      69,    70,     4,    48,     5,   174,   175,   232,     6,     7,
-       8,     9,   209,   210,   174,   175,   234,    65,    51,    66,
-      10,   215,   216,   217,   218,    11,    52,   162,   163,   164,
-     165,    69,    70,    12,    13,    53,    67,    14,    68,    15,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    35,
-      54,    25,    26,   116,   117,    36,    37,    38,    27,    28,
-      29,    55,    30,   174,   175,   236,    77,    10,    66,    78,
-      56,    68,    11,    57,   138,   203,    72,   139,    58,    72,
-      12,    13,    59,    60,    14,    61,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,   174,   175,    39,    40,
-     140,   142,    72,    72,    62,    27,    28,    29,   185,    30,
-      72,   187,    63,    72,    64,    74,    72,    75,    76,    84,
-      86,    88,   122,   134,   124,   137,   135,   136,   150,   151,
-      69,   152,   153,   154,   155,   156,   160,   157,   190,   158,
-     159,   184,   166,   167,   168,   169,   170,   171,   172,   195,
-     196,   197,   201,   204,   205,   211,   206,   207,   208,   212,
-     219,   220,   221,   222,   223,   214,   224,   129,   225,     0,
-     226,   227,   131,   228,   229,   230,   231
+      43,   136,    46,   197,    84,   206,    84,   187,    75,   149,
+     150,   151,   152,    45,    47,   153,   154,    44,   187,   199,
+     155,     1,     2,    98,    99,   100,   101,   102,   103,   104,
+     200,   207,   156,   157,   194,    77,   196,   221,    48,    76,
+     198,    76,    73,    74,    76,    76,    76,    76,   105,   106,
+      76,    76,   108,   109,   110,    76,   112,   113,   114,   115,
+     116,   117,   118,   119,   120,   121,   111,    76,    76,    76,
+      75,    76,    76,   133,   134,   241,   243,   245,   241,   243,
+     245,   181,   131,   132,    73,    74,   129,   125,    49,   201,
+     182,   183,   184,   126,   122,   123,   138,   139,   182,   183,
+     188,    76,   202,    50,   189,   190,   189,   190,    93,    94,
+      95,    96,   182,   183,   186,   147,     4,    52,     5,   182,
+     183,   240,     6,     7,     8,     9,   217,   218,    83,    51,
+      73,    74,   182,   183,    10,   223,   224,   225,   226,    11,
+     182,   183,   242,   170,   171,   172,   173,    12,    13,    53,
+      69,    14,    70,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    37,    54,    27,    28,    55,
+      68,    38,    39,    40,    29,    30,    31,    76,    32,   182,
+     183,   244,    71,    10,    72,    81,    56,    70,    11,    82,
+      85,    72,    86,   211,    57,    78,    12,    13,    58,    79,
+      14,    59,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    25,    26,    60,    61,    41,    42,   144,   145,
+      76,    76,    62,    29,    30,    31,   146,    32,    76,   148,
+     193,    76,    76,   195,    63,    76,    64,    65,    66,    67,
+      80,    88,   140,   141,   128,   142,   130,    90,    92,   143,
+      73,   192,   168,   158,   159,   160,   161,   162,   163,   164,
+     198,   209,   219,   165,   166,   167,   174,   175,   176,   177,
+     178,   179,   180,   203,   204,   205,   212,   213,   214,   220,
+     215,   216,   222,   227,   228,   229,   230,   231,   232,   233,
+     137,   234,     0,   235,   236,   237,   238,   239,     0,   135
   };
 
   const short
   EvalParser::yycheck_[] =
   {
-       2,    75,     4,   158,     4,     4,     4,     4,     8,     4,
-       4,     4,     4,     5,   169,    54,     6,     7,     4,    36,
-       0,    60,    18,    19,    20,     9,    60,     4,    62,     4,
-       4,    20,     4,    35,    18,    19,    20,     8,    67,    39,
-      39,    39,    39,    60,    39,    39,    39,    37,    77,    78,
-      52,    53,    54,    39,    56,    57,    58,    59,    60,    61,
-      62,    63,    39,    55,    39,    39,    55,    39,    39,    71,
-      72,   226,   227,   228,   229,   230,   231,    69,    70,    27,
-      28,    29,    30,    31,    32,    33,     9,     9,    15,     9,
-       9,    13,    14,     3,    13,    14,    17,    20,    18,    19,
-      57,    58,    50,    51,    22,    23,    24,    25,     4,    15,
-       6,     7,     3,    15,     5,    18,    19,    20,     9,    10,
-      11,    12,   196,   197,    18,    19,    20,    15,    17,    17,
-      21,   205,   206,   207,   208,    26,     3,   139,   140,   141,
-     142,     6,     7,    34,    35,     3,    15,    38,    17,    40,
-      41,    42,    43,    44,    45,    46,    47,    48,    49,     3,
-       3,    52,    53,    50,    51,     9,    10,    11,    59,    60,
-      61,     3,    63,    18,    19,    20,    15,    21,    17,    15,
-       3,    17,    26,     3,    37,   187,    39,    37,     3,    39,
-      34,    35,     3,     3,    38,     3,    40,    41,    42,    43,
-      44,    45,    46,    47,    48,    49,    18,    19,    52,    53,
-      37,    37,    39,    39,     3,    59,    60,    61,    37,    63,
-      39,    37,     3,    39,    17,    15,    39,    15,    15,    60,
-      60,    59,    56,    16,    56,     4,    16,    16,    16,    16,
-       6,    16,    16,    16,    16,    16,    60,    17,    55,    17,
-      17,    37,    17,    17,    17,    17,    17,    17,    17,     9,
-      15,    15,    60,    15,    15,     4,    15,    15,    15,     4,
-      16,    16,    16,    16,    16,    60,    16,    74,    16,    -1,
-      17,    17,    76,    17,    17,    17,    17
+       2,    79,     4,    20,     4,    36,     4,   166,     8,     4,
+       4,     4,     4,     4,     5,     4,     4,     0,   177,     9,
+       4,    59,    60,    27,    28,    29,    30,    31,    32,    33,
+      20,    62,     4,     4,     4,    37,     4,     4,    15,    39,
+      57,    39,     6,     7,    39,    39,    39,    39,    52,    53,
+      39,    39,    54,    55,    56,    39,    58,    59,    60,    61,
+      62,    63,    64,    65,    66,    67,    57,    39,    39,    39,
+       8,    39,    39,    75,    76,   234,   235,   236,   237,   238,
+     239,     9,    73,    74,     6,     7,    71,    56,    15,     9,
+      18,    19,    20,    62,    52,    53,    81,    82,    18,    19,
+       9,    39,     9,    15,    13,    14,    13,    14,    22,    23,
+      24,    25,    18,    19,    20,    37,     3,    17,     5,    18,
+      19,    20,     9,    10,    11,    12,   204,   205,     4,     3,
+       6,     7,    18,    19,    21,   213,   214,   215,   216,    26,
+      18,    19,    20,   145,   146,   147,   148,    34,    35,    17,
+      15,    38,    17,    40,    41,    42,    43,    44,    45,    46,
+      47,    48,    49,    50,    51,     3,     3,    54,    55,     3,
+      17,     9,    10,    11,    61,    62,    63,    39,    65,    18,
+      19,    20,    15,    21,    17,    15,     3,    17,    26,    15,
+      62,    17,    64,   195,     3,    15,    34,    35,     3,    15,
+      38,     3,    40,    41,    42,    43,    44,    45,    46,    47,
+      48,    49,    50,    51,     3,     3,    54,    55,    37,    37,
+      39,    39,     3,    61,    62,    63,    37,    65,    39,    37,
+      37,    39,    39,    37,     3,    39,     3,     3,     3,     3,
+      15,    62,    16,    16,    58,    16,    58,    62,    61,     4,
+       6,    37,    62,    16,    16,    16,    16,    16,    16,    16,
+      57,    62,     4,    17,    17,    17,    17,    17,    17,    17,
+      17,    17,    17,     9,    15,    15,    15,    15,    15,     4,
+      15,    15,    62,    16,    16,    16,    16,    16,    16,    16,
+      80,    17,    -1,    17,    17,    17,    17,    17,    -1,    78
   };
 
   const signed char
   EvalParser::yystos_[] =
   {
-       0,    57,    58,    65,     3,     5,     9,    10,    11,    12,
+       0,    59,    60,    67,     3,     5,     9,    10,    11,    12,
       21,    26,    34,    35,    38,    40,    41,    42,    43,    44,
-      45,    46,    47,    48,    49,    52,    53,    59,    60,    61,
-      63,    66,    67,    68,    69,     3,     9,    10,    11,    52,
-      53,    68,     0,    67,    68,    67,    15,    15,    15,     3,
-      17,    17,     3,     3,     3,     3,     3,     3,     3,     3,
-       3,     3,     3,     3,    17,    15,    17,    15,    17,     6,
-       7,     8,    39,    68,    15,    15,    15,    15,    15,     4,
-       4,    60,    62,    70,    60,    71,    60,    73,    59,    22,
-      23,    24,    25,    74,    27,    28,    29,    30,    31,    32,
-      33,    50,    51,    76,    68,    68,    68,    67,    68,    68,
-      68,    68,    68,    68,    68,    68,    50,    51,    77,    54,
-      60,    75,    56,    75,    56,    67,    67,    68,    68,    70,
-      71,    73,    75,    75,    16,    16,    16,     4,    37,    37,
-      37,    37,    37,     4,     4,     4,     4,     4,     4,     4,
-      16,    16,    16,    16,    16,    16,    16,    17,    17,    17,
-      60,    79,    68,    68,    68,    68,    17,    17,    17,    17,
-      17,    17,    17,     9,    18,    19,    20,    72,    20,    72,
-       9,    13,    14,    78,    37,    37,     4,    37,     4,    20,
-      55,     9,    20,     9,     9,     9,    15,    15,    36,    60,
-      80,    60,    81,    68,    15,    15,    15,    15,    15,    71,
-      71,     4,     4,     4,    60,    71,    71,    71,    71,    16,
-      16,    16,    16,    16,    16,    16,    17,    17,    17,    17,
-      17,    17,    20,    72,    20,    72,    20,    72
+      45,    46,    47,    48,    49,    50,    51,    54,    55,    61,
+      62,    63,    65,    68,    69,    70,    71,     3,     9,    10,
+      11,    54,    55,    70,     0,    69,    70,    69,    15,    15,
+      15,     3,    17,    17,     3,     3,     3,     3,     3,     3,
+       3,     3,     3,     3,     3,     3,     3,     3,    17,    15,
+      17,    15,    17,     6,     7,     8,    39,    70,    15,    15,
+      15,    15,    15,     4,     4,    62,    64,    72,    62,    73,
+      62,    75,    61,    22,    23,    24,    25,    76,    27,    28,
+      29,    30,    31,    32,    33,    52,    53,    78,    70,    70,
+      70,    69,    70,    70,    70,    70,    70,    70,    70,    70,
+      70,    70,    52,    53,    79,    56,    62,    77,    58,    77,
+      58,    69,    69,    70,    70,    72,    73,    75,    77,    77,
+      16,    16,    16,     4,    37,    37,    37,    37,    37,     4,
+       4,     4,     4,     4,     4,     4,     4,     4,    16,    16,
+      16,    16,    16,    16,    16,    17,    17,    17,    62,    81,
+      70,    70,    70,    70,    17,    17,    17,    17,    17,    17,
+      17,     9,    18,    19,    20,    74,    20,    74,     9,    13,
+      14,    80,    37,    37,     4,    37,     4,    20,    57,     9,
+      20,     9,     9,     9,    15,    15,    36,    62,    82,    62,
+      83,    70,    15,    15,    15,    15,    15,    73,    73,     4,
+       4,     4,    62,    73,    73,    73,    73,    16,    16,    16,
+      16,    16,    16,    16,    17,    17,    17,    17,    17,    17,
+      20,    74,    20,    74,    20,    74
   };
 
   const signed char
   EvalParser::yyr1_[] =
   {
-       0,    64,    65,    65,    66,    67,    67,    67,    67,    67,
-      67,    67,    67,    67,    67,    67,    67,    67,    68,    68,
-      68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
-      68,    68,    68,    68,    68,    68,    68,    68,    68,    68,
-      68,    68,    68,    68,    68,    68,    68,    68,    68,    69,
-      70,    70,    71,    72,    72,    73,    74,    74,    74,    74,
-      75,    75,    76,    76,    76,    76,    76,    76,    76,    76,
-      76,    77,    77,    78,    78,    79,    80,    80,    81
+       0,    66,    67,    67,    68,    69,    69,    69,    69,    69,
+      69,    69,    69,    69,    69,    69,    69,    69,    70,    70,
+      70,    70,    70,    70,    70,    70,    70,    70,    70,    70,
+      70,    70,    70,    70,    70,    70,    70,    70,    70,    70,
+      70,    70,    70,    70,    70,    70,    70,    70,    70,    70,
+      70,    71,    72,    72,    73,    74,    74,    75,    76,    76,
+      76,    76,    77,    77,    78,    78,    78,    78,    78,    78,
+      78,    78,    78,    79,    79,    80,    80,    81,    82,    82,
+      83
   };
 
   const signed char
@@ -2135,11 +2159,12 @@ namespace isc { namespace eval {
        0,     2,     2,     2,     1,     3,     2,     3,     3,     3,
        6,    11,     6,    11,     6,     6,    11,     4,     1,     1,
        1,     6,    11,     6,    11,     3,     3,     3,     6,     8,
-       8,     6,     3,     8,     6,     4,     4,     4,     4,     4,
-       4,     4,     3,     3,    11,     6,     9,     1,     3,     1,
+       8,     6,     3,     4,     4,     8,     6,     4,     4,     4,
+       4,     4,     4,     4,     3,     3,    11,     6,     9,     1,
+       3,     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,     1,     1,     1,     1
+       1
   };
 
 
@@ -2158,15 +2183,16 @@ namespace isc { namespace eval {
   "\"siaddr\"", "\"substring\"", "\"split\"", "\"all\"", "\",\"",
   "\"concat\"", "\"+\"", "\"ifelse\"", "\"hexstring\"", "\"addrtotext\"",
   "\"int8totext\"", "\"int16totext\"", "\"int32totext\"",
-  "\"uint8totext\"", "\"uint16totext\"", "\"uint32totext\"", "\"pkt6\"",
-  "\"msgtype\"", "\"transid\"", "\"vendor-class\"", "\"vendor\"", "\"*\"",
-  "\"data\"", "\"enterprise\"", "\"top-level bool\"",
-  "\"top-level string\"", "\"constant string\"", "\"integer\"",
-  "\"constant hexstring\"", "\"option name\"", "\"ip address\"", "$accept",
-  "start", "expression", "bool_expr", "string_expr", "integer_expr",
-  "option_code", "sub_option_code", "option_repr_type", "nest_level",
-  "pkt_metadata", "enterprise_id", "pkt4_field", "pkt6_field",
-  "relay6_field", "start_expr", "length_expr", "int_expr", YY_NULLPTR
+  "\"uint8totext\"", "\"uint16totext\"", "\"uint32totext\"", "\"lcase\"",
+  "\"ucase\"", "\"pkt6\"", "\"msgtype\"", "\"transid\"",
+  "\"vendor-class\"", "\"vendor\"", "\"*\"", "\"data\"", "\"enterprise\"",
+  "\"top-level bool\"", "\"top-level string\"", "\"constant string\"",
+  "\"integer\"", "\"constant hexstring\"", "\"option name\"",
+  "\"ip address\"", "$accept", "start", "expression", "bool_expr",
+  "string_expr", "integer_expr", "option_code", "sub_option_code",
+  "option_repr_type", "nest_level", "pkt_metadata", "enterprise_id",
+  "pkt4_field", "pkt6_field", "relay6_field", "start_expr", "length_expr",
+  "int_expr", YY_NULLPTR
   };
 #endif
 
@@ -2175,14 +2201,15 @@ namespace isc { namespace eval {
   const short
   EvalParser::yyrline_[] =
   {
-       0,   136,   136,   137,   142,   145,   146,   151,   156,   161,
-     166,   171,   176,   196,   210,   219,   228,   238,   255,   260,
-     265,   270,   275,   280,   301,   316,   321,   335,   349,   364,
-     369,   374,   379,   384,   389,   394,   399,   404,   409,   414,
-     419,   424,   429,   438,   448,   457,   470,   483,   488,   491,
-     497,   501,   507,   513,   517,   523,   532,   536,   540,   544,
-     550,   554,   560,   564,   568,   572,   576,   580,   584,   588,
-     592,   598,   602,   608,   612,   618,   625,   630,   636
+       0,   138,   138,   139,   144,   147,   148,   153,   158,   163,
+     168,   173,   178,   198,   212,   221,   230,   240,   257,   262,
+     267,   272,   277,   282,   303,   318,   323,   337,   351,   366,
+     371,   376,   381,   386,   391,   396,   401,   406,   411,   416,
+     421,   426,   431,   436,   441,   450,   460,   469,   482,   495,
+     500,   503,   509,   513,   519,   525,   529,   535,   544,   548,
+     552,   556,   562,   566,   572,   576,   580,   584,   588,   592,
+     596,   600,   604,   610,   614,   620,   624,   630,   637,   642,
+     648
   };
 
   void
@@ -2215,9 +2242,9 @@ namespace isc { namespace eval {
 
 #line 14 "parser.yy"
 } } // isc::eval
-#line 2219 "parser.cc"
+#line 2246 "parser.cc"
 
-#line 643 "parser.yy"
+#line 655 "parser.yy"
 
 void
 isc::eval::EvalParser::error(const location_type& loc,
index 597cf620e431a1b6a0650d1f7a96586cf6a5587f..435035d650db662e03b4ee0d01f145368e21b3ef 100644 (file)
@@ -554,21 +554,23 @@ namespace isc { namespace eval {
     TOKEN_UINT8TOTEXT = 301,       // "uint8totext"
     TOKEN_UINT16TOTEXT = 302,      // "uint16totext"
     TOKEN_UINT32TOTEXT = 303,      // "uint32totext"
-    TOKEN_PKT6 = 304,              // "pkt6"
-    TOKEN_MSGTYPE = 305,           // "msgtype"
-    TOKEN_TRANSID = 306,           // "transid"
-    TOKEN_VENDOR_CLASS = 307,      // "vendor-class"
-    TOKEN_VENDOR = 308,            // "vendor"
-    TOKEN_ANY = 309,               // "*"
-    TOKEN_DATA = 310,              // "data"
-    TOKEN_ENTERPRISE = 311,        // "enterprise"
-    TOKEN_TOPLEVEL_BOOL = 312,     // "top-level bool"
-    TOKEN_TOPLEVEL_STRING = 313,   // "top-level string"
-    TOKEN_STRING = 314,            // "constant string"
-    TOKEN_INTEGER = 315,           // "integer"
-    TOKEN_HEXSTRING = 316,         // "constant hexstring"
-    TOKEN_OPTION_NAME = 317,       // "option name"
-    TOKEN_IP_ADDRESS = 318         // "ip address"
+    TOKEN_LCASE = 304,             // "lcase"
+    TOKEN_UCASE = 305,             // "ucase"
+    TOKEN_PKT6 = 306,              // "pkt6"
+    TOKEN_MSGTYPE = 307,           // "msgtype"
+    TOKEN_TRANSID = 308,           // "transid"
+    TOKEN_VENDOR_CLASS = 309,      // "vendor-class"
+    TOKEN_VENDOR = 310,            // "vendor"
+    TOKEN_ANY = 311,               // "*"
+    TOKEN_DATA = 312,              // "data"
+    TOKEN_ENTERPRISE = 313,        // "enterprise"
+    TOKEN_TOPLEVEL_BOOL = 314,     // "top-level bool"
+    TOKEN_TOPLEVEL_STRING = 315,   // "top-level string"
+    TOKEN_STRING = 316,            // "constant string"
+    TOKEN_INTEGER = 317,           // "integer"
+    TOKEN_HEXSTRING = 318,         // "constant hexstring"
+    TOKEN_OPTION_NAME = 319,       // "option name"
+    TOKEN_IP_ADDRESS = 320         // "ip address"
       };
       /// Backward compatibility alias (Bison 3.6).
       typedef token_kind_type yytokentype;
@@ -585,7 +587,7 @@ namespace isc { namespace eval {
     {
       enum symbol_kind_type
       {
-        YYNTOKENS = 64, ///< Number of tokens.
+        YYNTOKENS = 66, ///< Number of tokens.
         S_YYEMPTY = -2,
         S_YYEOF = 0,                             // "end of file"
         S_YYerror = 1,                           // error
@@ -636,39 +638,41 @@ namespace isc { namespace eval {
         S_UINT8TOTEXT = 46,                      // "uint8totext"
         S_UINT16TOTEXT = 47,                     // "uint16totext"
         S_UINT32TOTEXT = 48,                     // "uint32totext"
-        S_PKT6 = 49,                             // "pkt6"
-        S_MSGTYPE = 50,                          // "msgtype"
-        S_TRANSID = 51,                          // "transid"
-        S_VENDOR_CLASS = 52,                     // "vendor-class"
-        S_VENDOR = 53,                           // "vendor"
-        S_ANY = 54,                              // "*"
-        S_DATA = 55,                             // "data"
-        S_ENTERPRISE = 56,                       // "enterprise"
-        S_TOPLEVEL_BOOL = 57,                    // "top-level bool"
-        S_TOPLEVEL_STRING = 58,                  // "top-level string"
-        S_STRING = 59,                           // "constant string"
-        S_INTEGER = 60,                          // "integer"
-        S_HEXSTRING = 61,                        // "constant hexstring"
-        S_OPTION_NAME = 62,                      // "option name"
-        S_IP_ADDRESS = 63,                       // "ip address"
-        S_YYACCEPT = 64,                         // $accept
-        S_start = 65,                            // start
-        S_expression = 66,                       // expression
-        S_bool_expr = 67,                        // bool_expr
-        S_string_expr = 68,                      // string_expr
-        S_integer_expr = 69,                     // integer_expr
-        S_option_code = 70,                      // option_code
-        S_sub_option_code = 71,                  // sub_option_code
-        S_option_repr_type = 72,                 // option_repr_type
-        S_nest_level = 73,                       // nest_level
-        S_pkt_metadata = 74,                     // pkt_metadata
-        S_enterprise_id = 75,                    // enterprise_id
-        S_pkt4_field = 76,                       // pkt4_field
-        S_pkt6_field = 77,                       // pkt6_field
-        S_relay6_field = 78,                     // relay6_field
-        S_start_expr = 79,                       // start_expr
-        S_length_expr = 80,                      // length_expr
-        S_int_expr = 81                          // int_expr
+        S_LCASE = 49,                            // "lcase"
+        S_UCASE = 50,                            // "ucase"
+        S_PKT6 = 51,                             // "pkt6"
+        S_MSGTYPE = 52,                          // "msgtype"
+        S_TRANSID = 53,                          // "transid"
+        S_VENDOR_CLASS = 54,                     // "vendor-class"
+        S_VENDOR = 55,                           // "vendor"
+        S_ANY = 56,                              // "*"
+        S_DATA = 57,                             // "data"
+        S_ENTERPRISE = 58,                       // "enterprise"
+        S_TOPLEVEL_BOOL = 59,                    // "top-level bool"
+        S_TOPLEVEL_STRING = 60,                  // "top-level string"
+        S_STRING = 61,                           // "constant string"
+        S_INTEGER = 62,                          // "integer"
+        S_HEXSTRING = 63,                        // "constant hexstring"
+        S_OPTION_NAME = 64,                      // "option name"
+        S_IP_ADDRESS = 65,                       // "ip address"
+        S_YYACCEPT = 66,                         // $accept
+        S_start = 67,                            // start
+        S_expression = 68,                       // expression
+        S_bool_expr = 69,                        // bool_expr
+        S_string_expr = 70,                      // string_expr
+        S_integer_expr = 71,                     // integer_expr
+        S_option_code = 72,                      // option_code
+        S_sub_option_code = 73,                  // sub_option_code
+        S_option_repr_type = 74,                 // option_repr_type
+        S_nest_level = 75,                       // nest_level
+        S_pkt_metadata = 76,                     // pkt_metadata
+        S_enterprise_id = 77,                    // enterprise_id
+        S_pkt4_field = 78,                       // pkt4_field
+        S_pkt6_field = 79,                       // pkt6_field
+        S_relay6_field = 80,                     // relay6_field
+        S_start_expr = 81,                       // start_expr
+        S_length_expr = 82,                      // length_expr
+        S_int_expr = 83                          // int_expr
       };
     };
 
@@ -1858,6 +1862,36 @@ switch (yykind)
         return symbol_type (token::TOKEN_UINT32TOTEXT, l);
       }
 #endif
+#if 201103L <= YY_CPLUSPLUS
+      static
+      symbol_type
+      make_LCASE (location_type l)
+      {
+        return symbol_type (token::TOKEN_LCASE, std::move (l));
+      }
+#else
+      static
+      symbol_type
+      make_LCASE (const location_type& l)
+      {
+        return symbol_type (token::TOKEN_LCASE, l);
+      }
+#endif
+#if 201103L <= YY_CPLUSPLUS
+      static
+      symbol_type
+      make_UCASE (location_type l)
+      {
+        return symbol_type (token::TOKEN_UCASE, std::move (l));
+      }
+#else
+      static
+      symbol_type
+      make_UCASE (const location_type& l)
+      {
+        return symbol_type (token::TOKEN_UCASE, l);
+      }
+#endif
 #if 201103L <= YY_CPLUSPLUS
       static
       symbol_type
@@ -2413,9 +2447,9 @@ switch (yykind)
     /// Constants.
     enum
     {
-      yylast_ = 286,     ///< Last index in yytable_.
+      yylast_ = 299,     ///< Last index in yytable_.
       yynnts_ = 18,  ///< Number of nonterminal symbols.
-      yyfinal_ = 42 ///< Termination state number.
+      yyfinal_ = 44 ///< Termination state number.
     };
 
 
@@ -2465,10 +2499,11 @@ switch (yykind)
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    62,    63
+      55,    56,    57,    58,    59,    60,    61,    62,    63,    64,
+      65
     };
     // Last valid token kind.
-    const int code_max = 318;
+    const int code_max = 320;
 
     if (t <= 0)
       return symbol_kind::S_YYEOF;
@@ -2669,7 +2704,7 @@ switch (yykind)
 
 #line 14 "parser.yy"
 } } // isc::eval
-#line 2673 "parser.h"
+#line 2708 "parser.h"
 
 
 
index 2015e8398d4b9053295f12be018c4545d04262a2..07caecd387dc0e492a2a00522d16530d78213ac8 100644 (file)
@@ -89,6 +89,8 @@ using namespace isc::eval;
   UINT8TOTEXT "uint8totext"
   UINT16TOTEXT "uint16totext"
   UINT32TOTEXT "uint32totext"
+  LCASE "lcase"
+  UCASE "ucase"
   PKT6 "pkt6"
   MSGTYPE "msgtype"
   TRANSID "transid"
@@ -381,6 +383,16 @@ string_expr : STRING
                       TokenPtr conc(new TokenConcat());
                       ctx.expression.push_back(conc);
                   }
+            | LCASE "(" string_expr ")"
+                  {
+                      TokenPtr lcase(new TokenLowerCase());
+                      ctx.expression.push_back(lcase);
+                  }
+            | UCASE "(" string_expr ")"
+                  {
+                      TokenPtr ucase(new TokenUpperCase());
+                      ctx.expression.push_back(ucase);
+                  }
             | IFELSE "(" bool_expr "," string_expr "," string_expr ")"
                   {
                       TokenPtr cond(new TokenIfElse());
index 26ef533a99b4cb5a878c35ddb639201d3d7b16eb..2e91a418bcd03e5e9ced0af1fd9a29b07e31e933 100644 (file)
@@ -26,9 +26,7 @@ namespace {
 class EvalContextTest : public ::testing::Test {
 public:
     /// @brief constructor to initialize members
-    EvalContextTest() : ::testing::Test(),
-    universe_(Option::V4), parsed_(false)
-    { }
+    EvalContextTest() : ::testing::Test(), universe_(Option::V4), parsed_(false) { }
 
     /// @brief checks if the given token is a string with the expected value
     void checkTokenString(const TokenPtr& token, const std::string& expected) {
@@ -47,6 +45,46 @@ public:
         EXPECT_EQ(expected, values.top());
     }
 
+    /// @brief checks if the given token is a constant lower case string with
+    /// the expected value
+    void checkTokenLowerCase(const TokenPtr& token, const std::string& expected) {
+        ASSERT_TRUE(token);
+        boost::shared_ptr<TokenLowerCase> str =
+            boost::dynamic_pointer_cast<TokenLowerCase>(token);
+        ASSERT_TRUE(str);
+
+        Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
+        ValueStack values;
+
+        values.push(expected);
+
+        EXPECT_NO_THROW(token->evaluate(*pkt4, values));
+
+        ASSERT_EQ(1, values.size());
+
+        EXPECT_EQ(expected, values.top());
+    }
+
+    /// @brief checks if the given token is a constant upper case string with
+    /// the expected value
+    void checkTokenUpperCase(const TokenPtr& token, const std::string& expected) {
+        ASSERT_TRUE(token);
+        boost::shared_ptr<TokenUpperCase> str =
+            boost::dynamic_pointer_cast<TokenUpperCase>(token);
+        ASSERT_TRUE(str);
+
+        Pkt4Ptr pkt4(new Pkt4(DHCPDISCOVER, 12345));
+        ValueStack values;
+
+        values.push(expected);
+
+        EXPECT_NO_THROW(token->evaluate(*pkt4, values));
+
+        ASSERT_EQ(1, values.size());
+
+        EXPECT_EQ(expected, values.top());
+    }
+
     /// @brief checks if the given token is a hex string with the expected value
     void checkTokenHexString(const TokenPtr& token,
                              const std::string& expected) {
@@ -1510,6 +1548,46 @@ TEST_F(EvalContextTest, toHexString) {
     checkTokenToHexString(tmp3);
 }
 
+// Test the parsing of lcase expression
+TEST_F(EvalContextTest, lcase) {
+    EvalContext eval(Option::V4);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString("lcase('LoWeR') == 'lower'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(4, eval.expression.size());
+
+    TokenPtr tmp1 = eval.expression.at(0);
+    TokenPtr tmp2 = eval.expression.at(1);
+    TokenPtr tmp3 = eval.expression.at(2);
+    TokenPtr tmp4 = eval.expression.at(3);
+
+    checkTokenString(tmp1, "LoWeR");
+    checkTokenLowerCase(tmp2, "lower");
+    checkTokenString(tmp3, "lower");
+    checkTokenEq(tmp4);
+}
+
+// Test the parsing of ucase expression
+TEST_F(EvalContextTest, ucase) {
+    EvalContext eval(Option::V4);
+
+    EXPECT_NO_THROW(parsed_ = eval.parseString("ucase('uPpEr') == 'UPPER'"));
+    EXPECT_TRUE(parsed_);
+
+    ASSERT_EQ(4, eval.expression.size());
+
+    TokenPtr tmp1 = eval.expression.at(0);
+    TokenPtr tmp2 = eval.expression.at(1);
+    TokenPtr tmp3 = eval.expression.at(2);
+    TokenPtr tmp4 = eval.expression.at(3);
+
+    checkTokenString(tmp1, "uPpEr");
+    checkTokenUpperCase(tmp2, "UPPER");
+    checkTokenString(tmp3, "UPPER");
+    checkTokenEq(tmp4);
+}
+
 // Test the parsing of an addrtotext expression
 TEST_F(EvalContextTest, addressToText) {
     {
index bc709275acf804534e0f4052e7d1ea81d4d49f10..5edf6559085b8e054d2d58e63c25be7badc8d06f 100644 (file)
@@ -745,6 +745,48 @@ TEST_F(TokenTest, hexstring6) {
     EXPECT_TRUE(checkFile());
 }
 
+// This simple test checks that a TokenLowerCase, representing a constant lower
+// case string, can be used in Pkt evaluation. (The actual packet is not used)
+TEST_F(TokenTest, lcase) {
+    // Store constant string "lower" in the TokenLowerCase object.
+    ASSERT_NO_THROW(t_.reset(new TokenLowerCase()));
+    values_.push("LoWeR");
+
+    // Make sure that the token can be evaluated without exceptions.
+    ASSERT_NO_THROW(t_->evaluate(*pkt6_, values_));
+
+    // Check that the evaluation put its value on the values stack.
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("lower", values_.top());
+
+    // Check that the debug output was correct.  Add the strings
+    // to the test vector in the class and then call checkFile
+    // for comparison
+    addString("EVAL_DEBUG_LCASE Poping string 'LoWeR' and pushing converted value to lower case 'lower'");
+    EXPECT_TRUE(checkFile());
+}
+
+// This simple test checks that a TokenUpperCase, representing a constant upper
+// case string, can be used in Pkt evaluation. (The actual packet is not used)
+TEST_F(TokenTest, ucase) {
+    // Store constant string "UPPER" in the TokenUpperCase object.
+    ASSERT_NO_THROW(t_.reset(new TokenUpperCase()));
+    values_.push("uPpEr");
+
+    // Make sure that the token can be evaluated without exceptions.
+    ASSERT_NO_THROW(t_->evaluate(*pkt6_, values_));
+
+    // Check that the evaluation put its value on the values stack.
+    ASSERT_EQ(1, values_.size());
+    EXPECT_EQ("UPPER", values_.top());
+
+    // Check that the debug output was correct.  Add the strings
+    // to the test vector in the class and then call checkFile
+    // for comparison
+    addString("EVAL_DEBUG_UCASE Poping string 'uPpEr' and pushing converted value to upper case 'UPPER'");
+    EXPECT_TRUE(checkFile());
+}
+
 // This test checks that a TokenIpAddress, representing an IP address as
 // a constant string, can be used in Pkt4/Pkt6 evaluation.
 // (The actual packet is not used)
index 017f22dd4b7a8eef98352af4a2e341cda25716e2..ff965d33f9ca480ca7c651e129621e5ab40d3eb2 100644 (file)
@@ -20,6 +20,7 @@
 #include <dhcp/option_vendor.h>
 #include <dhcp/option_vendor_class.h>
 
+#include <boost/algorithm/string.hpp>
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/split.hpp>
 
@@ -83,6 +84,42 @@ TokenHexString::evaluate(Pkt& /*pkt*/, ValueStack& values) {
         .arg(toHex(value_));
 }
 
+void
+TokenLowerCase::evaluate(Pkt& /*pkt*/, ValueStack& values) {
+    if (values.size() == 0) {
+        isc_throw(EvalBadStack, "Incorrect empty stack.");
+    }
+
+    string op = values.top();
+
+    values.pop();
+    string result(boost::algorithm::to_lower_copy(op));
+    values.push(result);
+
+    // Log what we pushed
+    LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_LCASE)
+        .arg('\'' + op + '\'')
+        .arg('\'' + result + '\'');
+}
+
+void
+TokenUpperCase::evaluate(Pkt& /*pkt*/, ValueStack& values) {
+    if (values.size() == 0) {
+        isc_throw(EvalBadStack, "Incorrect empty stack.");
+    }
+
+    string op = values.top();
+
+    values.pop();
+    string result(boost::algorithm::to_upper_copy(op));
+    values.push(result);
+
+    // Log what we pushed
+    LOG_DEBUG(eval_logger, EVAL_DBG_STACK, EVAL_DEBUG_UCASE)
+        .arg('\'' + op + '\'')
+        .arg('\'' + result + '\'');
+}
+
 TokenIpAddress::TokenIpAddress(const string& addr) : value_("") {
     // Transform IP address into binary format
     vector<uint8_t> binary;
index 83833af5cb3b94bda078404f48fb924c0c41c178..1d542035979c27333cfb34713bc7e2adba74bb24 100644 (file)
@@ -48,7 +48,6 @@ public:
         isc::Exception(file, line, what) { };
 };
 
-
 /// @brief Base class for all tokens
 ///
 /// It provides an interface for all tokens and storage for string representation
@@ -116,9 +115,7 @@ public:
     /// Value is set during token construction.
     ///
     /// @param str constant string to be represented.
-    TokenString(const std::string& str)
-        : value_(str){
-    }
+    TokenString(const std::string& str) : value_(str) {}
 
     /// @brief Token evaluation (puts value of the constant string on the stack)
     ///
@@ -155,6 +152,40 @@ protected:
     std::string value_; ///< Constant value
 };
 
+/// @brief Token representing a constant lower case string
+///
+/// This token converts a string expression value of the corresponding lower
+/// case string value e.g. it evaluates to "lower" in expression lcase('lOwEr')
+class TokenLowerCase : public Token {
+public:
+    /// @brief Constructor (does nothing)
+    TokenLowerCase() {}
+
+    /// @brief Token evaluation (puts value of the evaluated string expression
+    /// converted to lower case on the stack)
+    ///
+    /// @param pkt (ignored)
+    /// @param values (represented string will be pushed here)
+    void evaluate(Pkt& pkt, ValueStack& values);
+};
+
+/// @brief Token representing a constant upper case string
+///
+/// This token converts a string expression value of the corresponding upper
+/// case string value e.g. it evaluates to "UPPER" in expression lcase('UpPeR')
+class TokenUpperCase : public Token {
+public:
+    /// @brief Constructor (does nothing)
+    TokenUpperCase() {}
+
+    /// @brief Token evaluation (puts value of the evaluated string expression
+    /// converted to upper case on the stack)
+    ///
+    /// @param pkt (ignored)
+    /// @param values (represented string will be pushed here)
+    void evaluate(Pkt& pkt, ValueStack& values);
+};
+
 /// @brief Token representing an unsigned 32 bit integer
 ///
 /// For performance reasons, the constant integer value is converted to a string
@@ -518,8 +549,7 @@ public:
     };
 
     /// @brief Constructor (does nothing)
-    TokenPkt(const MetadataType type)
-        : type_(type) {}
+    TokenPkt(const MetadataType type) : type_(type) {}
 
     /// @brief Gets a value from the specified packet.
     ///
@@ -875,7 +905,7 @@ public:
 class TokenIfElse : public Token {
 public:
     /// @brief Constructor (does nothing)
-    TokenIfElse() { }
+    TokenIfElse() {}
 
     /// @brief Alternative.
     ///
@@ -905,7 +935,7 @@ public:
 class TokenToHexString : public Token {
 public:
     /// @brief Constructor (does nothing)
-    TokenToHexString() { }
+    TokenToHexString() {}
 
     /// @brief Convert a binary value to its hexadecimal string representation
     ///
@@ -1017,7 +1047,7 @@ public:
     ///
     /// @param client_class client class name
     TokenMember(const std::string& client_class)
-        : client_class_(client_class){
+        : client_class_(client_class) {
     }
 
     /// @brief Token evaluation (check if client_class_ was added to
@@ -1074,7 +1104,6 @@ public:
     /// @param field specifies which field should be returned
     TokenVendor(Option::Universe u, uint32_t vendor_id, FieldType field);
 
-
     /// @brief Constructor used for accessing an option
     ///
     /// This constructor is used for accessing suboptions. In general