]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5110] D2 now uses JSON parsing and SimpleParsers to handle D2 global scalars
authorThomas Markwalder <tmark@isc.org>
Tue, 24 Jan 2017 15:45:50 +0000 (10:45 -0500)
committerThomas Markwalder <tmark@isc.org>
Thu, 26 Jan 2017 19:37:31 +0000 (14:37 -0500)
new files:
    src/bin/d2/tests/
        d2_simple_parser_unittest.cc
        parser_unittest.cc
        parser_unittest.h

src/bin/d2/d2_cfg_mgr.h
src/bin/d2/d2_cfg_mgr.cc
    D2CfgMgr::parseElement() - overrides base class implementation,
    flag global parameters as parsed without pushing them to D2CfgContext
    value stores

    D2CfgMgr::setCfgDefaults() - overrides base class implementation,
    sets defaults for D2

    D2CfgMgr::buildParams() - revamped to pull parameters from the given
    element map instead of context value stores.  Removed checks that
    are now done by JSON parser.

src/bin/d2/d2_controller.cc
    D2Controller::parseFile() - instead of generic JSON parsing, parse
    file with PARSER_DHCPDDNS context

src/bin/d2/d2_lexer.ll
src/bin/d2/d2_parser.yy
    Changed namespace from dhcp to d2
    Added PARSER_SUB_DHCPDDNS and D2 global parameter parsing
    Added objects for forward-ddns, reverse-ddns, tsig-keys

src/bin/d2/parser_context.cc
src/bin/d2/parser_context.h
    Added PARSER_DHCPDDNS, PARSER_SUB_DHCPDDNS

src/bin/d2/tests/Makefile.am
    Added new test source files

src/bin/d2/tests/d2_cfg_mgr_unittests.cc
src/bin/d2/tests/testdata/d2_cfg_tests.json
    TEST_F(D2CfgMgrTest, configPermutations) - revamped to test JSON parsing
    as well as element parsing

src/bin/d2/tests/parser_unittest.h
src/bin/d2/tests/parser_unittest.cc
    New file that tests basic JSON parsing

src/lib/cc/data.h
    Added parens around TypeError position error text

src/lib/cc/simple_parser.cc
    SimpleParser::setDefaults() - added logic to detect bad lexical casts
    when handling integers

24 files changed:
src/bin/d2/d2_cfg_mgr.cc
src/bin/d2/d2_cfg_mgr.h
src/bin/d2/d2_controller.cc
src/bin/d2/d2_lexer.cc
src/bin/d2/d2_lexer.ll
src/bin/d2/d2_parser.cc
src/bin/d2/d2_parser.h
src/bin/d2/d2_parser.yy
src/bin/d2/d2_simple_parser.cc
src/bin/d2/d2_simple_parser.h
src/bin/d2/location.hh
src/bin/d2/parser_context.cc
src/bin/d2/parser_context.h
src/bin/d2/parser_context_decl.h
src/bin/d2/position.hh
src/bin/d2/stack.hh
src/bin/d2/tests/Makefile.am
src/bin/d2/tests/d2_cfg_mgr_unittests.cc
src/bin/d2/tests/d2_simple_parser_unittest.cc [new file with mode: 0644]
src/bin/d2/tests/parser_unittest.cc [new file with mode: 0644]
src/bin/d2/tests/parser_unittest.h [new file with mode: 0644]
src/bin/d2/tests/testdata/d2_cfg_tests.json
src/lib/cc/data.h
src/lib/cc/simple_parser.cc

index 53d60c150d08a466ada5f5a2b19f6820b9657807..6b2567cc6f4ff39ebc37d2d2bc6d36d92cffadec 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <d2/d2_log.h>
 #include <d2/d2_cfg_mgr.h>
+#include <d2/d2_simple_parser.h>
 #include <util/encode/hex.h>
 
 #include <boost/foreach.hpp>
@@ -197,96 +198,148 @@ D2CfgMgr::getConfigSummary(const uint32_t) {
     return (getD2Params()->getConfigSummary());
 }
 
-void
-D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
-    // Base class build creates parses and invokes build on each parser.
-    // This populate the context scalar stores with all of the parameters.
-    DCfgMgrBase::buildParams(params_config);
-
-    // Fetch and validate the parameters from the context to create D2Params.
-    // We validate them here rather than just relying on D2Param constructor
-    // so we can spit out config text position info with errors.
+namespace {
 
-    // Fetch and validate ip_address.
-    D2CfgContextPtr context = getD2CfgContext();
-    isc::dhcp::StringStoragePtr strings = context->getStringStorage();
-    asiolink::IOAddress ip_address(D2Params::DFT_IP_ADDRESS);
+template <typename int_type> int_type
+getInt(const std::string& name, isc::data::ConstElementPtr value) {
+    int64_t val_int = value->intValue();
+    if ((val_int < std::numeric_limits<int_type>::min()) ||
+        (val_int > std::numeric_limits<int_type>::max())) {
+        isc_throw(D2CfgError, "out of range value (" << val_int
+                  << ") specified for parameter '" << name
+                  << "' (" << value->getPosition() << ")");
+    }
+    return (static_cast<int_type>(val_int));
+}
 
-    std::string ip_address_str = strings->getOptionalParam("ip-address",
-                                                            D2Params::
-                                                            DFT_IP_ADDRESS);
+isc::asiolink::IOAddress
+getIOAddress(const std::string& name, isc::data::ConstElementPtr value) {
+    std::string str = value->stringValue();
     try {
-        ip_address = asiolink::IOAddress(ip_address_str);
+        return (isc::asiolink::IOAddress(str));
     } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "IP address invalid : \""
-                  << ip_address_str << "\" ("
-                  << strings->getPosition("ip-address") << ")");
+        isc_throw(D2CfgError, "invalid address (" << str
+                  << ") specified for parameter '" << name
+                  << "' (" << value->getPosition() << ")");
     }
+}
 
-    if ((ip_address.toText() == "0.0.0.0") || (ip_address.toText() == "::")) {
-        isc_throw(D2CfgError, "IP address cannot be \"" << ip_address << "\" ("
-                   << strings->getPosition("ip-address") << ")");
+dhcp_ddns::NameChangeProtocol
+getProtocol(const std::string& name, isc::data::ConstElementPtr value) {
+    std::string str = value->stringValue();
+    try {
+        return (dhcp_ddns::stringToNcrProtocol(str));
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError,
+                  "invalid NameChangeRequest protocol (" << str
+                  << ") specified for parameter '" << name
+                  << "' (" << value->getPosition() << ")");
     }
+}
 
-    // Fetch and validate port.
-    isc::dhcp::Uint32StoragePtr ints = context->getUint32Storage();
-    uint32_t port = ints->getOptionalParam("port", D2Params::DFT_PORT);
-
-    if (port == 0) {
-        isc_throw(D2CfgError, "port cannot be 0 ("
-                  << ints->getPosition("port") << ")");
+dhcp_ddns::NameChangeFormat
+getFormat(const std::string& name, isc::data::ConstElementPtr value) {
+    std::string str = value->stringValue();
+    try {
+        return (dhcp_ddns::stringToNcrFormat(str));
+    } catch (const std::exception& ex) {
+        isc_throw(D2CfgError,
+                  "invalid NameChangeRequest format (" << str
+                  << ") specified for parameter '" << name
+                  << "' (" << value->getPosition() << ")");
     }
+}
 
-    // Fetch and validate dns_server_timeout.
-    uint32_t dns_server_timeout
-        = ints->getOptionalParam("dns-server-timeout",
-                                 D2Params::DFT_DNS_SERVER_TIMEOUT);
+} // anon
 
-    if (dns_server_timeout < 1) {
-        isc_throw(D2CfgError, "DNS server timeout must be larger than 0 ("
-                  << ints->getPosition("dns-server-timeout") << ")");
-    }
+bool
+D2CfgMgr::parseElement(const std::string& element_id,
+                       isc::data::ConstElementPtr element) {
 
-    // Fetch and validate ncr_protocol.
-    dhcp_ddns::NameChangeProtocol ncr_protocol;
+    // Get D2 specific context.
     try {
-        ncr_protocol = dhcp_ddns::
-                       stringToNcrProtocol(strings->
-                                           getOptionalParam("ncr-protocol",
-                                                            D2Params::
-                                                            DFT_NCR_PROTOCOL));
+        D2CfgContextPtr context = getD2CfgContext();
+        if ((element_id == "ip-address") ||
+            (element_id == "ncr-protocol") ||
+            (element_id == "ncr-format") ||
+            (element_id == "port")  ||
+            (element_id == "dns-server-timeout"))  {
+            // global scalar params require nothing extra
+        } else {
+            // not something we handle here
+            return (false);
+        }
     } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "ncr-protocol : "
-                  << ex.what() << " ("
-                  << strings->getPosition("ncr-protocol") << ")");
+        isc_throw(D2CfgError, "element: " << element_id << " : "  << ex.what()
+                              << element->getPosition());
     }
 
-    if (ncr_protocol != dhcp_ddns::NCR_UDP) {
-        isc_throw(D2CfgError, "ncr-protocol : "
-                  << dhcp_ddns::ncrProtocolToString(ncr_protocol)
-                  << " is not yet supported ("
-                  << strings->getPosition("ncr-protocol") << ")");
-    }
+    return (true);
+};
 
-    // Fetch and validate ncr_format.
-    dhcp_ddns::NameChangeFormat ncr_format;
-    try {
-        ncr_format = dhcp_ddns::
-                     stringToNcrFormat(strings->
-                                       getOptionalParam("ncr-format",
-                                                        D2Params::
-                                                        DFT_NCR_FORMAT));
-    } catch (const std::exception& ex) {
-        isc_throw(D2CfgError, "ncr-format : "
-                  << ex.what() << " ("
-                  << strings->getPosition("ncr-format") << ")");
-    }
+void
+D2CfgMgr::setCfgDefaults(isc::data::ElementPtr mutable_config) {
+    D2SimpleParser::setAllDefaults(mutable_config);
+}
+
+void
+D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
+
+    // Base class build creates parses and invokes build on each parser.
+    // This populate the context scalar stores with all of the parameters.
+    DCfgMgrBase::buildParams(params_config);
+
+    // Fetch the parameters in the config, performing any logcial
+    // validation required.
+    asiolink::IOAddress ip_address(0);
+    uint32_t port = 0;
+    uint32_t dns_server_timeout = 0;
+    dhcp_ddns::NameChangeProtocol ncr_protocol = dhcp_ddns::NCR_UDP;
+    dhcp_ddns::NameChangeFormat ncr_format = dhcp_ddns::FMT_JSON;
+
+    BOOST_FOREACH(isc::dhcp::ConfigPair param, params_config->mapValue()) {
+        std::string entry(param.first);
+        isc::data::ConstElementPtr value(param.second);
+        try {
+            if (entry == "ip-address") {
+                ip_address = getIOAddress(entry, value);
+                if ((ip_address.toText() == "0.0.0.0") ||
+                    (ip_address.toText() == "::")) {
+                    isc_throw(D2CfgError, "IP address cannot be \""
+                              << ip_address << "\""
+                            << " (" << value->getPosition() << ")");
+                }
+            } else if (entry == "port") {
+                port = getInt<uint32_t>(entry, value);
+            } else if (entry == "dns-server-timeout") {
+                dns_server_timeout = getInt<uint32_t>(entry, value);
+            } else if (entry == "ncr-protocol") {
+                ncr_protocol = getProtocol(entry, value);
+                if (ncr_protocol != dhcp_ddns::NCR_UDP) {
+                    isc_throw(D2CfgError, "ncr-protocol : "
+                              << dhcp_ddns::ncrProtocolToString(ncr_protocol)
+                              << " is not yet supported "
+                              << " (" << value->getPosition() << ")");
+                }
+            } else if (entry == "ncr-format") {
+                ncr_format = getFormat(entry, value);
+                if (ncr_format != dhcp_ddns::FMT_JSON) {
+                    isc_throw(D2CfgError, "NCR Format:"
+                              << dhcp_ddns::ncrFormatToString(ncr_format)
+                              << " is not yet supported"
+                              << " (" << value->getPosition() << ")");
+                }
+            } else {
+                isc_throw(D2CfgError,
+                          "unsupported parameter '" << entry
+                          << " (" << value->getPosition() << ")");
+            }
+        } catch (const isc::data::TypeError&) {
+            isc_throw(D2CfgError,
+                      "invalid value type specified for parameter '" << entry
+                      << " (" << value->getPosition() << ")");
+        }
 
-    if (ncr_format != dhcp_ddns::FMT_JSON) {
-        isc_throw(D2CfgError, "NCR Format:"
-                  << dhcp_ddns::ncrFormatToString(ncr_format)
-                  << " is not yet supported ("
-                  << strings->getPosition("ncr-format") << ")");
     }
 
     // Attempt to create the new client config. This ought to fly as
@@ -294,7 +347,7 @@ D2CfgMgr::buildParams(isc::data::ConstElementPtr params_config) {
     D2ParamsPtr params(new D2Params(ip_address, port, dns_server_timeout,
                                     ncr_protocol, ncr_format));
 
-    context->getD2Params() = params;
+    getD2CfgContext()->getD2Params() = params;
 }
 
 isc::dhcp::ParserPtr
index c79b7dd962e8b12d792abbcd17fcb4ad28e0835e..980d8bda69d04be10fcfcb74841902fa1c2c0d86 100644 (file)
@@ -239,6 +239,31 @@ public:
     virtual std::string getConfigSummary(const uint32_t selection);
 
 protected:
+
+    /// @brief Parses an element using alternate parsers
+    ///
+    /// Each element to be parsed is passed first into this method to allow
+    /// it to be processed by SimpleParser derivations if they've been
+    /// implemented. The method should return true if it has processed the
+    /// element or false if the element should be passed onto the original
+    /// DhcpConfigParer mechanisms.  This method is invoked in both
+    /// @c DCfgMgrBase::buildParams() and DCfgMgrBase::buildAndCommit().
+    ///
+    /// @param element_id name of the element as it is expected in the cfg
+    /// @param element value of the element as ElementPtr
+    ///
+    /// @return true if the element was parsed, false otherwise
+    virtual bool parseElement(const std::string& element_id,
+                              isc::data::ConstElementPtr element);
+
+    /// @brief Adds default values to the given config
+    ///
+    /// Adds the D2 default values to the configuration Element map. This
+    /// method is invoked by @c DCfgMgrBase::paserConfig().
+    ///
+    /// @param mutable_config - configuration to which defaults should be added
+    virtual void setCfgDefaults(isc::data::ElementPtr mutable_config);
+
     /// @brief Performs the parsing of the given "params" element.
     ///
     /// Iterates over the set of parameters, creating a parser based on the
index acec9507c9a02651cb37919d51339fea0c7154dd..9e12c808d565413a98e5d9247f0511318fe26f95 100644 (file)
@@ -61,7 +61,7 @@ D2Controller::parseFile(const std::string& file_name) {
 
     // Read contents of the file and parse it as JSON
     D2ParserContext parser;
-    elements = parser.parseFile(file_name, D2ParserContext::PARSER_JSON);
+    elements = parser.parseFile(file_name, D2ParserContext::PARSER_DHCPDDNS);
     if (!elements) {
         isc_throw(isc::BadValue, "no configuration found in file");
     }
index 4b88c459fd6dcd6c3615d4888e6570ba70f5061c..1e51ee4f27d43eda30ebc75c1787a2000f606c59 100644 (file)
@@ -524,8 +524,8 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
 /* %% [3.0] code to copy yytext_ptr to d2_parser_text[] 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 43
-#define YY_END_OF_BUFFER 44
+#define YY_NUM_RULES 51
+#define YY_END_OF_BUFFER 52
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -533,31 +533,38 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static const flex_int16_t yy_accept[207] =
+static const flex_int16_t yy_accept[278] =
     {   0,
-       36,   36,    0,    0,    0,    0,    0,    0,    0,    0,
-       44,   42,   10,   11,   42,    1,   36,   33,   36,   36,
-       42,   35,   34,   42,   42,   42,   42,   42,   29,   30,
-       42,   42,   42,   31,   32,    5,    5,    5,   42,   42,
-       42,   10,   11,    0,    0,   25,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,    1,   36,
-       36,    0,   35,   36,    3,    2,    6,    0,   36,    0,
-        0,    0,    0,    0,    0,    4,    0,    0,    9,    0,
-       26,    0,    0,    0,    0,    0,    0,   28,    0,    0,
-        0,    0,    0,    0,    0,    0,    2,    0,    0,    0,
+       44,   44,    0,    0,    0,    0,    0,    0,    0,    0,
+       52,   50,   10,   11,   50,    1,   44,   41,   44,   44,
+       50,   43,   42,   50,   50,   50,   50,   50,   37,   38,
+       50,   50,   50,   39,   40,    5,    5,    5,   50,   50,
+       50,   10,   11,    0,    0,   33,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    1,   44,   44,    0,   43,   44,    3,    2,
+        6,    0,   44,    0,    0,    0,    0,    0,    0,    4,
+        0,    0,    9,    0,   34,    0,    0,    0,    0,    0,
+        0,    0,   36,    0,    0,    0,    0,    0,    0,    0,
 
+        0,    0,    0,    0,    0,    0,    2,    0,    0,    0,
         0,    0,    0,    0,    8,    0,    0,    0,    0,    0,
-        0,   27,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,   41,   39,    0,   38,   37,    0,    0,    0,    0,
-       17,   16,    0,    0,    0,    0,    0,    0,    0,    0,
-       40,   37,    0,    0,   18,    0,    0,    0,    0,    0,
-        0,    0,    0,   13,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    7,    0,    0,    0,    0,
-        0,    0,   22,    0,    0,   19,    0,    0,   20,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   24,    0,
-        0,    0,    0,    0,   23,   12,   15,    0,    0,    0,
-
-        0,   14,    0,    0,   21,    0
+        0,    0,   35,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   49,   47,    0,
+       46,   45,    0,    0,    0,    0,    0,   19,   18,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   48,   45,    0,    0,    0,    0,    0,   20,
+        0,    0,    0,    0,    0,    0,    0,   28,    0,    0,
+        0,   14,    0,    0,    0,    0,    0,   31,   32,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    7,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   27,    0,    0,    0,    0,    0,   24,    0,
+        0,    0,    0,   25,    0,    0,    0,    0,    0,    0,
+       12,    0,    0,    0,    0,    0,    0,    0,    0,   30,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   23,
+       29,    0,    0,   13,   17,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   21,   16,    0,   22,    0,    0,
+        0,   26,    0,    0,    0,   15,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
@@ -567,15 +574,15 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    4,    5,    6,    7,    5,    5,    5,    5,    5,
         5,    8,    9,   10,   11,   12,   13,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,   15,    5,   16,
-        5,   17,   18,    5,   19,   20,   21,   22,   23,   24,
-        5,    5,    5,   25,    5,   26,    5,   27,   28,   29,
-        5,   30,   31,   32,   33,    5,    5,    5,    5,    5,
-       34,   35,   36,    5,   37,    5,   38,   39,   40,   41,
-
-       42,   43,   44,    5,   45,   46,    5,   47,   48,   49,
-       50,   51,    5,   52,   53,   54,   55,   56,    5,    5,
-       57,    5,   58,    5,   59,    5,    5,    5,    5,    5,
+       14,   15,   14,   16,   14,   14,   14,   17,    5,   18,
+        5,   19,   20,    5,   21,   22,   23,   24,   25,   26,
+        5,    5,    5,   27,    5,   28,    5,   29,   30,   31,
+        5,   32,   33,   34,   35,    5,    5,    5,    5,    5,
+       36,   37,   38,    5,   39,    5,   40,   41,   42,   43,
+
+       44,   45,   46,   47,   48,   49,   50,   51,   52,   53,
+       54,   55,    5,   56,   57,   58,   59,   60,   61,    5,
+       62,    5,   63,    5,   64,    5,    5,    5,    5,    5,
         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
         5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
@@ -592,344 +599,499 @@ static const YY_CHAR yy_ec[256] =
         5,    5,    5,    5,    5
     } ;
 
-static const YY_CHAR yy_meta[60] =
+static const YY_CHAR yy_meta[65] =
     {   0,
         1,    1,    2,    3,    3,    4,    3,    3,    3,    3,
-        3,    3,    5,    6,    3,    3,    3,    3,    6,    6,
-        6,    6,    6,    6,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    5,    3,    3,    6,    7,    6,
-        6,    6,    7,    3,    3,    3,    3,    3,    5,    3,
-        3,    5,    3,    5,    5,    3,    3,    3,    3
+        3,    3,    3,    5,    5,    5,    3,    3,    3,    3,
+        5,    5,    5,    5,    5,    5,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    5,
+        5,    5,    5,    5,    5,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3
     } ;
 
-static const flex_int16_t yy_base[220] =
+static const flex_int16_t yy_base[290] =
     {   0,
-        0,    0,   58,   61,   64,    0,   66,   75,   49,   50,
-      280, 1144,   80,  268,  123,    0,   85, 1144,   89,   79,
-       77,  105, 1144,  251,  121,   67,   59,   85, 1144, 1144,
-      114,   83,  109, 1144, 1144, 1144,  132,  255,  209,    0,
-      232,  138,  245,  140,  178, 1144,  184,  190,  196,  204,
-      240,  221,  227,  241,  258,  249,  264,  271,    0,  140,
-      273,  148,  274,  267, 1144,    0, 1144,  227,  221,   57,
-       63,  110,  119,  124,  134, 1144,  194,  212, 1144,  177,
-     1144,  156,  299,  316,  323,  330,  202,  336,  368,  344,
-      361,  392,  367,  398,  411,  419,    0,  163,  162,  118,
-
-      201,  174,  172,  157, 1144,    0,  429,  436,  442,  456,
-      197, 1144,  478,  480,  487,  502,  525,  508,  538,  546,
-      178, 1144, 1144,  215, 1144, 1144,   98,    0,  552,  560,
-     1144, 1144,  592,  566,  583,  601,  574,  620,  636,  643,
-     1144, 1144,  110,    0, 1144,  650,  686,  656,  663,  678,
-      686,  713,  731, 1144,  737,  102,    0,  743,  749,  755,
-      761,  767,  773,  791,  797, 1144,  803,  809,  815,  828,
-      834,  840, 1144,  846,  852, 1144,  858,  870, 1144,  877,
-      883,  889,  896,  919,  926,  933,  940,  946, 1144,  954,
-      961,  968,  982,  989, 1144, 1144, 1144,  996, 1003, 1009,
-
-     1017, 1144, 1024, 1034, 1144, 1144, 1077, 1084, 1091, 1098,
-     1105, 1112, 1119, 1123, 1128, 1130, 1132, 1134, 1136
+        0,    0,   63,   66,   69,    0,   67,   71,   52,   68,
+      288, 1784,   87,  281,  133,    0,   96, 1784,  129,  133,
+       84,  150, 1784,  234,  109,   69,   67,   72, 1784, 1784,
+      110,   71,   97, 1784, 1784, 1784,   97,  225,  179,    0,
+      209,  167,  220,  146,  194, 1784,  200,  206,  212,  218,
+      224,  227,  250,  256,  268,  275,  294,  305,  312,  318,
+      324,  337,    0,  331,  338,  356,  371,  374, 1784,    0,
+     1784,  220,  230,  123,  128,  145,  165,  171,  170, 1784,
+      168,  179, 1784,  205, 1784,  363,  400,  408,  422,  429,
+      438,  166,  445,  480,  451,  470,  477,  507,  528,  534,
+
+      540,  546,  552,  558,  566,  579,    0,  232,  222,  173,
+      242,  251,  257,  112, 1784,    0,  591,  604,  618,  611,
+      628,  153, 1784,  652,  648,  634,  678,  685,  697,  703,
+      715,  726,  735,  743,  752,  758,  265, 1784, 1784,  273,
+     1784, 1784,   96,    0,  768,  776,  796, 1784, 1784,  831,
+      805,  813,  821,  861,  876,  828,  882,  888,  894,  904,
+      915,  927, 1784, 1784,  103,    0,  933,  942,  948, 1784,
+      955,  995,  975,  987,  966, 1026,  993, 1784, 1040, 1049,
+     1055, 1784, 1064, 1070, 1077,   98,    0, 1784, 1784, 1087,
+     1096, 1109, 1128, 1135, 1142, 1148, 1154, 1160, 1167, 1174,
+
+     1180, 1186, 1784, 1206, 1218, 1225, 1231, 1238, 1244, 1250,
+     1258, 1264, 1784, 1270, 1291, 1276, 1297, 1303, 1784, 1313,
+     1324, 1330, 1340, 1784, 1346, 1352, 1363, 1373, 1389, 1401,
+     1784, 1411, 1418, 1426, 1433, 1439, 1450, 1458, 1465, 1784,
+     1476, 1482, 1498, 1504, 1519, 1525, 1531, 1541, 1547, 1784,
+     1784, 1557, 1564, 1784, 1784, 1571, 1580, 1589, 1596, 1603,
+     1610, 1617, 1626, 1635, 1784, 1784, 1647, 1784, 1654, 1663,
+     1672, 1784, 1679, 1687, 1693, 1784, 1784, 1745, 1750, 1755,
+     1760, 1765, 1770, 1775, 1778,  133,  132,   91,   88
     } ;
 
-static const flex_int16_t yy_def[220] =
+static const flex_int16_t yy_def[290] =
     {   0,
-      206,    1,  207,  207,    1,    5,    5,    5,    5,    5,
-      206,  206,  206,  206,  208,  209,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  210,
-      206,  206,  206,  211,  208,  206,  208,  208,  208,  208,
-      212,  208,  208,  208,  208,  208,  208,  208,  209,  206,
-      206,  206,  206,  206,  206,  213,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  210,  206,  211,
-      206,  214,  208,  208,  208,  208,  215,  208,  212,  208,
-      208,  208,  208,  208,  208,  208,  213,  206,  206,  206,
-
-      206,  206,  206,  206,  206,  216,  208,  208,  208,  208,
-      215,  206,  212,  208,  208,  208,  208,  208,  208,  208,
-      206,  206,  206,  206,  206,  206,  206,  217,  208,  208,
-      206,  206,  212,  208,  208,  208,  208,  208,  208,  208,
-      206,  206,  206,  218,  206,  208,  212,  208,  208,  208,
-      208,  208,  208,  206,  208,  206,  219,  208,  208,  208,
-      208,  208,  208,  208,  208,  206,  208,  208,  208,  208,
-      208,  208,  206,  208,  208,  206,  208,  208,  206,  208,
-      208,  208,  208,  208,  208,  208,  208,  208,  206,  208,
-      208,  208,  208,  208,  206,  206,  206,  208,  208,  208,
-
-      208,  206,  208,  208,  206,    0,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206
+      277,    1,  278,  278,    1,    5,    5,    5,    5,    5,
+      277,  277,  277,  277,  279,  280,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  281,
+      277,  277,  277,  282,  279,  277,  279,  279,  279,  279,
+      279,  283,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  280,  277,  277,  277,  277,  277,  277,  284,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  281,  277,  282,  277,  277,  279,  279,  279,  279,
+      279,  285,  279,  283,  279,  279,  279,  279,  279,  279,
+
+      279,  279,  279,  279,  279,  279,  284,  277,  277,  277,
+      277,  277,  277,  277,  277,  286,  279,  279,  279,  279,
+      279,  285,  277,  283,  279,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  279,  279,  277,  277,  277,  277,
+      277,  277,  277,  287,  279,  279,  279,  277,  277,  283,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  277,  277,  277,  288,  279,  279,  279,  277,
+      279,  283,  279,  279,  279,  279,  279,  277,  279,  279,
+      279,  277,  279,  279,  279,  277,  289,  277,  277,  279,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  279,
+
+      279,  279,  277,  279,  279,  279,  279,  279,  279,  279,
+      279,  279,  277,  279,  279,  279,  279,  279,  277,  279,
+      279,  279,  279,  277,  279,  279,  279,  279,  279,  279,
+      277,  279,  279,  279,  279,  279,  279,  279,  279,  277,
+      279,  279,  279,  279,  279,  279,  279,  279,  279,  277,
+      277,  279,  279,  277,  277,  279,  279,  279,  279,  279,
+      279,  279,  279,  279,  277,  277,  279,  277,  279,  279,
+      279,  277,  279,  279,  279,  277,    0,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277
     } ;
 
-static const flex_int16_t yy_nxt[1204] =
+static const flex_int16_t yy_nxt[1849] =
     {   0,
        12,   13,   14,   13,   12,   15,   16,   12,   17,   18,
-       19,   20,   21,   22,   23,   24,   12,   12,   12,   12,
-       12,   12,   25,   26,   12,   12,   27,   12,   12,   12,
-       12,   28,   12,   29,   12,   30,   12,   12,   12,   12,
-       12,   25,   31,   12,   12,   12,   12,   12,   32,   12,
-       12,   12,   12,   33,   12,   12,   12,   34,   35,   37,
-       14,   37,   37,   14,   37,   38,   41,   41,   38,   12,
-       12,   40,   12,   12,   12,   12,   12,   12,   12,   12,
-       40,   42,   98,   42,   65,   70,   12,   12,   99,   66,
-       12,   71,   64,   12,   12,   12,   60,   12,   61,   12,
-
-       60,   62,   63,   98,   70,   12,   12,   62,   39,   99,
-       12,   62,   12,   71,   72,   71,   60,   12,   63,   12,
-       62,   12,   12,   44,   44,   44,   62,   62,   46,   68,
-       62,   68,   70,   42,   69,   42,   72,   74,   72,   42,
-      123,   42,  100,  166,   98,   81,   62,   47,   48,   99,
-      156,   73,  143,   64,   49,   50,   68,   51,   68,  123,
-       75,   69,   62,   52,  100,  101,  100,   53,   47,   54,
-      102,   55,   56,   57,   82,   58,   49,   50,   44,   44,
-       44,   62,   81,   46,   44,   44,   44,  122,  103,   46,
-       44,   44,   44,  121,  123,   46,   44,   44,   44,  122,
-
-      141,   46,  112,  127,   44,   44,   44,  112,  122,   46,
-      106,   82,   51,  126,   83,  121,   85,  105,   51,  141,
-      125,   44,   44,   44,   51,   86,   46,   44,   44,   44,
-       51,  121,   46,  104,   69,   85,   83,  141,   51,   84,
-       69,   44,   44,   44,   86,   88,   46,   43,   79,   44,
-       44,   44,   45,  124,   46,   51,  142,   77,   44,   44,
-       44,   51,   90,   46,   44,   44,   44,   76,   67,   46,
-       43,   44,   44,   44,   45,   51,   46,   91,   45,  206,
-       64,  206,   45,   51,   60,   60,   61,   63,   45,   62,
-       92,   45,   51,   45,   89,   62,   62,   93,   51,   44,
-
-       44,   44,  206,   94,   46,   51,  206,  206,   62,  206,
-      206,  206,   96,   95,   62,   62,   44,   44,   44,  206,
-      206,   46,  206,   44,   44,   44,  107,  206,   46,  206,
-       44,   44,   44,   51,  206,   46,   44,   44,   44,  206,
-      206,   46,  206,  206,   44,   44,   44,  206,  107,   46,
-       51,  109,  206,  206,  206,  206,  206,   51,  110,  108,
-      206,   44,   44,   44,   51,  206,   46,   44,   44,   44,
-       51,  115,   46,  109,  206,  206,  206,  206,   51,  206,
-      110,  113,  114,  206,  206,  206,  113,  113,  113,  113,
-      113,  113,   44,   44,   44,   51,  206,   46,   44,   44,
-
-       44,   51,  206,   46,  206,  113,  113,  113,  113,  113,
-      113,   44,   44,   44,  206,  206,   46,  206,  117,   44,
-       44,   44,  206,  206,   46,  206,   51,  206,  206,   44,
-       44,   44,   51,  206,   46,  116,   44,   44,   44,  206,
-      206,   46,   44,   44,   44,   51,  206,  131,  206,  206,
-      206,  118,  206,   51,  206,  129,   44,   44,   44,  206,
-      206,  132,  119,   51,  206,  206,  206,  206,  206,  206,
-       51,  206,  206,  206,  120,  206,   51,  129,  206,  130,
-       44,   44,   44,  206,  206,   46,  206,   44,   44,   44,
-       51,  133,   46,  206,  206,  206,  133,  133,  133,  133,
-
-      133,  133,   44,   44,   44,  206,  206,   46,   44,   44,
-       44,  206,  206,   46,   51,  133,  133,  133,  133,  133,
-      133,   51,  206,  206,  135,   44,   44,   44,  206,  206,
-       46,  206,  206,  206,  134,  137,   51,  206,   44,   44,
-       44,  206,   51,   46,  206,  136,   44,   44,   44,  206,
-      206,   46,   44,   44,   44,  206,  206,  145,  138,   51,
-       44,   44,   44,  206,  206,   46,   44,   44,   44,  206,
-      206,   46,   51,  206,   44,   44,   44,  206,  206,   46,
-       51,  206,  206,   44,   44,   44,   51,  140,   46,  206,
-      206,  139,  206,  206,   51,  206,  206,  206,  206,  206,
-
-       51,   44,   44,   44,  146,  147,   46,  206,   51,  148,
-      147,  147,  147,  147,  147,  147,  151,   51,  206,  206,
-       44,   44,   44,  149,  152,   46,  206,  206,  206,  147,
-      147,  147,  147,  147,  147,   51,   44,   44,   44,  206,
-      206,  154,  150,   44,   44,   44,  206,  206,   46,  206,
-       44,   44,   44,  206,   51,   46,   44,   44,   44,  206,
-      206,   46,  206,   44,   44,   44,  206,  206,   46,  206,
-       51,  206,  206,  206,  153,  206,  206,   51,   44,   44,
-       44,  206,  206,   46,   51,  206,   44,   44,   44,  206,
-       51,   46,  206,  206,  155,  206,  206,   51,  158,   45,
-
-      206,  206,  159,  160,   45,   45,   45,   45,   45,   45,
-      206,  206,   51,   44,   44,   44,  206,  206,   46,  206,
-       51,  206,  206,   45,   45,   45,   45,   45,   45,  161,
-      206,   44,   44,   44,  206,  162,   46,   44,   44,   44,
-      206,  206,   46,   44,   44,   44,  206,   51,   46,   44,
-       44,   44,  206,  206,   46,   44,   44,   44,  206,  206,
-       46,   44,   44,   44,  163,   51,   46,   44,   44,   44,
-      206,   51,   46,   44,   44,   44,  206,   51,   46,  206,
-      206,  165,  206,   51,  164,  206,  167,  206,  206,   51,
-      168,   44,   44,   44,  206,   51,  173,   44,   44,   44,
-
-      206,   51,   46,   44,   44,   44,  169,   51,  176,   44,
-       44,   44,  206,  170,   46,   44,   44,   44,  171,  206,
-       46,  206,  172,  206,  206,   51,  206,  174,   44,   44,
-       44,   51,  206,  179,   44,   44,   44,   51,  206,   46,
-       44,   44,   44,   51,  206,   46,   44,   44,   44,   51,
-      175,   46,   44,   44,   44,  206,  178,   46,   44,   44,
-       44,  206,   51,   46,  177,  206,  206,  206,   51,  206,
-       44,   44,   44,  206,   51,   46,  206,   44,   44,   44,
-       51,  180,   46,   44,   44,   44,   51,  206,   46,   44,
-       44,   44,   51,  181,   46,  182,   44,   44,   44,  184,
-
-      206,  189,  206,  206,   51,  206,  206,  206,  183,  206,
-      206,   51,  206,  206,  186,  206,  206,   51,  206,   44,
-       44,   44,  185,   51,   46,  206,   44,   44,   44,  206,
-       51,   46,  187,   44,   44,   44,  206,  206,   46,  188,
-       44,   44,   44,  206,  206,   46,   44,   44,   44,  206,
-      206,   46,  206,   51,   44,   44,   44,  206,  206,  195,
-       51,   44,   44,   44,  206,  190,  196,   51,   44,   44,
-       44,  206,  206,  197,   51,  206,  206,  206,  191,  193,
-       51,  206,   44,   44,   44,  206,  192,   46,   51,   44,
-       44,   44,  206,  206,   46,   51,   44,   44,   44,  194,
-
-      206,   46,   51,   44,   44,   44,  206,  206,   46,   44,
-       44,   44,  206,  206,  202,  206,   51,   44,   44,   44,
-      206,  206,   46,   51,   44,   44,   44,  206,  206,   46,
-       51,  198,  206,  199,   44,   44,   44,   51,  206,  205,
-      206,  206,  200,   51,  206,  206,  206,  206,  206,  206,
-      206,   51,  201,  206,  206,  206,  206,  206,   51,  206,
-      206,  206,  206,  206,  206,  203,  206,  206,   51,  206,
-      206,  206,  206,  206,  206,  206,  204,   36,   36,   36,
-       36,   36,   36,   36,   45,   45,   45,   45,   45,   45,
-       45,   59,  206,   59,   59,   59,   59,   59,   78,  206,
-
-       78,  206,   78,   78,   78,   80,   80,   80,   80,   80,
-       80,   80,   87,   87,   87,   87,   87,   87,   87,   97,
-      206,   97,   97,   97,   97,   97,   80,   80,  206,   80,
-      111,  111,  111,  111,  111,  128,  128,  144,  144,  157,
-      157,   80,   80,   11,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-
-      206,  206,  206
+       19,   20,   21,   22,   22,   22,   23,   24,   12,   12,
+       12,   12,   12,   12,   25,   26,   12,   12,   27,   12,
+       12,   12,   12,   28,   12,   29,   12,   30,   12,   12,
+       12,   12,   12,   25,   31,   12,   12,   12,   12,   12,
+       12,   12,   32,   12,   12,   12,   12,   33,   12,   12,
+       12,   12,   34,   35,   37,   14,   37,   37,   14,   37,
+       38,   41,   40,   38,   12,   12,   40,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,   41,   42,   74,
+       42,   69,   84,   12,   12,  187,   70,   12,   42,   12,
+
+       42,   75,   12,   76,   12,   75,   12,   64,   74,   65,
+       65,   65,   12,   12,   12,   12,   39,   72,   12,   72,
+       66,   12,   73,   73,   73,   75,   12,   76,   76,   78,
+       74,   12,   12,   44,   44,   44,  166,  144,   46,   66,
+       64,  203,   67,   67,   67,  186,   68,   68,   68,   77,
+      108,   85,   79,   66,  165,  109,   47,   66,  123,   48,
+       49,   64,  143,   67,   67,   67,   50,   51,   42,   52,
+       42,  123,   66,  108,   66,   53,   66,   54,  109,  110,
+       55,   48,   86,   56,  115,   57,   58,   59,   60,   61,
+       62,   51,  108,   66,   44,   44,   44,  139,  109,   46,
+
+       44,   44,   44,  110,  110,   46,   44,   44,   44,  114,
+       85,   46,   44,   44,   44,  111,  139,   46,   44,   44,
+       44,  112,   43,   46,   44,   44,   44,   83,  113,   46,
+       52,   81,   93,   73,   73,   73,   52,   80,   88,   45,
+       90,   86,   52,   73,   73,   73,   87,   91,   52,  138,
+       44,   44,   44,   71,   52,   46,   44,   44,   44,   90,
+       52,   46,   88,   45,  137,   89,   91,   45,   44,   44,
+       44,   45,  138,   46,  137,   44,   44,   44,  138,   45,
+       46,  139,   45,   43,   45,   94,   52,  277,  137,  163,
+      277,  277,   52,   95,   44,   44,   44,  163,  140,   46,
+
+      142,  141,   96,  277,   52,   44,   44,   44,  163,   97,
+       46,   52,   44,   44,   44,  277,  164,   46,   44,   44,
+       44,  277,   98,   46,   44,   44,   44,  277,   99,   46,
+       52,  277,  277,  100,  277,  101,  277,   44,   44,   44,
+      277,   52,   46,  277,   68,   68,   68,  277,   52,   64,
+      277,   65,   65,   65,   52,   66,  277,  277,  277,   90,
+       52,  104,   66,  102,   72,  103,   72,  105,   84,   73,
+       73,   73,  277,   52,   66,   84,  277,  277,   90,  277,
+      277,   66,   64,  277,   67,   67,   67,   68,   68,   68,
+      277,  277,  277,  106,  277,   66,  277,  277,   66,   84,
+
+       44,   44,   44,   84,  277,   46,  277,   84,   44,   44,
+       44,  277,  277,   46,   66,   84,  277,   66,   84,  277,
+       84,  116,   44,   44,   44,  277,  277,   46,  277,   44,
+       44,   44,  277,  277,   46,  277,   52,  118,   44,   44,
+       44,  117,  277,   46,   52,   44,   44,   44,  277,  277,
+       46,   44,   44,   44,  277,  277,   46,  277,   52,  120,
+      277,  118,  277,  277,  277,   52,  277,  119,  121,  277,
+       44,   44,   44,  277,   52,   46,  277,   44,   44,   44,
+      277,   52,   46,  120,  277,  277,  277,   52,  277,  277,
+      277,  125,  121,  124,  124,  124,  277,  277,  277,  277,
+
+      124,  124,  124,  124,  124,  124,   52,   44,   44,   44,
+      277,  277,   46,   52,  277,  277,  277,  128,  277,  124,
+      124,  124,  124,  124,  124,  277,  126,  277,   44,   44,
+       44,  277,  127,   46,   44,   44,   44,  277,  277,   46,
+       44,   44,   44,   52,  277,   46,   44,   44,   44,  277,
+      277,   46,   44,   44,   44,  277,  277,   46,   44,   44,
+       44,  277,  277,   46,   52,  277,   44,   44,   44,  277,
+       52,   46,  277,  129,  277,  277,   52,  277,  277,   44,
+       44,   44,   52,  277,   46,  130,  277,  277,   52,  277,
+      277,   44,   44,   44,   52,  131,   46,  277,  277,  277,
+
+      277,  277,   52,  132,   44,   44,   44,  133,  277,   46,
+      277,   44,   44,   44,  277,   52,  148,  134,   44,   44,
+       44,  277,  277,   46,  277,  135,  136,   52,   44,   44,
+       44,  277,  146,  149,   44,   44,   44,  277,  277,   46,
+       52,  277,  277,  277,  152,  145,  277,   52,   44,   44,
+       44,  277,  277,   46,   52,  277,  146,  277,  277,  277,
+      277,  277,  277,  147,   52,  150,  150,  150,  277,  277,
+       52,  277,  150,  150,  150,  150,  150,  150,   44,   44,
+       44,  277,  277,   46,   52,   44,   44,   44,  277,  277,
+       46,  150,  150,  150,  150,  150,  150,   44,   44,   44,
+
+      277,  277,   46,   44,   44,   44,  151,  277,   46,  277,
+      277,  277,  277,  277,   52,   44,   44,   44,  277,  277,
+       46,   52,  277,  277,  154,  157,   44,   44,   44,  277,
+      277,   46,  277,   52,  277,   44,   44,   44,  153,   52,
+       46,  277,  155,   44,   44,   44,  156,  277,   46,  277,
+      277,   52,   44,   44,   44,  277,  277,   46,   44,   44,
+       44,  277,   52,   46,  277,  277,  277,  277,   44,   44,
+       44,   52,  277,   46,  277,  277,   44,   44,   44,   52,
+      158,  170,  167,  168,  277,  277,  160,  277,   52,  277,
+      277,  169,  159,  277,   52,  161,   44,   44,   44,  277,
+
+      277,   46,  277,  162,   52,   44,   44,   44,  277,  277,
+       46,  277,   52,   44,   44,   44,  277,  277,   46,  277,
+      277,   44,   44,   44,  277,  277,   46,  277,   44,   44,
+       44,  277,   52,  178,  277,  277,  277,  277,  277,  277,
+      277,   52,  277,  171,  172,  172,  172,  277,  277,   52,
+      173,  172,  172,  172,  172,  172,  172,   52,  277,  277,
+      175,   44,   44,   44,   52,  277,   46,  277,  277,  174,
+      172,  172,  172,  172,  172,  172,   44,   44,   44,  277,
+      277,   46,   44,   44,   44,  277,  277,   46,   44,   44,
+       44,  277,  277,   46,   44,   44,   44,   52,  277,  182,
+
+      277,  277,  277,  176,   44,   44,   44,  277,  277,   46,
+      277,  277,   52,  277,  277,   44,   44,   44,   52,  177,
+       46,  277,  277,  277,   52,  277,  179,   44,   44,   44,
+       52,  277,   46,   44,   44,   44,  180,  185,  188,  277,
+       52,  277,   44,   44,   44,  277,  181,  189,   44,   44,
+       44,   52,  277,   46,  277,   44,   44,   44,  277,  183,
+       46,  277,  277,   52,  277,  277,   44,   44,   44,   52,
+      184,   46,  277,  277,  277,   44,   44,   44,   52,  277,
+       46,  277,  277,  277,   52,  277,  277,   44,   44,   44,
+      190,   52,   46,   44,   44,   44,  277,  277,   46,  277,
+
+      277,  277,   52,  277,  277,  277,  277,  191,   45,   45,
+       45,   52,  277,  277,  277,   45,   45,   45,   45,   45,
+       45,  194,  277,   52,  277,  192,   44,   44,   44,   52,
+      193,   46,  277,  277,   45,   45,   45,   45,   45,   45,
+       44,   44,   44,  277,  277,   46,  277,  277,  196,   44,
+       44,   44,  277,  277,   46,   44,   44,   44,  277,  277,
+       46,  277,   52,  277,   44,   44,   44,  277,  195,   46,
+       44,   44,   44,  277,  277,   46,   52,   44,   44,   44,
+      277,  277,   46,  277,  277,   52,  277,   44,   44,   44,
+      277,   52,   46,  197,  277,  277,   44,   44,   44,  277,
+
+       52,   46,  277,  277,  198,  277,   52,  277,  277,   44,
+       44,   44,  199,   52,   46,  277,  277,  201,  277,  277,
+      200,  277,  277,   52,  277,  277,  202,  277,   44,   44,
+       44,  277,   52,   46,  277,   44,   44,   44,  277,  204,
+       46,  205,   44,   44,   44,   52,  277,   46,   44,   44,
+       44,  277,  206,   46,   44,   44,   44,  277,  277,   46,
+       44,   44,   44,  277,   52,   46,  277,   44,   44,   44,
+      277,   52,  213,  277,   44,   44,   44,  208,   52,   46,
+       44,   44,   44,  207,   52,   46,   44,   44,   44,  277,
+       52,   46,  277,  277,  277,  277,   52,  209,  277,  277,
+
+      277,  277,  277,   52,  210,  214,   44,   44,   44,  211,
+       52,   46,  277,  212,  277,  277,   52,  215,   44,   44,
+       44,  277,   52,  219,  277,   44,   44,   44,  277,  217,
+       46,   44,   44,   44,  277,  277,   46,  216,   44,   44,
+       44,  277,   52,   46,   44,   44,   44,  277,  222,   46,
+       44,   44,   44,  277,   52,  224,  277,  277,   44,   44,
+       44,   52,  218,   46,   44,   44,   44,   52,  277,   46,
+       44,   44,   44,  277,   52,   46,   44,   44,   44,  277,
+       52,   46,  277,  277,  220,  277,   52,  223,  277,  277,
+      221,   44,   44,   44,   52,  277,   46,   44,   44,   44,
+
+       52,  228,   46,   44,   44,   44,   52,  277,  231,  225,
+      277,  277,   52,   44,   44,   44,  277,  277,   46,  277,
+      277,  226,  277,  227,   44,   44,   44,   52,  277,   46,
+       44,   44,   44,   52,  277,   46,  277,  229,  277,   52,
+       44,   44,   44,  277,  277,   46,   44,   44,   44,   52,
+      277,   46,   44,   44,   44,  277,  232,   46,  230,  277,
+       52,  277,  277,   44,   44,   44,   52,  233,   46,  277,
+      277,  277,  234,   44,   44,   44,   52,  277,   46,  277,
+      277,  277,   52,  277,  277,  236,  277,  277,   52,   44,
+       44,   44,  277,  277,  240,  277,  235,  277,  277,   52,
+
+      277,   44,   44,   44,  277,  237,   46,  277,  277,   52,
+      277,   44,   44,   44,  277,  239,   46,  238,   44,   44,
+       44,  277,  277,   46,  277,   52,   44,   44,   44,  277,
+      277,   46,  277,   44,   44,   44,  277,   52,   46,   44,
+       44,   44,  277,  277,   46,  277,  277,   52,  277,  277,
+       44,   44,   44,  277,   52,   46,  277,  241,   44,   44,
+       44,  242,   52,   46,  277,   44,   44,   44,  244,   52,
+       46,  277,  277,  243,  277,   52,   44,   44,   44,  277,
+      277,  250,   44,   44,   44,  277,   52,  251,  277,  245,
+      277,  247,  277,  277,   52,  277,  246,  277,   44,   44,
+
+       44,   52,  277,   46,   44,   44,   44,  249,  252,   46,
+      277,  277,   52,  277,  277,  248,  277,  277,   52,   44,
+       44,   44,  277,  277,  254,   44,   44,   44,  277,  277,
+      255,   44,   44,   44,   52,  277,   46,  277,  277,  277,
+       52,   44,   44,   44,  277,  277,   46,   44,   44,   44,
+      277,  277,   46,  277,  277,   52,  253,   44,   44,   44,
+      277,   52,   46,  277,   44,   44,   44,   52,  277,   46,
+      277,   44,   44,   44,  277,  277,   46,   52,  277,  277,
+       44,   44,   44,   52,  256,   46,  277,  277,  257,   44,
+       44,   44,  277,   52,   46,  277,   44,   44,   44,  258,
+
+       52,   46,  277,   44,   44,   44,  277,   52,  265,  277,
+       44,   44,   44,  277,  259,  266,   52,   44,   44,   44,
+      260,  261,   46,  277,  277,   52,   44,   44,   44,  277,
+      277,  268,   52,  262,  277,   44,   44,   44,  277,   52,
+       46,  277,  277,  264,  277,  263,   52,   44,   44,   44,
+      277,  277,   46,   52,   44,   44,   44,  277,  277,   46,
+      277,  277,   52,   44,   44,   44,  277,  277,  272,  267,
+      277,   52,   44,   44,   44,  277,  277,   46,  277,   44,
+       44,   44,  277,   52,   46,  277,  269,   44,   44,   44,
+       52,  277,   46,   44,   44,   44,  277,  271,  276,   52,
+
+      277,  277,  277,  270,  277,  277,  277,  277,   52,  277,
+      277,  277,  277,  277,  277,   52,  277,  277,  277,  277,
+      277,  277,  277,   52,  277,  273,  277,  277,  277,   52,
+      277,  277,  277,  277,  277,  277,  277,  274,  277,  277,
+      277,  277,  277,  277,  275,   36,   36,   36,   36,   36,
+       45,   45,   45,   45,   45,   63,  277,   63,   63,   63,
+       82,  277,   82,  277,   82,   84,   84,   84,   84,   84,
+       92,   92,   92,   92,   92,  107,  277,  107,  107,  107,
+      122,  122,  122,   11,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277
     } ;
 
-static const flex_int16_t yy_chk[1204] =
+static const flex_int16_t yy_chk[1849] =
     {   0,
         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,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
-        3,    3,    4,    4,    4,    3,    9,   10,    4,    5,
-        5,    7,    5,    5,    5,    5,    5,    5,    5,    5,
-        8,   13,   70,   13,   21,   26,    5,    5,   71,   21,
-        5,   27,   20,    9,   10,    5,   17,    5,   17,    5,
-
-       19,   20,   19,   70,   26,    5,    5,   17,    5,   71,
-        7,   19,    5,   27,   28,   32,   22,    5,   22,    8,
-       20,    5,    5,   15,   15,   15,   17,   22,   15,   25,
-       19,   25,   31,   37,   25,   37,   28,   32,   33,   42,
-      100,   42,   72,  156,   73,   44,   22,   15,   15,   74,
-      143,   31,  127,   60,   15,   15,   62,   15,   62,  100,
-       33,   62,   60,   15,   72,   73,   75,   15,   15,   15,
-       74,   15,   15,   15,   44,   15,   15,   15,   45,   45,
-       45,   60,   80,   45,   47,   47,   47,   99,   75,   47,
-       48,   48,   48,   98,  103,   48,   49,   49,   49,  102,
-
-      121,   49,  111,  104,   50,   50,   50,   87,   99,   50,
-       82,   80,   45,  103,   47,   98,   49,   78,   47,  121,
-      102,   52,   52,   52,   48,   50,   52,   53,   53,   53,
-       49,  101,   53,   77,   69,   49,   47,  124,   50,   48,
-       68,   54,   54,   54,   50,   51,   54,   43,   41,   56,
-       56,   56,   51,  101,   56,   52,  124,   39,   55,   55,
-       55,   53,   52,   55,   57,   57,   57,   38,   24,   57,
-       14,   58,   58,   58,   51,   54,   58,   53,   51,   11,
-       64,    0,   51,   56,   61,   63,   61,   63,   51,   64,
-       54,   51,   55,   51,   51,   61,   63,   55,   57,   83,
-
-       83,   83,    0,   56,   83,   58,    0,    0,   64,    0,
-        0,    0,   58,   57,   61,   63,   84,   84,   84,    0,
-        0,   84,    0,   85,   85,   85,   83,    0,   85,    0,
-       86,   86,   86,   83,    0,   86,   88,   88,   88,    0,
-        0,   88,    0,    0,   90,   90,   90,    0,   83,   90,
-       84,   85,    0,    0,    0,    0,    0,   85,   86,   84,
-        0,   91,   91,   91,   86,    0,   91,   93,   93,   93,
-       88,   91,   93,   85,    0,    0,    0,    0,   90,    0,
-       86,   89,   90,    0,    0,    0,   89,   89,   89,   89,
-       89,   89,   92,   92,   92,   91,    0,   92,   94,   94,
-
-       94,   93,    0,   94,    0,   89,   89,   89,   89,   89,
-       89,   95,   95,   95,    0,    0,   95,    0,   93,   96,
-       96,   96,    0,    0,   96,    0,   92,    0,    0,  107,
-      107,  107,   94,    0,  107,   92,  108,  108,  108,    0,
-        0,  108,  109,  109,  109,   95,    0,  109,    0,    0,
-        0,   94,    0,   96,    0,  107,  110,  110,  110,    0,
-        0,  110,   95,  107,    0,    0,    0,    0,    0,    0,
-      108,    0,    0,    0,   96,    0,  109,  107,    0,  108,
-      114,  114,  114,    0,    0,  114,    0,  115,  115,  115,
-      110,  113,  115,    0,    0,    0,  113,  113,  113,  113,
-
-      113,  113,  116,  116,  116,    0,    0,  116,  118,  118,
-      118,    0,    0,  118,  114,  113,  113,  113,  113,  113,
-      113,  115,    0,    0,  115,  117,  117,  117,    0,    0,
-      117,    0,    0,    0,  114,  117,  116,    0,  119,  119,
-      119,    0,  118,  119,    0,  116,  120,  120,  120,    0,
-        0,  120,  129,  129,  129,    0,    0,  129,  118,  117,
-      130,  130,  130,    0,    0,  130,  134,  134,  134,    0,
-        0,  134,  119,    0,  137,  137,  137,    0,    0,  137,
-      120,    0,    0,  135,  135,  135,  129,  120,  135,    0,
-        0,  119,    0,    0,  130,    0,    0,    0,    0,    0,
-
-      134,  136,  136,  136,  130,  133,  136,    0,  137,  134,
-      133,  133,  133,  133,  133,  133,  137,  135,    0,    0,
-      138,  138,  138,  135,  137,  138,    0,    0,    0,  133,
-      133,  133,  133,  133,  133,  136,  139,  139,  139,    0,
-        0,  139,  136,  140,  140,  140,    0,    0,  140,    0,
-      146,  146,  146,    0,  138,  146,  148,  148,  148,    0,
-        0,  148,    0,  149,  149,  149,    0,    0,  149,    0,
-      139,    0,    0,    0,  138,    0,    0,  140,  150,  150,
-      150,    0,    0,  150,  146,    0,  151,  151,  151,    0,
-      148,  151,    0,    0,  140,    0,    0,  149,  146,  147,
-
-        0,    0,  148,  149,  147,  147,  147,  147,  147,  147,
-        0,    0,  150,  152,  152,  152,    0,    0,  152,    0,
-      151,    0,    0,  147,  147,  147,  147,  147,  147,  150,
-        0,  153,  153,  153,    0,  151,  153,  155,  155,  155,
-        0,    0,  155,  158,  158,  158,    0,  152,  158,  159,
-      159,  159,    0,    0,  159,  160,  160,  160,    0,    0,
-      160,  161,  161,  161,  152,  153,  161,  162,  162,  162,
-        0,  155,  162,  163,  163,  163,    0,  158,  163,    0,
-        0,  155,    0,  159,  153,    0,  158,    0,    0,  160,
-      159,  164,  164,  164,    0,  161,  164,  165,  165,  165,
-
-        0,  162,  165,  167,  167,  167,  160,  163,  167,  168,
-      168,  168,    0,  161,  168,  169,  169,  169,  162,    0,
-      169,    0,  163,    0,    0,  164,    0,  164,  170,  170,
-      170,  165,    0,  170,  171,  171,  171,  167,    0,  171,
-      172,  172,  172,  168,    0,  172,  174,  174,  174,  169,
-      165,  174,  175,  175,  175,    0,  169,  175,  177,  177,
-      177,    0,  170,  177,  168,    0,    0,    0,  171,    0,
-      178,  178,  178,    0,  172,  178,    0,  180,  180,  180,
-      174,  171,  180,  181,  181,  181,  175,    0,  181,  182,
-      182,  182,  177,  172,  182,  174,  183,  183,  183,  177,
-
-        0,  183,    0,    0,  178,    0,    0,    0,  175,    0,
-        0,  180,    0,    0,  180,    0,    0,  181,    0,  184,
-      184,  184,  178,  182,  184,    0,  185,  185,  185,    0,
-      183,  185,  181,  186,  186,  186,    0,    0,  186,  182,
-      187,  187,  187,    0,    0,  187,  188,  188,  188,    0,
-        0,  188,    0,  184,  190,  190,  190,    0,    0,  190,
-      185,  191,  191,  191,    0,  184,  191,  186,  192,  192,
-      192,    0,    0,  192,  187,    0,    0,    0,  185,  187,
-      188,    0,  193,  193,  193,    0,  186,  193,  190,  194,
-      194,  194,    0,    0,  194,  191,  198,  198,  198,  188,
-
-        0,  198,  192,  199,  199,  199,    0,    0,  199,  200,
-      200,  200,    0,    0,  200,    0,  193,  201,  201,  201,
-        0,    0,  201,  194,  203,  203,  203,    0,    0,  203,
-      198,  193,    0,  194,  204,  204,  204,  199,    0,  204,
-        0,    0,  198,  200,    0,    0,    0,    0,    0,    0,
-        0,  201,  199,    0,    0,    0,    0,    0,  203,    0,
-        0,    0,    0,    0,    0,  201,    0,    0,  204,    0,
-        0,    0,    0,    0,    0,    0,  203,  207,  207,  207,
-      207,  207,  207,  207,  208,  208,  208,  208,  208,  208,
-      208,  209,    0,  209,  209,  209,  209,  209,  210,    0,
-
-      210,    0,  210,  210,  210,  211,  211,  211,  211,  211,
-      211,  211,  212,  212,  212,  212,  212,  212,  212,  213,
-        0,  213,  213,  213,  213,  213,  214,  214,    0,  214,
-      215,  215,  215,  215,  215,  216,  216,  217,  217,  218,
-      218,  219,  219,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-      206,  206,  206,  206,  206,  206,  206,  206,  206,  206,
-
-      206,  206,  206
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    3,    3,    3,    4,    4,    4,
+        3,    9,    7,    4,    5,    5,    8,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,   10,   13,   26,
+       13,   21,  289,    5,    5,  288,   21,    5,   37,    9,
+
+       37,   27,    5,   28,    5,   32,    5,   17,   26,   17,
+       17,   17,    5,    5,    7,   10,    5,   25,    8,   25,
+       17,    5,   25,   25,   25,   27,    5,   28,   33,   32,
+       31,    5,    5,   15,   15,   15,  287,  286,   15,   17,
+       19,  186,   19,   19,   19,  165,   20,   20,   20,   31,
+       74,   44,   33,   19,  143,   75,   15,   20,  122,   15,
+       15,   22,  114,   22,   22,   22,   15,   15,   42,   15,
+       42,   92,   19,   74,   22,   15,   20,   15,   75,   76,
+       15,   15,   44,   15,   82,   15,   15,   15,   15,   15,
+       15,   15,   77,   22,   45,   45,   45,  110,   78,   45,
+
+       47,   47,   47,   76,   79,   47,   48,   48,   48,   81,
+       84,   48,   49,   49,   49,   77,  110,   49,   50,   50,
+       50,   78,   43,   50,   51,   51,   51,   41,   79,   51,
+       45,   39,   52,   72,   72,   72,   47,   38,   48,   52,
+       50,   84,   48,   73,   73,   73,   47,   51,   49,  109,
+       53,   53,   53,   24,   50,   53,   54,   54,   54,   50,
+       51,   54,   48,   52,  108,   49,   51,   52,   55,   55,
+       55,   52,  109,   55,  111,   56,   56,   56,  112,   52,
+       56,  113,   52,   14,   52,   52,   53,   11,  108,  137,
+        0,    0,   54,   53,   57,   57,   57,  140,  111,   57,
+
+      113,  112,   53,    0,   55,   58,   58,   58,  137,   54,
+       58,   56,   59,   59,   59,    0,  140,   59,   60,   60,
+       60,    0,   55,   60,   61,   61,   61,    0,   56,   61,
+       57,    0,    0,   57,    0,   57,    0,   62,   62,   62,
+        0,   58,   62,    0,   64,   64,   64,    0,   59,   65,
+        0,   65,   65,   65,   60,   64,    0,    0,    0,   62,
+       61,   60,   65,   58,   66,   59,   66,   61,   86,   66,
+       66,   66,    0,   62,   64,   86,    0,    0,   62,    0,
+        0,   65,   67,    0,   67,   67,   67,   68,   68,   68,
+        0,    0,    0,   62,    0,   67,    0,    0,   68,   86,
+
+       87,   87,   87,   86,    0,   87,    0,   86,   88,   88,
+       88,    0,    0,   88,   67,   86,    0,   68,   86,    0,
+       86,   86,   89,   89,   89,    0,    0,   89,    0,   90,
+       90,   90,    0,    0,   90,    0,   87,   88,   91,   91,
+       91,   87,    0,   91,   88,   93,   93,   93,    0,    0,
+       93,   95,   95,   95,    0,    0,   95,    0,   89,   90,
+        0,   88,    0,    0,    0,   90,    0,   89,   91,    0,
+       96,   96,   96,    0,   91,   96,    0,   97,   97,   97,
+        0,   93,   97,   90,    0,    0,    0,   95,    0,    0,
+        0,   95,   91,   94,   94,   94,    0,    0,    0,    0,
+
+       94,   94,   94,   94,   94,   94,   96,   98,   98,   98,
+        0,    0,   98,   97,    0,    0,    0,   98,    0,   94,
+       94,   94,   94,   94,   94,    0,   96,    0,   99,   99,
+       99,    0,   97,   99,  100,  100,  100,    0,    0,  100,
+      101,  101,  101,   98,    0,  101,  102,  102,  102,    0,
+        0,  102,  103,  103,  103,    0,    0,  103,  104,  104,
+      104,    0,    0,  104,   99,    0,  105,  105,  105,    0,
+      100,  105,    0,   99,    0,    0,  101,    0,    0,  106,
+      106,  106,  102,    0,  106,  100,    0,    0,  103,    0,
+        0,  117,  117,  117,  104,  101,  117,    0,    0,    0,
+
+        0,    0,  105,  102,  118,  118,  118,  103,    0,  118,
+        0,  120,  120,  120,    0,  106,  120,  104,  119,  119,
+      119,    0,    0,  119,    0,  105,  106,  117,  121,  121,
+      121,    0,  118,  121,  126,  126,  126,    0,    0,  126,
+      118,    0,    0,    0,  126,  117,    0,  120,  125,  125,
+      125,    0,    0,  125,  119,    0,  118,    0,    0,    0,
+        0,    0,    0,  119,  121,  124,  124,  124,    0,    0,
+      126,    0,  124,  124,  124,  124,  124,  124,  127,  127,
+      127,    0,    0,  127,  125,  128,  128,  128,    0,    0,
+      128,  124,  124,  124,  124,  124,  124,  129,  129,  129,
+
+        0,    0,  129,  130,  130,  130,  125,    0,  130,    0,
+        0,    0,    0,    0,  127,  131,  131,  131,    0,    0,
+      131,  128,    0,    0,  128,  131,  132,  132,  132,    0,
+        0,  132,    0,  129,    0,  133,  133,  133,  127,  130,
+      133,    0,  129,  134,  134,  134,  130,    0,  134,    0,
+        0,  131,  135,  135,  135,    0,    0,  135,  136,  136,
+      136,    0,  132,  136,    0,    0,    0,    0,  145,  145,
+      145,  133,    0,  145,    0,    0,  146,  146,  146,  134,
+      132,  146,  145,  145,    0,    0,  134,    0,  135,    0,
+        0,  145,  133,    0,  136,  135,  147,  147,  147,    0,
+
+        0,  147,    0,  136,  145,  151,  151,  151,    0,    0,
+      151,    0,  146,  152,  152,  152,    0,    0,  152,    0,
+        0,  153,  153,  153,    0,    0,  153,    0,  156,  156,
+      156,    0,  147,  156,    0,    0,    0,    0,    0,    0,
+        0,  151,    0,  147,  150,  150,  150,    0,    0,  152,
+      151,  150,  150,  150,  150,  150,  150,  153,    0,    0,
+      153,  154,  154,  154,  156,    0,  154,    0,    0,  152,
+      150,  150,  150,  150,  150,  150,  155,  155,  155,    0,
+        0,  155,  157,  157,  157,    0,    0,  157,  158,  158,
+      158,    0,    0,  158,  159,  159,  159,  154,    0,  159,
+
+        0,    0,    0,  154,  160,  160,  160,    0,    0,  160,
+        0,    0,  155,    0,    0,  161,  161,  161,  157,  155,
+      161,    0,    0,    0,  158,    0,  157,  162,  162,  162,
+      159,    0,  162,  167,  167,  167,  157,  162,  167,    0,
+      160,    0,  168,  168,  168,    0,  158,  168,  169,  169,
+      169,  161,    0,  169,    0,  171,  171,  171,    0,  160,
+      171,    0,    0,  162,    0,    0,  175,  175,  175,  167,
+      161,  175,    0,    0,    0,  173,  173,  173,  168,    0,
+      173,    0,    0,    0,  169,    0,    0,  174,  174,  174,
+      169,  171,  174,  177,  177,  177,    0,    0,  177,    0,
+
+        0,    0,  175,    0,    0,    0,    0,  171,  172,  172,
+      172,  173,    0,    0,    0,  172,  172,  172,  172,  172,
+      172,  175,    0,  174,    0,  173,  176,  176,  176,  177,
+      174,  176,    0,    0,  172,  172,  172,  172,  172,  172,
+      179,  179,  179,    0,    0,  179,    0,    0,  177,  180,
+      180,  180,    0,    0,  180,  181,  181,  181,    0,    0,
+      181,    0,  176,    0,  183,  183,  183,    0,  176,  183,
+      184,  184,  184,    0,    0,  184,  179,  185,  185,  185,
+        0,    0,  185,    0,    0,  180,    0,  190,  190,  190,
+        0,  181,  190,  179,    0,    0,  191,  191,  191,    0,
+
+      183,  191,    0,    0,  180,    0,  184,    0,    0,  192,
+      192,  192,  181,  185,  192,    0,    0,  184,    0,    0,
+      183,    0,    0,  190,    0,    0,  185,    0,  193,  193,
+      193,    0,  191,  193,    0,  194,  194,  194,    0,  190,
+      194,  191,  195,  195,  195,  192,    0,  195,  196,  196,
+      196,    0,  192,  196,  197,  197,  197,    0,    0,  197,
+      198,  198,  198,    0,  193,  198,    0,  199,  199,  199,
+        0,  194,  199,    0,  200,  200,  200,  194,  195,  200,
+      201,  201,  201,  193,  196,  201,  202,  202,  202,    0,
+      197,  202,    0,    0,    0,    0,  198,  195,    0,    0,
+
+        0,    0,    0,  199,  196,  199,  204,  204,  204,  197,
+      200,  204,    0,  198,    0,    0,  201,  200,  205,  205,
+      205,    0,  202,  205,    0,  206,  206,  206,    0,  202,
+      206,  207,  207,  207,    0,    0,  207,  201,  208,  208,
+      208,    0,  204,  208,  209,  209,  209,    0,  208,  209,
+      210,  210,  210,    0,  205,  210,    0,    0,  211,  211,
+      211,  206,  204,  211,  212,  212,  212,  207,    0,  212,
+      214,  214,  214,    0,  208,  214,  216,  216,  216,    0,
+      209,  216,    0,    0,  206,    0,  210,  209,    0,    0,
+      207,  215,  215,  215,  211,    0,  215,  217,  217,  217,
+
+      212,  215,  217,  218,  218,  218,  214,    0,  218,  211,
+        0,    0,  216,  220,  220,  220,    0,    0,  220,    0,
+        0,  212,    0,  214,  221,  221,  221,  215,    0,  221,
+      222,  222,  222,  217,    0,  222,    0,  216,    0,  218,
+      223,  223,  223,    0,    0,  223,  225,  225,  225,  220,
+        0,  225,  226,  226,  226,    0,  220,  226,  217,    0,
+      221,    0,    0,  227,  227,  227,  222,  221,  227,    0,
+        0,    0,  222,  228,  228,  228,  223,    0,  228,    0,
+        0,    0,  225,    0,    0,  225,    0,    0,  226,  229,
+      229,  229,    0,    0,  229,    0,  223,    0,    0,  227,
+
+        0,  230,  230,  230,    0,  226,  230,    0,    0,  228,
+        0,  232,  232,  232,    0,  228,  232,  227,  233,  233,
+      233,    0,    0,  233,    0,  229,  234,  234,  234,    0,
+        0,  234,    0,  235,  235,  235,    0,  230,  235,  236,
+      236,  236,    0,    0,  236,    0,    0,  232,    0,    0,
+      237,  237,  237,    0,  233,  237,    0,  230,  238,  238,
+      238,  232,  234,  238,    0,  239,  239,  239,  234,  235,
+      239,    0,    0,  233,    0,  236,  241,  241,  241,    0,
+        0,  241,  242,  242,  242,    0,  237,  242,    0,  235,
+        0,  237,    0,    0,  238,    0,  236,    0,  243,  243,
+
+      243,  239,    0,  243,  244,  244,  244,  239,  243,  244,
+        0,    0,  241,    0,    0,  238,    0,    0,  242,  245,
+      245,  245,    0,    0,  245,  246,  246,  246,    0,    0,
+      246,  247,  247,  247,  243,    0,  247,    0,    0,    0,
+      244,  248,  248,  248,    0,    0,  248,  249,  249,  249,
+        0,    0,  249,    0,    0,  245,  244,  252,  252,  252,
+        0,  246,  252,    0,  253,  253,  253,  247,    0,  253,
+        0,  256,  256,  256,    0,    0,  256,  248,    0,    0,
+      257,  257,  257,  249,  247,  257,    0,    0,  248,  258,
+      258,  258,    0,  252,  258,    0,  259,  259,  259,  249,
+
+      253,  259,    0,  260,  260,  260,    0,  256,  260,    0,
+      261,  261,  261,    0,  252,  261,  257,  262,  262,  262,
+      253,  256,  262,    0,    0,  258,  263,  263,  263,    0,
+        0,  263,  259,  257,    0,  264,  264,  264,    0,  260,
+      264,    0,    0,  259,    0,  258,  261,  267,  267,  267,
+        0,    0,  267,  262,  269,  269,  269,    0,    0,  269,
+        0,    0,  263,  270,  270,  270,    0,    0,  270,  262,
+        0,  264,  271,  271,  271,    0,    0,  271,    0,  273,
+      273,  273,    0,  267,  273,    0,  264,  274,  274,  274,
+      269,    0,  274,  275,  275,  275,    0,  269,  275,  270,
+
+        0,    0,    0,  267,    0,    0,    0,    0,  271,    0,
+        0,    0,    0,    0,    0,  273,    0,    0,    0,    0,
+        0,    0,    0,  274,    0,  271,    0,    0,    0,  275,
+        0,    0,    0,    0,    0,    0,    0,  273,    0,    0,
+        0,    0,    0,    0,  274,  278,  278,  278,  278,  278,
+      279,  279,  279,  279,  279,  280,    0,  280,  280,  280,
+      281,    0,  281,    0,  281,  282,  282,  282,  282,  282,
+      283,  283,  283,  283,  283,  284,    0,  284,  284,  284,
+      285,  285,  285,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277,  277,  277,
+      277,  277,  277,  277,  277,  277,  277,  277
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -938,13 +1100,13 @@ static char *yy_last_accepting_cpos;
 extern int d2_parser__flex_debug;
 int d2_parser__flex_debug = 1;
 
-static const flex_int16_t yy_rule_linenum[43] =
+static const flex_int16_t yy_rule_linenum[51] =
     {   0,
-      115,  117,  119,  124,  125,  130,  131,  132,  144,  147,
-      152,  158,  167,  176,  185,  194,  204,  214,  224,  233,
-      242,  251,  260,  269,  278,  376,  381,  386,  391,  392,
-      393,  394,  395,  396,  398,  416,  429,  434,  438,  440,
-      442,  444
+      117,  119,  121,  126,  127,  132,  133,  134,  146,  149,
+      154,  160,  169,  178,  187,  196,  205,  214,  224,  234,
+      244,  253,  262,  272,  281,  290,  299,  308,  317,  326,
+      335,  344,  354,  452,  457,  462,  467,  468,  469,  470,
+      471,  472,  474,  492,  505,  510,  514,  516,  518,  520
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -982,14 +1144,14 @@ namespace {
 
 bool start_token_flag = false;
 
-isc::dhcp::D2ParserContext::ParserType start_token_value;
+isc::d2::D2ParserContext::ParserType start_token_value;
 unsigned int comment_start_line = 0;
 
 };
 
 // To avoid the call to exit... oops!
-#define YY_FATAL_ERROR(msg) isc::dhcp::D2ParserContext::fatal(msg)
-#line 992 "d2_lexer.cc"
+#define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
+#line 1154 "d2_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
@@ -1015,8 +1177,8 @@ unsigned int comment_start_line = 0;
 // by moving it ahead by yyleng bytes. yyleng specifies the length of the
 // currently matched token.
 #define YY_USER_ACTION  driver.loc_.columns(yyleng);
-#line 1018 "d2_lexer.cc"
-#line 1019 "d2_lexer.cc"
+#line 1180 "d2_lexer.cc"
+#line 1181 "d2_lexer.cc"
 
 #define INITIAL 0
 #define COMMENT 1
@@ -1315,14 +1477,16 @@ YY_DECL
         switch (start_token_value) {
         case D2ParserContext::PARSER_JSON:
         default:
-            return isc::dhcp::D2Parser::make_TOPLEVEL_JSON(driver.loc_);
+            return isc::d2::D2Parser::make_TOPLEVEL_JSON(driver.loc_);
         case D2ParserContext::PARSER_DHCPDDNS:
-            return isc::dhcp::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
+            return isc::d2::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
+        case D2ParserContext::PARSER_SUB_DHCPDDNS:
+            return isc::d2::D2Parser::make_SUB_DHCPDDNS(driver.loc_);
         }
     }
 
 
-#line 1325 "d2_lexer.cc"
+#line 1489 "d2_lexer.cc"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -1351,13 +1515,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 >= 207 )
+                               if ( yy_current_state >= 278 )
                                        yy_c = yy_meta[yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
                        ++yy_cp;
                        }
-               while ( yy_current_state != 206 );
+               while ( yy_current_state != 277 );
                yy_cp = (yy_last_accepting_cpos);
                yy_current_state = (yy_last_accepting_state);
 
@@ -1376,13 +1540,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 < 43 )
+                       else if ( yy_act < 51 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], d2_parser_text );
-                       else if ( yy_act == 43 )
+                       else if ( yy_act == 51 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         d2_parser_text );
-                       else if ( yy_act == 44 )
+                       else if ( yy_act == 52 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1400,17 +1564,17 @@ do_action:      /* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 115 "d2_lexer.ll"
+#line 117 "d2_lexer.ll"
 ;
        YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 117 "d2_lexer.ll"
+#line 119 "d2_lexer.ll"
 ;
        YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 119 "d2_lexer.ll"
+#line 121 "d2_lexer.ll"
 {
   BEGIN(COMMENT);
   comment_start_line = driver.loc_.end.line;;
@@ -1418,33 +1582,33 @@ YY_RULE_SETUP
        YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 124 "d2_lexer.ll"
+#line 126 "d2_lexer.ll"
 BEGIN(INITIAL);
        YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 125 "d2_lexer.ll"
+#line 127 "d2_lexer.ll"
 ;
        YY_BREAK
 case YY_STATE_EOF(COMMENT):
-#line 126 "d2_lexer.ll"
+#line 128 "d2_lexer.ll"
 {
     isc_throw(D2ParseError, "Comment not closed. (/* in line " << comment_start_line);
 }
        YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 130 "d2_lexer.ll"
+#line 132 "d2_lexer.ll"
 BEGIN(DIR_ENTER);
        YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 131 "d2_lexer.ll"
+#line 133 "d2_lexer.ll"
 BEGIN(DIR_INCLUDE);
        YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 132 "d2_lexer.ll"
+#line 134 "d2_lexer.ll"
 {
     // Include directive.
 
@@ -1458,19 +1622,19 @@ YY_RULE_SETUP
 case YY_STATE_EOF(DIR_ENTER):
 case YY_STATE_EOF(DIR_INCLUDE):
 case YY_STATE_EOF(DIR_EXIT):
-#line 141 "d2_lexer.ll"
+#line 143 "d2_lexer.ll"
 {
     isc_throw(D2ParseError, "Directive not closed.");
 }
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 144 "d2_lexer.ll"
+#line 146 "d2_lexer.ll"
 BEGIN(INITIAL);
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 147 "d2_lexer.ll"
+#line 149 "d2_lexer.ll"
 {
     // Ok, we found a with space. Let's ignore it and update loc variable.
     driver.loc_.step();
@@ -1479,7 +1643,7 @@ YY_RULE_SETUP
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 152 "d2_lexer.ll"
+#line 154 "d2_lexer.ll"
 {
     // Newline found. Let's update the location and continue.
     driver.loc_.lines(yyleng);
@@ -1488,76 +1652,74 @@ YY_RULE_SETUP
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 158 "d2_lexer.ll"
+#line 160 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_IP_ADDRESS(driver.loc_);
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCPDDNS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ip-address", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("DhcpDdns", driver.loc_);
     }
 }
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 167 "d2_lexer.ll"
+#line 169 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_PORT(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_IP_ADDRESS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("port", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("ip-address", driver.loc_);
     }
 }
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 176 "d2_lexer.ll"
+#line 178 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_NCR_PROTOCOL(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_PORT(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ncr-protocol", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("port", driver.loc_);
     }
 }
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 185 "d2_lexer.ll"
+#line 187 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_NCR_FORMAT(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_DNS_SERVER_TIMEOUT(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ncr-format", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("dns-server-timeout", driver.loc_);
     }
 }
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 194 "d2_lexer.ll"
+#line 196 "d2_lexer.ll"
 {
-    /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_PROTOCOL) {
-        return isc::dhcp::D2Parser::make_UDP(driver.loc_);
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_NCR_PROTOCOL(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("ncr-protocol", driver.loc_);
     }
-    std::string tmp(yytext+1);
-    tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
 }
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 204 "d2_lexer.ll"
+#line 205 "d2_lexer.ll"
 {
-    /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_PROTOCOL) {
-        return isc::dhcp::D2Parser::make_TCP(driver.loc_);
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_NCR_FORMAT(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("ncr-format", driver.loc_);
     }
-    std::string tmp(yytext+1);
-    tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
 }
        YY_BREAK
 case 18:
@@ -1565,89 +1727,187 @@ YY_RULE_SETUP
 #line 214 "d2_lexer.ll"
 {
     /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_FORMAT) {
-        return isc::dhcp::D2Parser::make_JSON(driver.loc_);
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
+        return isc::d2::D2Parser::make_UDP(driver.loc_);
     }
     std::string tmp(yytext+1);
     tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
        YY_BREAK
 case 19:
 YY_RULE_SETUP
 #line 224 "d2_lexer.ll"
 {
-    switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::CONFIG:
-        return isc::dhcp::D2Parser::make_LOGGING(driver.loc_);
-    default:
-        return isc::dhcp::D2Parser::make_STRING("Logging", driver.loc_);
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
+        return isc::d2::D2Parser::make_TCP(driver.loc_);
     }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 233 "d2_lexer.ll"
+#line 234 "d2_lexer.ll"
 {
-    switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGING:
-        return isc::dhcp::D2Parser::make_LOGGERS(driver.loc_);
-    default:
-        return isc::dhcp::D2Parser::make_STRING("loggers", driver.loc_);
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_FORMAT) {
+        return isc::d2::D2Parser::make_JSON(driver.loc_);
     }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 242 "d2_lexer.ll"
+#line 244 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_OUTPUT_OPTIONS(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_FORWARD_DDNS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("output_options", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("forward-ddns", driver.loc_);
     }
 }
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 251 "d2_lexer.ll"
+#line 253 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::OUTPUT_OPTIONS:
-        return isc::dhcp::D2Parser::make_OUTPUT(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_REVERSE_DDNS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("output", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("reverse-ddns", driver.loc_);
     }
 }
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 260 "d2_lexer.ll"
+#line 262 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_DEBUGLEVEL(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_TSIG_KEYS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("debuglevel", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("tsig-keys", driver.loc_);
     }
 }
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 269 "d2_lexer.ll"
+#line 272 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_SEVERITY(driver.loc_);
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_LOGGING(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("severity", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("Logging", driver.loc_);
     }
 }
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 278 "d2_lexer.ll"
+#line 281 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGING:
+        return isc::d2::D2Parser::make_LOGGERS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("loggers", driver.loc_);
+    }
+}
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 290 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_OUTPUT_OPTIONS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("output_options", driver.loc_);
+    }
+}
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 299 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
+        return isc::d2::D2Parser::make_OUTPUT(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("output", driver.loc_);
+    }
+}
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 308 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_NAME(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("name", driver.loc_);
+    }
+}
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 317 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_DEBUGLEVEL(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("debuglevel", driver.loc_);
+    }
+}
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 326 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_SEVERITY(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("severity", driver.loc_);
+    }
+}
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 335 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCP4(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("Dhcp4", driver.loc_);
+    }
+}
+       YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 344 "d2_lexer.ll"
+{
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCP6(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("Dhcp6", driver.loc_);
+    }
+}
+       YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 354 "d2_lexer.ll"
 {
     // A string has been matched. It contains the actual string and single quotes.
     // We need to get those quotes out of the way and just use its content, e.g.
@@ -1743,68 +2003,68 @@ YY_RULE_SETUP
         }
     }
 
-    return isc::dhcp::D2Parser::make_STRING(decoded, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(decoded, driver.loc_);
 }
        YY_BREAK
-case 26:
-/* rule 26 can match eol */
+case 34:
+/* rule 34 can match eol */
 YY_RULE_SETUP
-#line 376 "d2_lexer.ll"
+#line 452 "d2_lexer.ll"
 {
     // Bad string with a forbidden control character inside
     driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
 }
        YY_BREAK
-case 27:
-/* rule 27 can match eol */
+case 35:
+/* rule 35 can match eol */
 YY_RULE_SETUP
-#line 381 "d2_lexer.ll"
+#line 457 "d2_lexer.ll"
 {
     // Bad string with a bad escape inside
     driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
 }
        YY_BREAK
-case 28:
+case 36:
 YY_RULE_SETUP
-#line 386 "d2_lexer.ll"
+#line 462 "d2_lexer.ll"
 {
     // Bad string with an open escape at the end
     driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
 }
        YY_BREAK
-case 29:
+case 37:
 YY_RULE_SETUP
-#line 391 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_LSQUARE_BRACKET(driver.loc_); }
+#line 467 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_LSQUARE_BRACKET(driver.loc_); }
        YY_BREAK
-case 30:
+case 38:
 YY_RULE_SETUP
-#line 392 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_RSQUARE_BRACKET(driver.loc_); }
+#line 468 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_RSQUARE_BRACKET(driver.loc_); }
        YY_BREAK
-case 31:
+case 39:
 YY_RULE_SETUP
-#line 393 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_LCURLY_BRACKET(driver.loc_); }
+#line 469 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_LCURLY_BRACKET(driver.loc_); }
        YY_BREAK
-case 32:
+case 40:
 YY_RULE_SETUP
-#line 394 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_RCURLY_BRACKET(driver.loc_); }
+#line 470 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_RCURLY_BRACKET(driver.loc_); }
        YY_BREAK
-case 33:
+case 41:
 YY_RULE_SETUP
-#line 395 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_COMMA(driver.loc_); }
+#line 471 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_COMMA(driver.loc_); }
        YY_BREAK
-case 34:
+case 42:
 YY_RULE_SETUP
-#line 396 "d2_lexer.ll"
-{ return isc::dhcp::D2Parser::make_COLON(driver.loc_); }
+#line 472 "d2_lexer.ll"
+{ return isc::d2::D2Parser::make_COLON(driver.loc_); }
        YY_BREAK
-case 35:
+case 43:
 YY_RULE_SETUP
-#line 398 "d2_lexer.ll"
+#line 474 "d2_lexer.ll"
 {
     // An integer was found.
     std::string tmp(yytext);
@@ -1820,12 +2080,12 @@ YY_RULE_SETUP
     }
 
     // The parser needs the string form as double conversion is no lossless
-    return isc::dhcp::D2Parser::make_INTEGER(integer, driver.loc_);
+    return isc::d2::D2Parser::make_INTEGER(integer, driver.loc_);
 }
        YY_BREAK
-case 36:
+case 44:
 YY_RULE_SETUP
-#line 416 "d2_lexer.ll"
+#line 492 "d2_lexer.ll"
 {
     // A floating point was found.
     std::string tmp(yytext);
@@ -1836,49 +2096,49 @@ YY_RULE_SETUP
         driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
     }
 
-    return isc::dhcp::D2Parser::make_FLOAT(fp, driver.loc_);
+    return isc::d2::D2Parser::make_FLOAT(fp, driver.loc_);
 }
        YY_BREAK
-case 37:
+case 45:
 YY_RULE_SETUP
-#line 429 "d2_lexer.ll"
+#line 505 "d2_lexer.ll"
 {
     string tmp(yytext);
-    return isc::dhcp::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
+    return isc::d2::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
 }
        YY_BREAK
-case 38:
+case 46:
 YY_RULE_SETUP
-#line 434 "d2_lexer.ll"
+#line 510 "d2_lexer.ll"
 {
-   return isc::dhcp::D2Parser::make_NULL_TYPE(driver.loc_);
+   return isc::d2::D2Parser::make_NULL_TYPE(driver.loc_);
 }
        YY_BREAK
-case 39:
+case 47:
 YY_RULE_SETUP
-#line 438 "d2_lexer.ll"
+#line 514 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON true reserved keyword is lower case only");
        YY_BREAK
-case 40:
+case 48:
 YY_RULE_SETUP
-#line 440 "d2_lexer.ll"
+#line 516 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON false reserved keyword is lower case only");
        YY_BREAK
-case 41:
+case 49:
 YY_RULE_SETUP
-#line 442 "d2_lexer.ll"
+#line 518 "d2_lexer.ll"
 driver.error (driver.loc_, "JSON null reserved keyword is lower case only");
        YY_BREAK
-case 42:
+case 50:
 YY_RULE_SETUP
-#line 444 "d2_lexer.ll"
+#line 520 "d2_lexer.ll"
 driver.error (driver.loc_, "Invalid character: " + std::string(yytext));
        YY_BREAK
 case YY_STATE_EOF(INITIAL):
-#line 446 "d2_lexer.ll"
+#line 522 "d2_lexer.ll"
 {
     if (driver.states_.empty()) {
-        return isc::dhcp::D2Parser::make_END(driver.loc_);
+        return isc::d2::D2Parser::make_END(driver.loc_);
     }
     driver.loc_ = driver.locs_.back();
     driver.locs_.pop_back();
@@ -1899,12 +2159,12 @@ case YY_STATE_EOF(INITIAL):
     BEGIN(DIR_EXIT);
 }
        YY_BREAK
-case 43:
+case 51:
 YY_RULE_SETUP
-#line 469 "d2_lexer.ll"
+#line 545 "d2_lexer.ll"
 ECHO;
        YY_BREAK
-#line 1907 "d2_lexer.cc"
+#line 2167 "d2_lexer.cc"
 
        case YY_END_OF_BUFFER:
                {
@@ -2219,7 +2479,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 >= 207 )
+                       if ( yy_current_state >= 278 )
                                yy_c = yy_meta[yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -2252,11 +2512,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 >= 207 )
+               if ( yy_current_state >= 278 )
                        yy_c = yy_meta[yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-       yy_is_jam = (yy_current_state == 206);
+       yy_is_jam = (yy_current_state == 277);
 
                return yy_is_jam ? 0 : yy_current_state;
 }
@@ -3005,7 +3265,7 @@ void d2_parser_free (void * ptr )
 
 /* %ok-for-header */
 
-#line 469 "d2_lexer.ll"
+#line 545 "d2_lexer.ll"
 
 
 using namespace isc::dhcp;
index feccf57f5b845486bb1b7abb79a4a0b591ac3cb1..b15e27667d4c6d8fe95c565970b0a6abfdaacc3a 100644 (file)
@@ -25,13 +25,13 @@ namespace {
 
 bool start_token_flag = false;
 
-isc::dhcp::D2ParserContext::ParserType start_token_value;
+isc::d2::D2ParserContext::ParserType start_token_value;
 unsigned int comment_start_line = 0;
 
 };
 
 // To avoid the call to exit... oops!
-#define YY_FATAL_ERROR(msg) isc::dhcp::D2ParserContext::fatal(msg)
+#define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
 %}
 
 /* noyywrap disables automatic rewinding for the next file to parse. Since we
@@ -104,9 +104,11 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
         switch (start_token_value) {
         case D2ParserContext::PARSER_JSON:
         default:
-            return isc::dhcp::D2Parser::make_TOPLEVEL_JSON(driver.loc_);
+            return isc::d2::D2Parser::make_TOPLEVEL_JSON(driver.loc_);
         case D2ParserContext::PARSER_DHCPDDNS:
-            return isc::dhcp::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
+            return isc::d2::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
+        case D2ParserContext::PARSER_SUB_DHCPDDNS:
+            return isc::d2::D2Parser::make_SUB_DHCPDDNS(driver.loc_);
         }
     }
 %}
@@ -154,126 +156,200 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     driver.loc_.step();
 }
 
+\"DhcpDdns\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCPDDNS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("DhcpDdns", driver.loc_);
+    }
+}
+
 \"ip-address\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_IP_ADDRESS(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_IP_ADDRESS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ip-address", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("ip-address", driver.loc_);
     }
 }
 
 \"port\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_PORT(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_PORT(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("port", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("port", driver.loc_);
+    }
+}
+
+\"dns-server-timeout\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_DNS_SERVER_TIMEOUT(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("dns-server-timeout", driver.loc_);
     }
 }
 
 \"ncr-protocol\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_NCR_PROTOCOL(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_NCR_PROTOCOL(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ncr-protocol", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("ncr-protocol", driver.loc_);
     }
 }
 
 \"ncr-format\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::DHCPDDNS:
-        return isc::dhcp::D2Parser::make_NCR_FORMAT(driver.loc_);
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_NCR_FORMAT(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("ncr-format", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("ncr-format", driver.loc_);
     }
 }
 
 (?i:\"UDP\") {
     /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_PROTOCOL) {
-        return isc::dhcp::D2Parser::make_UDP(driver.loc_);
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
+        return isc::d2::D2Parser::make_UDP(driver.loc_);
     }
     std::string tmp(yytext+1);
     tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
 
 (?i:\"TCP\") {
     /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_PROTOCOL) {
-        return isc::dhcp::D2Parser::make_TCP(driver.loc_);
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_PROTOCOL) {
+        return isc::d2::D2Parser::make_TCP(driver.loc_);
     }
     std::string tmp(yytext+1);
     tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
 }
 
 (?i:\"JSON\") {
     /* dhcp-ddns value keywords are case insensitive */
-    if (driver.ctx_ == isc::dhcp::D2ParserContext::NCR_FORMAT) {
-        return isc::dhcp::D2Parser::make_JSON(driver.loc_);
+    if (driver.ctx_ == isc::d2::D2ParserContext::NCR_FORMAT) {
+        return isc::d2::D2Parser::make_JSON(driver.loc_);
     }
     std::string tmp(yytext+1);
     tmp.resize(tmp.size() - 1);
-    return isc::dhcp::D2Parser::make_STRING(tmp, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(tmp, driver.loc_);
+}
+
+\"forward-ddns\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_FORWARD_DDNS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("forward-ddns", driver.loc_);
+    }
+}
+
+\"reverse-ddns\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_REVERSE_DDNS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("reverse-ddns", driver.loc_);
+    }
+}
+
+\"tsig-keys\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::DHCPDDNS:
+        return isc::d2::D2Parser::make_TSIG_KEYS(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("tsig-keys", driver.loc_);
+    }
 }
 
+
 \"Logging\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::CONFIG:
-        return isc::dhcp::D2Parser::make_LOGGING(driver.loc_);
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_LOGGING(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("Logging", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("Logging", driver.loc_);
     }
 }
 
 \"loggers\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGING:
-        return isc::dhcp::D2Parser::make_LOGGERS(driver.loc_);
+    case isc::d2::D2ParserContext::LOGGING:
+        return isc::d2::D2Parser::make_LOGGERS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("loggers", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("loggers", driver.loc_);
     }
 }
 
 \"output_options\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_OUTPUT_OPTIONS(driver.loc_);
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_OUTPUT_OPTIONS(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("output_options", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("output_options", driver.loc_);
     }
 }
 
 \"output\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::OUTPUT_OPTIONS:
-        return isc::dhcp::D2Parser::make_OUTPUT(driver.loc_);
+    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
+        return isc::d2::D2Parser::make_OUTPUT(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("output", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("output", driver.loc_);
+    }
+}
+
+\"name\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_NAME(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("name", driver.loc_);
     }
 }
 
 \"debuglevel\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_DEBUGLEVEL(driver.loc_);
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_DEBUGLEVEL(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("debuglevel", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("debuglevel", driver.loc_);
     }
 }
 
 \"severity\" {
     switch(driver.ctx_) {
-    case isc::dhcp::D2ParserContext::LOGGERS:
-        return isc::dhcp::D2Parser::make_SEVERITY(driver.loc_);
+    case isc::d2::D2ParserContext::LOGGERS:
+        return isc::d2::D2Parser::make_SEVERITY(driver.loc_);
     default:
-        return isc::dhcp::D2Parser::make_STRING("severity", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("severity", driver.loc_);
     }
 }
 
+\"Dhcp4\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCP4(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("Dhcp4", driver.loc_);
+    }
+}
+
+\"Dhcp6\" {
+    switch(driver.ctx_) {
+    case isc::d2::D2ParserContext::CONFIG:
+        return isc::d2::D2Parser::make_DHCP6(driver.loc_);
+    default:
+        return isc::d2::D2Parser::make_STRING("Dhcp6", driver.loc_);
+    }
+}
+
+
 {JSONString} {
     // A string has been matched. It contains the actual string and single quotes.
     // We need to get those quotes out of the way and just use its content, e.g.
@@ -369,7 +445,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
         }
     }
 
-    return isc::dhcp::D2Parser::make_STRING(decoded, driver.loc_);
+    return isc::d2::D2Parser::make_STRING(decoded, driver.loc_);
 }
 
 \"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
@@ -387,12 +463,12 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
 }
 
-"["    { return isc::dhcp::D2Parser::make_LSQUARE_BRACKET(driver.loc_); }
-"]"    { return isc::dhcp::D2Parser::make_RSQUARE_BRACKET(driver.loc_); }
-"{"    { return isc::dhcp::D2Parser::make_LCURLY_BRACKET(driver.loc_); }
-"}"    { return isc::dhcp::D2Parser::make_RCURLY_BRACKET(driver.loc_); }
-","    { return isc::dhcp::D2Parser::make_COMMA(driver.loc_); }
-":"    { return isc::dhcp::D2Parser::make_COLON(driver.loc_); }
+"["    { return isc::d2::D2Parser::make_LSQUARE_BRACKET(driver.loc_); }
+"]"    { return isc::d2::D2Parser::make_RSQUARE_BRACKET(driver.loc_); }
+"{"    { return isc::d2::D2Parser::make_LCURLY_BRACKET(driver.loc_); }
+"}"    { return isc::d2::D2Parser::make_RCURLY_BRACKET(driver.loc_); }
+","    { return isc::d2::D2Parser::make_COMMA(driver.loc_); }
+":"    { return isc::d2::D2Parser::make_COLON(driver.loc_); }
 
 {int} {
     // An integer was found.
@@ -409,7 +485,7 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 
     // The parser needs the string form as double conversion is no lossless
-    return isc::dhcp::D2Parser::make_INTEGER(integer, driver.loc_);
+    return isc::d2::D2Parser::make_INTEGER(integer, driver.loc_);
 }
 
 [-+]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)? {
@@ -422,16 +498,16 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
         driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
     }
 
-    return isc::dhcp::D2Parser::make_FLOAT(fp, driver.loc_);
+    return isc::d2::D2Parser::make_FLOAT(fp, driver.loc_);
 }
 
 true|false {
     string tmp(yytext);
-    return isc::dhcp::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
+    return isc::d2::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
 }
 
 null {
-   return isc::dhcp::D2Parser::make_NULL_TYPE(driver.loc_);
+   return isc::d2::D2Parser::make_NULL_TYPE(driver.loc_);
 }
 
 (?i:true) driver.error (driver.loc_, "JSON true reserved keyword is lower case only");
@@ -444,7 +520,7 @@ null {
 
 <<EOF>> {
     if (driver.states_.empty()) {
-        return isc::dhcp::D2Parser::make_END(driver.loc_);
+        return isc::d2::D2Parser::make_END(driver.loc_);
     }
     driver.loc_ = driver.locs_.back();
     driver.locs_.pop_back();
index a711f41e5abb814099f599a8eae21c8f47448b41..4352b6ba991814b1035fa56d2f4b57599b11406a 100644 (file)
 #define YYRECOVERING()  (!!yyerrstatus_)
 
 #line 14 "d2_parser.yy" // lalr1.cc:479
-namespace isc { namespace dhcp {
+namespace isc { namespace d2 {
 #line 145 "d2_parser.cc" // lalr1.cc:479
 
   /* Return YYSTR after stripping away unnecessary quotes and
@@ -182,7 +182,7 @@ namespace isc { namespace dhcp {
 
 
   /// Build a parser object.
-  D2Parser::D2Parser (isc::dhcp::D2ParserContext& ctx_yyarg)
+  D2Parser::D2Parser (isc::d2::D2ParserContext& ctx_yyarg)
     :
 #if D2_PARSER_DEBUG
       yydebug_ (false),
@@ -253,24 +253,24 @@ namespace isc { namespace dhcp {
   {
       switch (that.type_get ())
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.move< ElementPtr > (that.value);
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.move< bool > (that.value);
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.move< double > (that.value);
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.move< int64_t > (that.value);
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.move< std::string > (that.value);
         break;
 
@@ -289,24 +289,24 @@ namespace isc { namespace dhcp {
     state = that.state;
       switch (that.type_get ())
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.copy< ElementPtr > (that.value);
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.copy< bool > (that.value);
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.copy< double > (that.value);
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.copy< int64_t > (that.value);
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.copy< std::string > (that.value);
         break;
 
@@ -346,44 +346,44 @@ namespace isc { namespace dhcp {
         << yysym.location << ": ";
     switch (yytype)
     {
-            case 31: // "constant string"
+            case 34: // "constant string"
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< std::string > (); }
 #line 354 "d2_parser.cc" // lalr1.cc:636
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< int64_t > (); }
 #line 361 "d2_parser.cc" // lalr1.cc:636
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< double > (); }
 #line 368 "d2_parser.cc" // lalr1.cc:636
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< bool > (); }
 #line 375 "d2_parser.cc" // lalr1.cc:636
         break;
 
-      case 40: // value
+      case 43: // value
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< ElementPtr > (); }
 #line 382 "d2_parser.cc" // lalr1.cc:636
         break;
 
-      case 67: // ncr_protocol_value
+      case 70: // ncr_protocol_value
 
-#line 88 "d2_parser.yy" // lalr1.cc:636
+#line 91 "d2_parser.yy" // lalr1.cc:636
         { yyoutput << yysym.value.template as< ElementPtr > (); }
 #line 389 "d2_parser.cc" // lalr1.cc:636
         break;
@@ -585,24 +585,24 @@ namespace isc { namespace dhcp {
          when using variants.  */
         switch (yyr1_[yyn])
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         yylhs.value.build< ElementPtr > ();
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         yylhs.value.build< bool > ();
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         yylhs.value.build< double > ();
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         yylhs.value.build< int64_t > ();
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         yylhs.value.build< std::string > ();
         break;
 
@@ -624,67 +624,67 @@ namespace isc { namespace dhcp {
           switch (yyn)
             {
   case 2:
-#line 97 "d2_parser.yy" // lalr1.cc:859
+#line 100 "d2_parser.yy" // lalr1.cc:859
     { ctx.ctx_ = ctx.NO_KEYWORD; }
 #line 630 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 4:
-#line 98 "d2_parser.yy" // lalr1.cc:859
+#line 101 "d2_parser.yy" // lalr1.cc:859
     { ctx.ctx_ = ctx.CONFIG; }
 #line 636 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 6:
-#line 99 "d2_parser.yy" // lalr1.cc:859
+#line 102 "d2_parser.yy" // lalr1.cc:859
     { ctx.ctx_ = ctx.DHCPDDNS; }
 #line 642 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 8:
-#line 107 "d2_parser.yy" // lalr1.cc:859
+#line 110 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location))); }
 #line 648 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 9:
-#line 108 "d2_parser.yy" // lalr1.cc:859
+#line 111 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as< double > (), ctx.loc2pos(yystack_[0].location))); }
 #line 654 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 10:
-#line 109 "d2_parser.yy" // lalr1.cc:859
+#line 112 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as< bool > (), ctx.loc2pos(yystack_[0].location))); }
 #line 660 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 11:
-#line 110 "d2_parser.yy" // lalr1.cc:859
+#line 113 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location))); }
 #line 666 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 12:
-#line 111 "d2_parser.yy" // lalr1.cc:859
+#line 114 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new NullElement(ctx.loc2pos(yystack_[0].location))); }
 #line 672 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 13:
-#line 112 "d2_parser.yy" // lalr1.cc:859
+#line 115 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); }
 #line 678 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 14:
-#line 113 "d2_parser.yy" // lalr1.cc:859
+#line 116 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); }
 #line 684 "d2_parser.cc" // lalr1.cc:859
     break;
 
   case 15:
-#line 116 "d2_parser.yy" // lalr1.cc:859
+#line 119 "d2_parser.yy" // lalr1.cc:859
     {
     // Push back the JSON value on the stack
     ctx.stack_.push_back(yystack_[0].value.as< ElementPtr > ());
@@ -693,7 +693,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 16:
-#line 121 "d2_parser.yy" // lalr1.cc:859
+#line 124 "d2_parser.yy" // lalr1.cc:859
     {
     // This code is executed when we're about to start parsing
     // the content of the map
@@ -704,7 +704,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 17:
-#line 126 "d2_parser.yy" // lalr1.cc:859
+#line 129 "d2_parser.yy" // lalr1.cc:859
     {
     // map parsing completed. If we ever want to do any wrap up
     // (maybe some sanity checking), this would be the best place
@@ -714,7 +714,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 20:
-#line 137 "d2_parser.yy" // lalr1.cc:859
+#line 140 "d2_parser.yy" // lalr1.cc:859
     {
                   // map containing a single entry
                   ctx.stack_.back()->set(yystack_[2].value.as< std::string > (), yystack_[0].value.as< ElementPtr > ());
@@ -723,7 +723,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 21:
-#line 141 "d2_parser.yy" // lalr1.cc:859
+#line 144 "d2_parser.yy" // lalr1.cc:859
     {
                   // map consisting of a shorter map followed by
                   // comma and string:value
@@ -733,7 +733,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 22:
-#line 148 "d2_parser.yy" // lalr1.cc:859
+#line 151 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.push_back(l);
@@ -742,7 +742,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 23:
-#line 151 "d2_parser.yy" // lalr1.cc:859
+#line 154 "d2_parser.yy" // lalr1.cc:859
     {
     // list parsing complete. Put any sanity checking here
 }
@@ -750,7 +750,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 26:
-#line 167 "d2_parser.yy" // lalr1.cc:859
+#line 170 "d2_parser.yy" // lalr1.cc:859
     {
                   // List consisting of a single element.
                   ctx.stack_.back()->add(yystack_[0].value.as< ElementPtr > ());
@@ -759,7 +759,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 27:
-#line 171 "d2_parser.yy" // lalr1.cc:859
+#line 174 "d2_parser.yy" // lalr1.cc:859
     {
                   // List ending with , and a value.
                   ctx.stack_.back()->add(yystack_[0].value.as< ElementPtr > ());
@@ -768,7 +768,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 28:
-#line 182 "d2_parser.yy" // lalr1.cc:859
+#line 185 "d2_parser.yy" // lalr1.cc:859
     {
     const std::string& where = ctx.contextName();
     const std::string& keyword = yystack_[1].value.as< std::string > ();
@@ -779,7 +779,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 29:
-#line 192 "d2_parser.yy" // lalr1.cc:859
+#line 195 "d2_parser.yy" // lalr1.cc:859
     {
     // This code is executed when we're about to start parsing
     // the content of the map
@@ -790,7 +790,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 30:
-#line 197 "d2_parser.yy" // lalr1.cc:859
+#line 200 "d2_parser.yy" // lalr1.cc:859
     {
     // map parsing completed. If we ever want to do any wrap up
     // (maybe some sanity checking), this would be the best place
@@ -800,7 +800,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 38:
-#line 218 "d2_parser.yy" // lalr1.cc:859
+#line 221 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("DhcpDdns", m);
@@ -811,7 +811,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 39:
-#line 223 "d2_parser.yy" // lalr1.cc:859
+#line 226 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
@@ -820,7 +820,7 @@ namespace isc { namespace dhcp {
     break;
 
   case 40:
-#line 228 "d2_parser.yy" // lalr1.cc:859
+#line 231 "d2_parser.yy" // lalr1.cc:859
     {
     // Parse the dhcpddns map
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
@@ -830,23 +830,23 @@ namespace isc { namespace dhcp {
     break;
 
   case 41:
-#line 232 "d2_parser.yy" // lalr1.cc:859
+#line 235 "d2_parser.yy" // lalr1.cc:859
     {
     // parsing completed
 }
 #line 838 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 50:
-#line 248 "d2_parser.yy" // lalr1.cc:859
+  case 53:
+#line 254 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
 #line 846 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 51:
-#line 250 "d2_parser.yy" // lalr1.cc:859
+  case 54:
+#line 256 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr s(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ip-address", s);
@@ -855,266 +855,324 @@ namespace isc { namespace dhcp {
 #line 856 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 52:
-#line 256 "d2_parser.yy" // lalr1.cc:859
+  case 55:
+#line 262 "d2_parser.yy" // lalr1.cc:859
     {
+    if (yystack_[0].value.as< int64_t > () <= 0) {
+        error(yystack_[0].location, "port must be greater than zero");
+    } 
     ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("port", i);
 }
-#line 865 "d2_parser.cc" // lalr1.cc:859
+#line 868 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 53:
-#line 261 "d2_parser.yy" // lalr1.cc:859
+  case 56:
+#line 270 "d2_parser.yy" // lalr1.cc:859
     {
-    ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
-    ctx.stack_.back()->set("dns-server-timeout", i);
+    if (yystack_[0].value.as< int64_t > () <= 0) {
+        error(yystack_[0].location, "dns-server-timeout must be greater than zero");
+    } else { 
+        ElementPtr i(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
+        ctx.stack_.back()->set("dns-server-timeout", i);
+    }
 }
-#line 874 "d2_parser.cc" // lalr1.cc:859
+#line 881 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 54:
-#line 266 "d2_parser.yy" // lalr1.cc:859
+  case 57:
+#line 279 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_PROTOCOL);
 }
-#line 882 "d2_parser.cc" // lalr1.cc:859
+#line 889 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 55:
-#line 268 "d2_parser.yy" // lalr1.cc:859
+  case 58:
+#line 281 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("ncr-protocol", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 891 "d2_parser.cc" // lalr1.cc:859
+#line 898 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 56:
-#line 274 "d2_parser.yy" // lalr1.cc:859
+  case 59:
+#line 287 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("UDP", ctx.loc2pos(yystack_[0].location))); }
-#line 897 "d2_parser.cc" // lalr1.cc:859
+#line 904 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 57:
-#line 275 "d2_parser.yy" // lalr1.cc:859
+  case 60:
+#line 288 "d2_parser.yy" // lalr1.cc:859
     { yylhs.value.as< ElementPtr > () = ElementPtr(new StringElement("TCP", ctx.loc2pos(yystack_[0].location))); }
-#line 903 "d2_parser.cc" // lalr1.cc:859
+#line 910 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 58:
-#line 278 "d2_parser.yy" // lalr1.cc:859
+  case 61:
+#line 291 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NCR_FORMAT);
 }
-#line 911 "d2_parser.cc" // lalr1.cc:859
+#line 918 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 59:
-#line 280 "d2_parser.yy" // lalr1.cc:859
+  case 62:
+#line 293 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr json(new StringElement("JSON", ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("ncr-format", json);
     ctx.leave();
 }
-#line 921 "d2_parser.cc" // lalr1.cc:859
+#line 928 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 60:
-#line 286 "d2_parser.yy" // lalr1.cc:859
+  case 63:
+#line 299 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 929 "d2_parser.cc" // lalr1.cc:859
+#line 936 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 61:
-#line 288 "d2_parser.yy" // lalr1.cc:859
+  case 64:
+#line 301 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.stack_.back()->set("forward-ddns", yystack_[0].value.as< ElementPtr > ());
+    ctx.leave();
+}
+#line 945 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 65:
+#line 306 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.enter(ctx.NO_KEYWORD);
+}
+#line 953 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 66:
+#line 308 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.stack_.back()->set("reverse-ddns", yystack_[0].value.as< ElementPtr > ());
+    ctx.leave();
+}
+#line 962 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 67:
+#line 313 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.enter(ctx.NO_KEYWORD);
+}
+#line 970 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 68:
+#line 315 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.stack_.back()->set("tsig-keys", yystack_[0].value.as< ElementPtr > ());
+    ctx.leave();
+}
+#line 979 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 69:
+#line 320 "d2_parser.yy" // lalr1.cc:859
+    {
+    ctx.enter(ctx.NO_KEYWORD);
+}
+#line 987 "d2_parser.cc" // lalr1.cc:859
+    break;
+
+  case 70:
+#line 322 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Dhcp6", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 938 "d2_parser.cc" // lalr1.cc:859
+#line 996 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 62:
-#line 293 "d2_parser.yy" // lalr1.cc:859
+  case 71:
+#line 327 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 946 "d2_parser.cc" // lalr1.cc:859
+#line 1004 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 63:
-#line 295 "d2_parser.yy" // lalr1.cc:859
+  case 72:
+#line 329 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.back()->set("Dhcp4", yystack_[0].value.as< ElementPtr > ());
     ctx.leave();
 }
-#line 955 "d2_parser.cc" // lalr1.cc:859
+#line 1013 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 64:
-#line 305 "d2_parser.yy" // lalr1.cc:859
+  case 73:
+#line 339 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("Logging", m);
     ctx.stack_.push_back(m);
     ctx.enter(ctx.LOGGING);
 }
-#line 966 "d2_parser.cc" // lalr1.cc:859
+#line 1024 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 65:
-#line 310 "d2_parser.yy" // lalr1.cc:859
+  case 74:
+#line 344 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 975 "d2_parser.cc" // lalr1.cc:859
+#line 1033 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 69:
-#line 327 "d2_parser.yy" // lalr1.cc:859
+  case 78:
+#line 361 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("loggers", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.LOGGERS);
 }
-#line 986 "d2_parser.cc" // lalr1.cc:859
+#line 1044 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 70:
-#line 332 "d2_parser.yy" // lalr1.cc:859
+  case 79:
+#line 366 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 995 "d2_parser.cc" // lalr1.cc:859
+#line 1053 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 73:
-#line 344 "d2_parser.yy" // lalr1.cc:859
+  case 82:
+#line 378 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(l);
     ctx.stack_.push_back(l);
 }
-#line 1005 "d2_parser.cc" // lalr1.cc:859
+#line 1063 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 74:
-#line 348 "d2_parser.yy" // lalr1.cc:859
+  case 83:
+#line 382 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 1013 "d2_parser.cc" // lalr1.cc:859
+#line 1071 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 82:
-#line 363 "d2_parser.yy" // lalr1.cc:859
+  case 91:
+#line 397 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1021 "d2_parser.cc" // lalr1.cc:859
+#line 1079 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 83:
-#line 365 "d2_parser.yy" // lalr1.cc:859
+  case 92:
+#line 399 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr name(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("name", name);
     ctx.leave();
 }
-#line 1031 "d2_parser.cc" // lalr1.cc:859
+#line 1089 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 84:
-#line 371 "d2_parser.yy" // lalr1.cc:859
+  case 93:
+#line 405 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr dl(new IntElement(yystack_[0].value.as< int64_t > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("debuglevel", dl);
 }
-#line 1040 "d2_parser.cc" // lalr1.cc:859
+#line 1098 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 85:
-#line 375 "d2_parser.yy" // lalr1.cc:859
+  case 94:
+#line 409 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1048 "d2_parser.cc" // lalr1.cc:859
+#line 1106 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 86:
-#line 377 "d2_parser.yy" // lalr1.cc:859
+  case 95:
+#line 411 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("severity", sev);
     ctx.leave();
 }
-#line 1058 "d2_parser.cc" // lalr1.cc:859
+#line 1116 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 87:
-#line 383 "d2_parser.yy" // lalr1.cc:859
+  case 96:
+#line 417 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output_options", l);
     ctx.stack_.push_back(l);
     ctx.enter(ctx.OUTPUT_OPTIONS);
 }
-#line 1069 "d2_parser.cc" // lalr1.cc:859
+#line 1127 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 88:
-#line 388 "d2_parser.yy" // lalr1.cc:859
+  case 97:
+#line 422 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
     ctx.leave();
 }
-#line 1078 "d2_parser.cc" // lalr1.cc:859
+#line 1136 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 91:
-#line 397 "d2_parser.yy" // lalr1.cc:859
+  case 100:
+#line 431 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->add(m);
     ctx.stack_.push_back(m);
 }
-#line 1088 "d2_parser.cc" // lalr1.cc:859
+#line 1146 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 92:
-#line 401 "d2_parser.yy" // lalr1.cc:859
+  case 101:
+#line 435 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.stack_.pop_back();
 }
-#line 1096 "d2_parser.cc" // lalr1.cc:859
+#line 1154 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 95:
-#line 409 "d2_parser.yy" // lalr1.cc:859
+  case 104:
+#line 443 "d2_parser.yy" // lalr1.cc:859
     {
     ctx.enter(ctx.NO_KEYWORD);
 }
-#line 1104 "d2_parser.cc" // lalr1.cc:859
+#line 1162 "d2_parser.cc" // lalr1.cc:859
     break;
 
-  case 96:
-#line 411 "d2_parser.yy" // lalr1.cc:859
+  case 105:
+#line 445 "d2_parser.yy" // lalr1.cc:859
     {
     ElementPtr sev(new StringElement(yystack_[0].value.as< std::string > (), ctx.loc2pos(yystack_[0].location)));
     ctx.stack_.back()->set("output", sev);
     ctx.leave();
 }
-#line 1114 "d2_parser.cc" // lalr1.cc:859
+#line 1172 "d2_parser.cc" // lalr1.cc:859
     break;
 
 
-#line 1118 "d2_parser.cc" // lalr1.cc:859
+#line 1176 "d2_parser.cc" // lalr1.cc:859
             default:
               break;
             }
@@ -1369,30 +1427,31 @@ namespace isc { namespace dhcp {
   }
 
 
-  const signed char D2Parser::yypact_ninf_ = -57;
+  const signed char D2Parser::yypact_ninf_ = -62;
 
   const signed char D2Parser::yytable_ninf_ = -1;
 
   const signed char
   D2Parser::yypact_[] =
   {
-      22,   -57,   -57,   -57,     5,    -3,    41,    46,   -57,   -57,
-     -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,
-     -57,   -57,   -57,   -57,    -3,    -4,     1,     2,   -57,    30,
-      51,    52,    47,    54,   -57,   -57,   -57,   -57,    56,   -57,
-       0,   -57,   -57,   -57,   -57,   -57,   -57,    57,    58,   -57,
-     -57,   -57,     6,   -57,   -57,   -57,   -57,   -57,   -57,   -57,
-      -3,    -3,   -57,    33,    59,    61,    62,    63,   -57,     1,
-     -57,    64,    38,    39,    68,    69,     2,   -57,   -57,   -57,
-      70,    -3,    -3,    71,    72,   -57,    44,   -57,   -57,    29,
-      60,   -57,    -3,   -57,   -57,     2,    55,   -57,   -57,   -57,
-     -57,   -57,   -57,    16,   -57,    17,   -57,   -57,   -57,    77,
-      55,   -57,    78,   -57,    75,   -57,     4,   -57,    18,    75,
-     -57,   -57,   -57,    80,   -57,   -57,    31,   -57,   -57,   -57,
-     -57,   -57,   -57,    81,    82,    65,    83,    18,   -57,    45,
-      84,   -57,    67,   -57,   -57,    86,   -57,   -57,    20,   -57,
-      66,    86,   -57,   -57,    32,   -57,   -57,    90,    66,   -57,
-      73,   -57,   -57
+      25,   -62,   -62,   -62,     7,    -3,    16,    22,   -62,   -62,
+     -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,    -3,    -4,     1,     5,   -62,    30,
+      45,    50,    51,    57,   -62,   -62,   -62,   -62,    58,   -62,
+       0,   -62,   -62,   -62,   -62,   -62,   -62,    59,    60,   -62,
+     -62,   -62,   -62,   -62,   -62,     2,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,   -62,   -62,    -3,    -3,   -62,    27,
+      61,    62,    65,    66,   -62,     1,   -62,    67,    37,    38,
+      70,    71,    72,    76,    78,     5,   -62,   -62,   -62,    79,
+      -3,    -3,    77,    80,   -62,    52,   -62,   -62,    -2,    68,
+      -3,    -3,    -3,   -62,    -3,   -62,   -62,     5,    64,   -62,
+     -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,     6,   -62,
+      14,   -62,   -62,   -62,    81,    64,   -62,    85,   -62,    84,
+     -62,    47,   -62,    11,    84,   -62,   -62,   -62,    88,   -62,
+     -62,    39,   -62,   -62,   -62,   -62,   -62,   -62,    89,    90,
+      63,    91,    11,   -62,    69,    92,   -62,    74,   -62,   -62,
+      93,   -62,   -62,    49,   -62,    73,    93,   -62,   -62,    43,
+     -62,   -62,    95,    73,   -62,    75,   -62,   -62
   };
 
   const unsigned char
@@ -1401,115 +1460,120 @@ namespace isc { namespace dhcp {
        0,     2,     4,     6,     0,     0,     0,     0,     1,    22,
       16,    12,    11,     8,     9,    10,    15,     3,    13,    14,
       29,     5,    40,     7,    24,    18,     0,     0,    26,     0,
-      25,     0,     0,    19,    60,    62,    38,    64,     0,    37,
-       0,    31,    36,    33,    35,    34,    50,     0,     0,    54,
-      58,    49,     0,    42,    44,    45,    46,    47,    48,    23,
-       0,     0,    17,     0,     0,     0,     0,     0,    28,     0,
-      30,     0,     0,     0,     0,     0,     0,    41,    27,    20,
-       0,     0,     0,     0,     0,    32,     0,    52,    53,     0,
-       0,    43,     0,    61,    63,     0,     0,    51,    56,    57,
-      55,    59,    21,     0,    69,     0,    66,    68,    39,     0,
-       0,    65,     0,    67,     0,    73,     0,    71,     0,     0,
-      70,    82,    87,     0,    85,    81,     0,    75,    77,    79,
-      80,    78,    72,     0,     0,     0,     0,     0,    74,     0,
-       0,    84,     0,    76,    83,     0,    86,    91,     0,    89,
-       0,     0,    88,    95,     0,    93,    90,     0,     0,    92,
-       0,    94,    96
+      25,     0,     0,    19,    69,    71,    38,    73,     0,    37,
+       0,    31,    36,    33,    35,    34,    53,     0,     0,    57,
+      61,    63,    65,    67,    52,     0,    42,    44,    45,    46,
+      47,    48,    49,    50,    51,    23,     0,     0,    17,     0,
+       0,     0,     0,     0,    28,     0,    30,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    41,    27,    20,     0,
+       0,     0,     0,     0,    32,     0,    55,    56,     0,     0,
+       0,     0,     0,    43,     0,    70,    72,     0,     0,    54,
+      59,    60,    58,    62,    64,    66,    68,    21,     0,    78,
+       0,    75,    77,    39,     0,     0,    74,     0,    76,     0,
+      82,     0,    80,     0,     0,    79,    91,    96,     0,    94,
+      90,     0,    84,    86,    88,    89,    87,    81,     0,     0,
+       0,     0,     0,    83,     0,     0,    93,     0,    85,    92,
+       0,    95,   100,     0,    98,     0,     0,    97,   104,     0,
+     102,    99,     0,     0,   101,     0,   103,   105
   };
 
   const signed char
   D2Parser::yypgoto_[] =
   {
-     -57,   -57,   -57,   -57,   -57,   -23,   -57,   -57,   -57,   -57,
-     -57,   -57,   -57,   -57,   -57,   -26,   -57,   -57,   -57,    19,
-     -57,   -57,   -57,   -57,    -5,    23,   -57,   -57,   -57,   -57,
-     -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,
-     -57,   -57,   -15,   -57,   -57,   -57,   -19,   -57,   -57,   -41,
-     -57,   -57,   -57,   -57,   -57,   -57,   -57,   -57,   -50,   -57,
-     -57,   -56,   -57
+     -62,   -62,   -62,   -62,   -62,   -23,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,   -62,   -26,   -62,   -62,   -62,    21,
+     -62,   -62,   -62,   -62,    -5,    19,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,   -62,   -62,   -62,   -62,   -20,   -62,
+     -62,   -62,   -28,   -62,   -62,   -42,   -62,   -62,   -62,   -62,
+     -62,   -62,   -62,   -62,   -55,   -62,   -62,   -61,   -62
   };
 
   const short int
   D2Parser::yydefgoto_[] =
   {
       -1,     4,     5,     6,     7,    16,    17,    18,    25,    32,
-      33,    19,    24,    29,    30,    51,    21,    26,    40,    41,
-      42,    66,    23,    27,    52,    53,    54,    71,    55,    56,
-      57,    74,   100,    58,    75,    43,    64,    44,    65,    45,
-      67,   105,   106,   107,   109,   116,   117,   118,   126,   127,
-     128,   133,   129,   130,   136,   131,   134,   148,   149,   150,
-     154,   155,   157
+      33,    19,    24,    29,    30,    54,    21,    26,    40,    41,
+      42,    72,    23,    27,    55,    56,    57,    77,    58,    59,
+      60,    80,   112,    61,    81,    62,    82,    63,    83,    64,
+      84,    43,    70,    44,    71,    45,    73,   120,   121,   122,
+     124,   131,   132,   133,   141,   142,   143,   148,   144,   145,
+     151,   146,   149,   163,   164,   165,   169,   170,   172
   };
 
   const unsigned char
   D2Parser::yytable_[] =
   {
-      39,    28,     9,    69,    10,     8,    11,   119,    70,    76,
-     120,    34,    35,    36,    77,    46,    47,    48,    49,    76,
-     110,    50,    37,   151,   108,   111,   152,    31,    12,    13,
-      14,    15,    38,    38,   137,   158,    59,    78,    79,   138,
-     159,   121,   122,    39,   123,   124,    98,    99,    20,    38,
-       1,     2,     3,    22,    60,    62,    61,    63,    93,    94,
-      68,    72,    73,    81,    80,    82,    83,    84,    86,   102,
-      87,    88,    89,    90,    92,    97,   144,   104,    95,    96,
-     101,   112,   115,   114,   135,   139,   140,   142,    85,   145,
-     103,   153,   125,   147,   160,   113,   143,   141,   146,    91,
-     132,   156,   161,     0,   162,     0,     0,     0,     0,     0,
-       0,   125
+      39,    28,     9,    75,    10,    85,    11,     8,    76,    85,
+      86,    34,    35,    36,   123,   110,   111,   125,    46,    47,
+      48,    49,   126,    20,    50,    37,    51,    52,    53,    22,
+      31,    12,    13,    14,    15,    38,    65,   136,   137,    38,
+     138,   139,   152,    87,    88,    38,   173,   153,    66,    39,
+     134,   174,   166,   135,    67,   167,     1,     2,     3,    68,
+      69,    89,    74,    78,    79,    90,    91,   105,   106,    92,
+      93,    95,    96,    97,    98,    99,   100,   114,   115,   116,
+     101,   117,   102,   104,   107,   127,   109,   108,   113,   119,
+     129,   130,   150,   154,   155,   157,    94,   160,   156,   175,
+     162,   168,   118,   159,   103,   128,   147,   140,   161,   177,
+     158,   171,   176,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   140
   };
 
   const short int
   D2Parser::yycheck_[] =
   {
-      26,    24,     5,     3,     7,     0,     9,     3,     8,     3,
-       6,    10,    11,    12,     8,    13,    14,    15,    16,     3,
-       3,    19,    21,     3,     8,     8,     6,    31,    31,    32,
-      33,    34,    31,    31,     3,     3,     6,    60,    61,     8,
-       8,    23,    24,    69,    26,    27,    17,    18,     7,    31,
-      28,    29,    30,     7,     3,     8,     4,     3,    81,    82,
-       4,     4,     4,     4,    31,     4,     4,     4,     4,    92,
-      32,    32,     4,     4,     4,    31,    31,    22,     7,     7,
-      20,     4,     7,     5,     4,     4,     4,     4,    69,     5,
-      95,    25,   118,     7,     4,   110,   137,    32,    31,    76,
-     119,   151,   158,    -1,    31,    -1,    -1,    -1,    -1,    -1,
-      -1,   137
+      26,    24,     5,     3,     7,     3,     9,     0,     8,     3,
+       8,    10,    11,    12,     8,    17,    18,     3,    13,    14,
+      15,    16,     8,     7,    19,    24,    21,    22,    23,     7,
+      34,    34,    35,    36,    37,    34,     6,    26,    27,    34,
+      29,    30,     3,    66,    67,    34,     3,     8,     3,    75,
+       3,     8,     3,     6,     4,     6,    31,    32,    33,     8,
+       3,    34,     4,     4,     4,     4,     4,    90,    91,     4,
+       4,     4,    35,    35,     4,     4,     4,   100,   101,   102,
+       4,   104,     4,     4,     7,     4,    34,     7,    20,    25,
+       5,     7,     4,     4,     4,     4,    75,     5,    35,     4,
+       7,    28,   107,    34,    85,   125,   134,   133,    34,    34,
+     152,   166,   173,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,   152
   };
 
   const unsigned char
   D2Parser::yystos_[] =
   {
-       0,    28,    29,    30,    36,    37,    38,    39,     0,     5,
-       7,     9,    31,    32,    33,    34,    40,    41,    42,    46,
-       7,    51,     7,    57,    47,    43,    52,    58,    40,    48,
-      49,    31,    44,    45,    10,    11,    12,    21,    31,    50,
-      53,    54,    55,    70,    72,    74,    13,    14,    15,    16,
-      19,    50,    59,    60,    61,    63,    64,    65,    68,     6,
-       3,     4,     8,     3,    71,    73,    56,    75,     4,     3,
-       8,    62,     4,     4,    66,    69,     3,     8,    40,    40,
-      31,     4,     4,     4,     4,    54,     4,    32,    32,     4,
-       4,    60,     4,    40,    40,     7,     7,    31,    17,    18,
-      67,    20,    40,    59,    22,    76,    77,    78,     8,    79,
-       3,     8,     4,    77,     5,     7,    80,    81,    82,     3,
-       6,    23,    24,    26,    27,    50,    83,    84,    85,    87,
-      88,    90,    81,    86,    91,     4,    89,     3,     8,     4,
-       4,    32,     4,    84,    31,     5,    31,     7,    92,    93,
-      94,     3,     6,    25,    95,    96,    93,    97,     3,     8,
-       4,    96,    31
+       0,    31,    32,    33,    39,    40,    41,    42,     0,     5,
+       7,     9,    34,    35,    36,    37,    43,    44,    45,    49,
+       7,    54,     7,    60,    50,    46,    55,    61,    43,    51,
+      52,    34,    47,    48,    10,    11,    12,    24,    34,    53,
+      56,    57,    58,    79,    81,    83,    13,    14,    15,    16,
+      19,    21,    22,    23,    53,    62,    63,    64,    66,    67,
+      68,    71,    73,    75,    77,     6,     3,     4,     8,     3,
+      80,    82,    59,    84,     4,     3,     8,    65,     4,     4,
+      69,    72,    74,    76,    78,     3,     8,    43,    43,    34,
+       4,     4,     4,     4,    57,     4,    35,    35,     4,     4,
+       4,     4,     4,    63,     4,    43,    43,     7,     7,    34,
+      17,    18,    70,    20,    43,    43,    43,    43,    62,    25,
+      85,    86,    87,     8,    88,     3,     8,     4,    86,     5,
+       7,    89,    90,    91,     3,     6,    26,    27,    29,    30,
+      53,    92,    93,    94,    96,    97,    99,    90,    95,   100,
+       4,    98,     3,     8,     4,     4,    35,     4,    93,    34,
+       5,    34,     7,   101,   102,   103,     3,     6,    28,   104,
+     105,   102,   106,     3,     8,     4,   105,    34
   };
 
   const unsigned char
   D2Parser::yyr1_[] =
   {
-       0,    35,    37,    36,    38,    36,    39,    36,    40,    40,
-      40,    40,    40,    40,    40,    41,    43,    42,    44,    44,
-      45,    45,    47,    46,    48,    48,    49,    49,    50,    52,
-      51,    53,    53,    54,    54,    54,    54,    54,    56,    55,
-      58,    57,    59,    59,    60,    60,    60,    60,    60,    60,
-      62,    61,    63,    64,    66,    65,    67,    67,    69,    68,
-      71,    70,    73,    72,    75,    74,    76,    76,    77,    79,
-      78,    80,    80,    82,    81,    83,    83,    84,    84,    84,
-      84,    84,    86,    85,    87,    89,    88,    91,    90,    92,
-      92,    94,    93,    95,    95,    97,    96
+       0,    38,    40,    39,    41,    39,    42,    39,    43,    43,
+      43,    43,    43,    43,    43,    44,    46,    45,    47,    47,
+      48,    48,    50,    49,    51,    51,    52,    52,    53,    55,
+      54,    56,    56,    57,    57,    57,    57,    57,    59,    58,
+      61,    60,    62,    62,    63,    63,    63,    63,    63,    63,
+      63,    63,    63,    65,    64,    66,    67,    69,    68,    70,
+      70,    72,    71,    74,    73,    76,    75,    78,    77,    80,
+      79,    82,    81,    84,    83,    85,    85,    86,    88,    87,
+      89,    89,    91,    90,    92,    92,    93,    93,    93,    93,
+      93,    95,    94,    96,    98,    97,   100,    99,   101,   101,
+     103,   102,   104,   104,   106,   105
   };
 
   const unsigned char
@@ -1520,11 +1584,12 @@ namespace isc { namespace dhcp {
        3,     5,     0,     4,     0,     1,     1,     3,     2,     0,
        4,     1,     3,     1,     1,     1,     1,     1,     0,     6,
        0,     4,     1,     3,     1,     1,     1,     1,     1,     1,
-       0,     4,     3,     3,     0,     4,     1,     1,     0,     4,
-       0,     4,     0,     4,     0,     6,     1,     3,     1,     0,
-       6,     1,     3,     0,     4,     1,     3,     1,     1,     1,
-       1,     1,     0,     4,     3,     0,     4,     0,     6,     1,
-       3,     0,     4,     1,     3,     0,     4
+       1,     1,     1,     0,     4,     3,     3,     0,     4,     1,
+       1,     0,     4,     0,     4,     0,     4,     0,     4,     0,
+       4,     0,     4,     0,     6,     1,     3,     1,     0,     6,
+       1,     3,     0,     4,     1,     3,     1,     1,     1,     1,
+       1,     0,     4,     3,     0,     4,     0,     6,     1,     3,
+       0,     4,     1,     3,     0,     4
   };
 
 
@@ -1538,39 +1603,42 @@ namespace isc { namespace dhcp {
   "\"]\"", "\"{\"", "\"}\"", "\"null\"", "\"Dhcp6\"", "\"Dhcp4\"",
   "\"DhcpDdns\"", "\"ip-address\"", "\"port\"", "\"dns-server-timeout\"",
   "\"ncr-protocol\"", "\"UDP\"", "\"TCP\"", "\"ncr-format\"", "\"JSON\"",
-  "\"Logging\"", "\"loggers\"", "\"name\"", "\"output_options\"",
-  "\"output\"", "\"debuglevel\"", "\"severity\"", "TOPLEVEL_JSON",
-  "TOPLEVEL_DHCPDDNS", "SUB_DHCPDDNS", "\"constant string\"",
-  "\"integer\"", "\"floating point\"", "\"boolean\"", "$accept", "start",
-  "$@1", "$@2", "$@3", "value", "sub_json", "map2", "$@4", "map_content",
+  "\"forward-ddns\"", "\"reverse-ddns\"", "\"tsig-keys\"", "\"Logging\"",
+  "\"loggers\"", "\"name\"", "\"output_options\"", "\"output\"",
+  "\"debuglevel\"", "\"severity\"", "TOPLEVEL_JSON", "TOPLEVEL_DHCPDDNS",
+  "SUB_DHCPDDNS", "\"constant string\"", "\"integer\"",
+  "\"floating point\"", "\"boolean\"", "$accept", "start", "$@1", "$@2",
+  "$@3", "value", "sub_json", "map2", "$@4", "map_content",
   "not_empty_map", "list_generic", "$@5", "list_content", "not_empty_list",
   "unknown_map_entry", "syntax_map", "$@6", "global_objects",
   "global_object", "dhcpddns_object", "$@7", "sub_dhcpddns", "$@8",
   "dhcpddns_params", "dhcpddns_param", "ip_address", "$@9", "port",
   "dns_server_timeout", "ncr_protocol", "$@10", "ncr_protocol_value",
-  "ncr_format", "$@11", "dhcp6_json_object", "$@12", "dhcp4_json_object",
-  "$@13", "logging_object", "$@14", "logging_params", "logging_param",
-  "loggers", "$@15", "loggers_entries", "logger_entry", "$@16",
-  "logger_params", "logger_param", "name", "$@17", "debuglevel",
-  "severity", "$@18", "output_options_list", "$@19",
-  "output_options_list_content", "output_entry", "$@20", "output_params",
-  "output_param", "$@21", YY_NULLPTR
+  "ncr_format", "$@11", "forward_ddns", "$@12", "reverse_ddns", "$@13",
+  "tsig_keys", "$@14", "dhcp6_json_object", "$@15", "dhcp4_json_object",
+  "$@16", "logging_object", "$@17", "logging_params", "logging_param",
+  "loggers", "$@18", "loggers_entries", "logger_entry", "$@19",
+  "logger_params", "logger_param", "name", "$@20", "debuglevel",
+  "severity", "$@21", "output_options_list", "$@22",
+  "output_options_list_content", "output_entry", "$@23", "output_params",
+  "output_param", "$@24", YY_NULLPTR
   };
 
 #if D2_PARSER_DEBUG
   const unsigned short int
   D2Parser::yyrline_[] =
   {
-       0,    97,    97,    97,    98,    98,    99,    99,   107,   108,
-     109,   110,   111,   112,   113,   116,   121,   121,   133,   134,
-     137,   141,   148,   148,   163,   164,   167,   171,   182,   192,
-     192,   204,   205,   209,   210,   211,   212,   213,   218,   218,
-     228,   228,   236,   237,   240,   241,   242,   243,   244,   245,
-     248,   248,   256,   261,   266,   266,   274,   275,   278,   278,
-     286,   286,   293,   293,   305,   305,   318,   319,   323,   327,
-     327,   339,   340,   344,   344,   352,   353,   356,   357,   358,
-     359,   360,   363,   363,   371,   375,   375,   383,   383,   393,
-     394,   397,   397,   405,   406,   409,   409
+       0,   100,   100,   100,   101,   101,   102,   102,   110,   111,
+     112,   113,   114,   115,   116,   119,   124,   124,   136,   137,
+     140,   144,   151,   151,   166,   167,   170,   174,   185,   195,
+     195,   207,   208,   212,   213,   214,   215,   216,   221,   221,
+     231,   231,   239,   240,   243,   244,   245,   246,   247,   248,
+     249,   250,   251,   254,   254,   262,   270,   279,   279,   287,
+     288,   291,   291,   299,   299,   306,   306,   313,   313,   320,
+     320,   327,   327,   339,   339,   352,   353,   357,   361,   361,
+     373,   374,   378,   378,   386,   387,   390,   391,   392,   393,
+     394,   397,   397,   405,   409,   409,   417,   417,   427,   428,
+     431,   431,   439,   440,   443,   443
   };
 
   // Print the state stack on the debug stream.
@@ -1604,13 +1672,13 @@ namespace isc { namespace dhcp {
 
 
 #line 14 "d2_parser.yy" // lalr1.cc:1167
-} } // isc::dhcp
-#line 1609 "d2_parser.cc" // lalr1.cc:1167
-#line 417 "d2_parser.yy" // lalr1.cc:1168
+} } // isc::d2
+#line 1677 "d2_parser.cc" // lalr1.cc:1167
+#line 451 "d2_parser.yy" // lalr1.cc:1168
 
 
 void
-isc::dhcp::D2Parser::error(const location_type& loc,
+isc::d2::D2Parser::error(const location_type& loc,
                               const std::string& what)
 {
     ctx.error(loc, what);
index 5648d8a3f4a3df1b40545e8af3552f280b24af29..dcac797a3c2b4457c447cd8e86b1514824e9815f 100644 (file)
@@ -32,7 +32,7 @@
 
 /**
  ** \file d2_parser.h
- ** Define the isc::dhcp::parser class.
+ ** Define the isc::d2::parser class.
  */
 
 // C++ LALR(1) parser skeleton written by Akim Demaille.
@@ -48,7 +48,7 @@
 #include <boost/lexical_cast.hpp>
 #include <d2/parser_context_decl.h>
 
-using namespace isc::dhcp;
+using namespace isc::d2;
 using namespace isc::data;
 using namespace std;
 
@@ -136,7 +136,7 @@ using namespace std;
 #endif  /* ! defined D2_PARSER_DEBUG */
 
 #line 14 "d2_parser.yy" // lalr1.cc:392
-namespace isc { namespace dhcp {
+namespace isc { namespace d2 {
 #line 141 "d2_parser.h" // lalr1.cc:392
 
 
@@ -360,20 +360,23 @@ namespace isc { namespace dhcp {
         TOKEN_TCP = 273,
         TOKEN_NCR_FORMAT = 274,
         TOKEN_JSON = 275,
-        TOKEN_LOGGING = 276,
-        TOKEN_LOGGERS = 277,
-        TOKEN_NAME = 278,
-        TOKEN_OUTPUT_OPTIONS = 279,
-        TOKEN_OUTPUT = 280,
-        TOKEN_DEBUGLEVEL = 281,
-        TOKEN_SEVERITY = 282,
-        TOKEN_TOPLEVEL_JSON = 283,
-        TOKEN_TOPLEVEL_DHCPDDNS = 284,
-        TOKEN_SUB_DHCPDDNS = 285,
-        TOKEN_STRING = 286,
-        TOKEN_INTEGER = 287,
-        TOKEN_FLOAT = 288,
-        TOKEN_BOOLEAN = 289
+        TOKEN_FORWARD_DDNS = 276,
+        TOKEN_REVERSE_DDNS = 277,
+        TOKEN_TSIG_KEYS = 278,
+        TOKEN_LOGGING = 279,
+        TOKEN_LOGGERS = 280,
+        TOKEN_NAME = 281,
+        TOKEN_OUTPUT_OPTIONS = 282,
+        TOKEN_OUTPUT = 283,
+        TOKEN_DEBUGLEVEL = 284,
+        TOKEN_SEVERITY = 285,
+        TOKEN_TOPLEVEL_JSON = 286,
+        TOKEN_TOPLEVEL_DHCPDDNS = 287,
+        TOKEN_SUB_DHCPDDNS = 288,
+        TOKEN_STRING = 289,
+        TOKEN_INTEGER = 290,
+        TOKEN_FLOAT = 291,
+        TOKEN_BOOLEAN = 292
       };
     };
 
@@ -564,6 +567,18 @@ namespace isc { namespace dhcp {
     symbol_type
     make_JSON (const location_type& l);
 
+    static inline
+    symbol_type
+    make_FORWARD_DDNS (const location_type& l);
+
+    static inline
+    symbol_type
+    make_REVERSE_DDNS (const location_type& l);
+
+    static inline
+    symbol_type
+    make_TSIG_KEYS (const location_type& l);
+
     static inline
     symbol_type
     make_LOGGING (const location_type& l);
@@ -622,7 +637,7 @@ namespace isc { namespace dhcp {
 
 
     /// Build a parser object.
-    D2Parser (isc::dhcp::D2ParserContext& ctx_yyarg);
+    D2Parser (isc::d2::D2ParserContext& ctx_yyarg);
     virtual ~D2Parser ();
 
     /// Parse.
@@ -825,17 +840,17 @@ namespace isc { namespace dhcp {
     enum
     {
       yyeof_ = 0,
-      yylast_ = 111,     ///< Last index in yytable_.
-      yynnts_ = 63,  ///< Number of nonterminal symbols.
+      yylast_ = 126,     ///< Last index in yytable_.
+      yynnts_ = 69,  ///< Number of nonterminal symbols.
       yyfinal_ = 8, ///< Termination state number.
       yyterror_ = 1,
       yyerrcode_ = 256,
-      yyntokens_ = 35  ///< Number of tokens.
+      yyntokens_ = 38  ///< Number of tokens.
     };
 
 
     // User arguments.
-    isc::dhcp::D2ParserContext& ctx;
+    isc::d2::D2ParserContext& ctx;
   };
 
   // Symbol number corresponding to token number t.
@@ -875,9 +890,10 @@ namespace isc { namespace dhcp {
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35,    36,    37
     };
-    const unsigned int user_token_number_max_ = 289;
+    const unsigned int user_token_number_max_ = 292;
     const token_number_type undef_token_ = 2;
 
     if (static_cast<int>(t) <= yyeof_)
@@ -910,24 +926,24 @@ namespace isc { namespace dhcp {
   {
       switch (other.type_get ())
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.copy< ElementPtr > (other.value);
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.copy< bool > (other.value);
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.copy< double > (other.value);
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.copy< int64_t > (other.value);
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.copy< std::string > (other.value);
         break;
 
@@ -948,24 +964,24 @@ namespace isc { namespace dhcp {
     (void) v;
       switch (this->type_get ())
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.copy< ElementPtr > (v);
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.copy< bool > (v);
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.copy< double > (v);
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.copy< int64_t > (v);
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.copy< std::string > (v);
         break;
 
@@ -1045,24 +1061,24 @@ namespace isc { namespace dhcp {
     // Type destructor.
     switch (yytype)
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.template destroy< ElementPtr > ();
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.template destroy< bool > ();
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.template destroy< double > ();
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.template destroy< int64_t > ();
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.template destroy< std::string > ();
         break;
 
@@ -1089,24 +1105,24 @@ namespace isc { namespace dhcp {
     super_type::move(s);
       switch (this->type_get ())
     {
-      case 40: // value
-      case 67: // ncr_protocol_value
+      case 43: // value
+      case 70: // ncr_protocol_value
         value.move< ElementPtr > (s.value);
         break;
 
-      case 34: // "boolean"
+      case 37: // "boolean"
         value.move< bool > (s.value);
         break;
 
-      case 33: // "floating point"
+      case 36: // "floating point"
         value.move< double > (s.value);
         break;
 
-      case 32: // "integer"
+      case 35: // "integer"
         value.move< int64_t > (s.value);
         break;
 
-      case 31: // "constant string"
+      case 34: // "constant string"
         value.move< std::string > (s.value);
         break;
 
@@ -1168,7 +1184,7 @@ namespace isc { namespace dhcp {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289
+     285,   286,   287,   288,   289,   290,   291,   292
     };
     return static_cast<token_type> (yytoken_number_[type]);
   }
@@ -1287,6 +1303,24 @@ namespace isc { namespace dhcp {
     return symbol_type (token::TOKEN_JSON, l);
   }
 
+  D2Parser::symbol_type
+  D2Parser::make_FORWARD_DDNS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_FORWARD_DDNS, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_REVERSE_DDNS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_REVERSE_DDNS, l);
+  }
+
+  D2Parser::symbol_type
+  D2Parser::make_TSIG_KEYS (const location_type& l)
+  {
+    return symbol_type (token::TOKEN_TSIG_KEYS, l);
+  }
+
   D2Parser::symbol_type
   D2Parser::make_LOGGING (const location_type& l)
   {
@@ -1373,8 +1407,8 @@ namespace isc { namespace dhcp {
 
 
 #line 14 "d2_parser.yy" // lalr1.cc:392
-} } // isc::dhcp
-#line 1378 "d2_parser.h" // lalr1.cc:392
+} } // isc::d2
+#line 1412 "d2_parser.h" // lalr1.cc:392
 
 
 
index 35e57fca72d5203ab0cd0a13ecead0dc7a1385ad..7b6cce7cee554f21e3241a53806ce1620cd012cc 100644 (file)
@@ -11,7 +11,7 @@
 %define api.prefix {d2_parser_}
 %define api.token.constructor
 %define api.value.type variant
-%define api.namespace {isc::dhcp}
+%define api.namespace {isc::d2}
 %define parse.assert
 %code requires
 {
 #include <boost/lexical_cast.hpp>
 #include <d2/parser_context_decl.h>
 
-using namespace isc::dhcp;
+using namespace isc::d2;
 using namespace isc::data;
 using namespace std;
 }
 // The parsing context.
-%param { isc::dhcp::D2ParserContext& ctx }
+%param { isc::d2::D2ParserContext& ctx }
 %locations
 %define parse.trace
 %define parse.error verbose
@@ -38,7 +38,7 @@ using namespace std;
 
 %define api.token.prefix {TOKEN_}
 // Tokens in an order which makes sense and related to the intented use.
-// Actual regexps for tokens are defined in dhcp6_lexer.ll.
+// Actual regexps for tokens are defined in d2_lexer.ll.
 %token
   END  0  "end of file"
   COMMA ","
@@ -61,6 +61,9 @@ using namespace std;
   TCP "TCP"
   NCR_FORMAT "ncr-format"
   JSON "JSON"
+  FORWARD_DDNS "forward-ddns"
+  REVERSE_DDNS "reverse-ddns"
+  TSIG_KEYS "tsig-keys"
 
   LOGGING "Logging"
   LOGGERS "loggers"
@@ -242,6 +245,9 @@ dhcpddns_param: ip_address
                | dns_server_timeout
                | ncr_protocol
                | ncr_format
+               | forward_ddns
+               | reverse_ddns
+               | tsig_keys
                | unknown_map_entry
                ;
 
@@ -254,13 +260,20 @@ ip_address: IP_ADDRESS {
 };
 
 port: PORT COLON INTEGER {
+    if ($3 <= 0) {
+        error(@3, "port must be greater than zero");
+    } 
     ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
     ctx.stack_.back()->set("port", i);
 };
 
 dns_server_timeout: DNS_SERVER_TIMEOUT COLON INTEGER {
-    ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
-    ctx.stack_.back()->set("dns-server-timeout", i);
+    if ($3 <= 0) {
+        error(@3, "dns-server-timeout must be greater than zero");
+    } else { 
+        ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
+        ctx.stack_.back()->set("dns-server-timeout", i);
+    }
 };
 
 ncr_protocol: NCR_PROTOCOL {
@@ -283,6 +296,27 @@ ncr_format: NCR_FORMAT {
     ctx.leave();
 };
 
+forward_ddns : FORWARD_DDNS {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON value {
+    ctx.stack_.back()->set("forward-ddns", $4);
+    ctx.leave();
+};
+
+reverse_ddns : REVERSE_DDNS {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON value {
+    ctx.stack_.back()->set("reverse-ddns", $4);
+    ctx.leave();
+};
+
+tsig_keys : TSIG_KEYS {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON value {
+    ctx.stack_.back()->set("tsig-keys", $4);
+    ctx.leave();
+};
+
 dhcp6_json_object: DHCP6 {
     ctx.enter(ctx.NO_KEYWORD);
 } COLON value {
@@ -417,7 +451,7 @@ output_param: OUTPUT {
 %%
 
 void
-isc::dhcp::D2Parser::error(const location_type& loc,
+isc::d2::D2Parser::error(const location_type& loc,
                               const std::string& what)
 {
     ctx.error(loc, what);
index 0c12ec092bff2bc136a08c0ea0d5684fc4a453b2..74a85b454762507165929ece8b90aed4f7243c50 100644 (file)
@@ -11,7 +11,7 @@
 using namespace isc::data;
 
 namespace isc {
-namespace dhcp {
+namespace d2 {
 /// @brief This sets of arrays define the default values and
 ///        values inherited (derived) between various scopes.
 ///
@@ -36,8 +36,8 @@ const SimpleDefaults D2SimpleParser::D2_GLOBAL_DEFAULTS = {
     { "ip-address",         Element::string, "127.0.0.1" },
     { "port",               Element::integer, "53001" },
     { "dns-server-timeout", Element::integer, "100" },
-    { "ncr-protocol",       Element::integer, "UDP" },
-    { "ncr-format",         Element::integer, "JSON" }
+    { "ncr-protocol",       Element::string, "UDP" },
+    { "ncr-format",         Element::string, "JSON" }
 };
 
 /// @}
index 260c72ea16142ab7c31c98952220df01cda540e4..2f58d8eebe1244615ce285cccd6f63897f446fcb 100644 (file)
@@ -10,7 +10,7 @@
 #include <cc/simple_parser.h>
 
 namespace isc {
-namespace dhcp {
+namespace d2 {
 
 /// @brief SimpleParser specialized for D2
 ///
index 5f420fb91bb3ade84f5b3f415d22d6a4d1879ffe..80826e9758c9a24f402802a9383e0fbe7aad8b85 100644 (file)
@@ -32,7 +32,7 @@
 
 /**
  ** \file location.hh
- ** Define the isc::dhcp::location class.
+ ** Define the isc::d2::location class.
  */
 
 #ifndef YY_D2_PARSER_LOCATION_HH_INCLUDED
@@ -41,7 +41,7 @@
 # include "position.hh"
 
 #line 14 "d2_parser.yy" // location.cc:337
-namespace isc { namespace dhcp {
+namespace isc { namespace d2 {
 #line 46 "location.hh" // location.cc:337
   /// Abstract a location.
   class location
@@ -187,6 +187,6 @@ namespace isc { namespace dhcp {
   }
 
 #line 14 "d2_parser.yy" // location.cc:337
-} } // isc::dhcp
+} } // isc::d2
 #line 192 "location.hh" // location.cc:337
 #endif // !YY_D2_PARSER_LOCATION_HH_INCLUDED
index f46786d44ef8ad3e8eba2e42b5989a45f7b1c139..6ab6d61988e048fb0474863b06043595e2fa4bf3 100644 (file)
@@ -13,7 +13,7 @@
 #include <limits>
 
 namespace isc {
-namespace dhcp {
+namespace d2 {
 
 D2ParserContext::D2ParserContext()
   : ctx_(NO_KEYWORD), trace_scanning_(false), trace_parsing_(false)
@@ -43,7 +43,7 @@ D2ParserContext::parseFile(const std::string& filename, ParserType parser_type)
 
 isc::data::ElementPtr
 D2ParserContext::parseCommon() {
-    isc::dhcp::D2Parser parser(*this);
+    isc::d2::D2Parser parser(*this);
     // Uncomment this to get detailed parser logs.
     // trace_parsing_ = true;
     parser.set_debug_level(trace_parsing_);
@@ -68,7 +68,7 @@ D2ParserContext::parseCommon() {
 
 
 void
-D2ParserContext::error(const isc::dhcp::location& loc, const std::string& what)
+D2ParserContext::error(const isc::d2::location& loc, const std::string& what)
 {
     isc_throw(D2ParseError, loc << ": " << what);
 }
@@ -86,7 +86,7 @@ D2ParserContext::fatal (const std::string& what)
 }
 
 isc::data::Element::Position
-D2ParserContext::loc2pos(isc::dhcp::location& loc)
+D2ParserContext::loc2pos(isc::d2::location& loc)
 {
     const std::string& file = *loc.begin.filename;
     const uint32_t line = loc.begin.line;
index 5848f7f9be735c19690c62ff62e13d468a0aa7c9..63bd55dda89a1c5187158eeccf59de07f8ced7db 100644 (file)
 #include <exceptions/exceptions.h>
 
 // Tell Flex the lexer's prototype ...
-#define YY_DECL isc::dhcp::D2Parser::symbol_type d2_parser_lex (D2ParserContext& driver)
+#define YY_DECL isc::d2::D2Parser::symbol_type d2_parser_lex (D2ParserContext& driver)
 
 // ... and declare it for the parser's sake.
 YY_DECL;
 
 namespace isc {
-namespace dhcp {
+namespace d2 {
 
 /// @brief Evaluation error exception raised when trying to parse.
 ///
@@ -49,10 +49,10 @@ public:
         PARSER_JSON,
 
         ///< Used while parsing top level (contains DhcpDdns, Logging, others)
-        PARSER_CONFIG,
+        PARSER_DHCPDDNS,
 
         ///< Used while parsing content of DhcpDdns.
-        PARSER_DHCPDDNS
+        PARSER_SUB_DHCPDDNS
     } ParserType;
 
     /// @brief Default constructor.
@@ -116,7 +116,7 @@ public:
     /// @param loc location within the parsed file when experienced a problem.
     /// @param what string explaining the nature of the error.
     /// @throw D2ParseError
-    void error(const isc::dhcp::location& loc, const std::string& what);
+    void error(const isc::d2::location& loc, const std::string& what);
 
     /// @brief Error handler
     ///
@@ -143,7 +143,7 @@ public:
     ///
     /// @param loc location in bison format
     /// @return Position in format accepted by Element
-    isc::data::Element::Position loc2pos(isc::dhcp::location& loc);
+    isc::data::Element::Position loc2pos(isc::d2::location& loc);
 
     /// @brief Defines syntactic contexts for lexical tie-ins
     typedef enum {
@@ -183,10 +183,10 @@ public:
     ///
     /// The lexer will keep updating it. This variable will be useful
     /// for logging errors.
-    isc::dhcp::location loc_;
+    isc::d2::location loc_;
 
     /// @brief Location stack
-    std::vector<isc::dhcp::location> locs_;
+    std::vector<isc::d2::location> locs_;
 
     /// @brief Lexer state stack
     std::vector<struct yy_buffer_state*> states_;
index 474a66bc2b1213391102784159f9f9c91e2783ca..a927ac1b4b3e117494098c3527c48b46d7132e27 100644 (file)
@@ -10,7 +10,7 @@
 /// @file d2/parser_context_decl.h Forward declaration of the ParserContext class
 
 namespace isc {
-namespace dhcp {
+namespace d2 {
 
 class D2ParserContext;
 
index 6d0316bbbde6438d9e74e11d9fe37dc02677a6ef..41f8acd1b9000840ed92065859f29222d52b0e56 100644 (file)
@@ -32,7 +32,7 @@
 
 /**
  ** \file position.hh
- ** Define the isc::dhcp::position class.
+ ** Define the isc::d2::position class.
  */
 
 #ifndef YY_D2_PARSER_POSITION_HH_INCLUDED
@@ -51,7 +51,7 @@
 # endif
 
 #line 14 "d2_parser.yy" // location.cc:337
-namespace isc { namespace dhcp {
+namespace isc { namespace d2 {
 #line 56 "position.hh" // location.cc:337
   /// Abstract a position.
   class position
@@ -175,6 +175,6 @@ namespace isc { namespace dhcp {
   }
 
 #line 14 "d2_parser.yy" // location.cc:337
-} } // isc::dhcp
+} } // isc::d2
 #line 180 "position.hh" // location.cc:337
 #endif // !YY_D2_PARSER_POSITION_HH_INCLUDED
index 0f0887c98240537db776d9a972179bbc23ec55b5..92c74d309edff5844aa0c11b4ffa76082720a43f 100644 (file)
@@ -32,7 +32,7 @@
 
 /**
  ** \file stack.hh
- ** Define the isc::dhcp::stack class.
+ ** Define the isc::d2::stack class.
  */
 
 #ifndef YY_D2_PARSER_STACK_HH_INCLUDED
@@ -41,7 +41,7 @@
 # include <vector>
 
 #line 14 "d2_parser.yy" // stack.hh:151
-namespace isc { namespace dhcp {
+namespace isc { namespace d2 {
 #line 46 "stack.hh" // stack.hh:151
   template <class T, class S = std::vector<T> >
   class stack
@@ -151,7 +151,7 @@ namespace isc { namespace dhcp {
   };
 
 #line 14 "d2_parser.yy" // stack.hh:151
-} } // isc::dhcp
+} } // isc::d2
 #line 156 "stack.hh" // stack.hh:151
 
 #endif // !YY_D2_PARSER_STACK_HH_INCLUDED
index a28ed6e8631df21478becce5ae6f91454c55d7cd..14b8ea06f077c7804612e30842c87f7619a67197 100644 (file)
@@ -23,6 +23,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/src/bin
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/bin/d2/tests\"
 AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
+AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/ddns\"
 
 CLEANFILES = $(builddir)/interfaces.txt $(builddir)/logger_lockfile
 
@@ -55,6 +56,8 @@ d2_unittests_SOURCES += nc_remove_unittests.cc
 d2_unittests_SOURCES += nc_test_utils.cc nc_test_utils.h
 d2_unittests_SOURCES += nc_trans_unittests.cc
 d2_unittests_SOURCES += d2_controller_unittests.cc
+d2_unittests_SOURCES += d2_simple_parser_unittest.cc
+d2_unittests_SOURCES += parser_unittest.cc parser_unittest.h
 
 d2_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 d2_unittests_LDFLAGS = $(AM_LDFLAGS) $(CRYPTO_LDFLAGS)
@@ -76,6 +79,7 @@ d2_unittests_LDADD += $(top_builddir)/src/lib/process/libkea-process.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/testutils/libdhcpsrvtest.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
+d2_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/asiodns/libkea-asiodns.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/stats/libkea-stats.la
 d2_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
index 3f56dd578ad1be8be5ce6e29bf96882099a54c9f..3aece23cc8069e682b0983a70fc62d1633ee8055 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -9,6 +9,7 @@
 #include <config/module_spec.h>
 #include <d2/d2_config.h>
 #include <d2/d2_cfg_mgr.h>
+#include <d2/parser_context.h>
 #include <dhcpsrv/testutils/config_result_check.h>
 #include <process/testutils/d_test_stubs.h>
 #include <test_data_files_config.h>
@@ -172,7 +173,8 @@ public:
             return;
         }
 
-        FAIL() << "Parsing failed as expected but lacks position : " << *comment;
+        FAIL() << "Parsing failed as expected but lacks position : " << *comment
+            << ", filename:" << file_name;
     }
 
     /// @brief Pointer the D2Params most recently parsed.
@@ -433,7 +435,7 @@ TEST_F(D2CfgMgrTest, defaultValues) {
     EXPECT_EQ(D2Params::DFT_DNS_SERVER_TIMEOUT,
               d2_params_->getDnsServerTimeout());
 
-    // Check that protocol timeout gets you its default
+    // Check that omitting protocol gets you its default
     config =
             "{"
             " \"ip-address\": \"192.0.0.1\" , "
@@ -449,7 +451,7 @@ TEST_F(D2CfgMgrTest, defaultValues) {
     EXPECT_EQ(dhcp_ddns::stringToNcrProtocol(D2Params::DFT_NCR_PROTOCOL),
               d2_params_->getNcrProtocol());
 
-    // Check that format timeout gets you its default
+    // Check that omitting format gets you its default
     config =
             "{"
             " \"ip-address\": \"192.0.0.1\" , "
@@ -1641,6 +1643,12 @@ TEST_F(D2CfgMgrTest, matchReverse) {
 }
 
 /// @brief Tests D2 config parsing against a wide range of config permutations.
+///
+/// It tests for both syntax errors that the JSON parsing (D2ParserContext)
+/// should detect as well as post-JSON parsing logic errors generated by
+/// the Element parsers (i.e...SimpleParser/DhcpParser derivations)
+///
+///
 /// It iterates over all of the test configurations described in given file.
 /// The file content is JSON specialized to this test. The format of the file
 /// is:
@@ -1656,12 +1664,15 @@ TEST_F(D2CfgMgrTest, matchReverse) {
 ///
 /// #    Each test has:
 /// #      1. description - optional text description
-/// #      2. should-fail - bool indicator if parsing is expected to file
+/// #      2. syntax-error - text of syntax error D2Parser is expected to emit
+/// #         (defaults to blank = no error expected)
+/// #      3. logic-error - indicator if post-parsing element logic should fail
 /// #         (defaults to false)
-/// #       3. data - configuration text to parse
+/// #      4. data - configuration text to parse
 /// #
 ///      "description" : "<text describing test>",
-///      "should_fail" : <true|false> ,
+///      "syntax-error" : ""|"<exact text from parser including position>" ,
+///      "logic_error" : <true|false> ,
 ///      "data" :
 ///          {
 /// #        configuration elements here
@@ -1695,14 +1706,18 @@ TEST_F(D2CfgMgrTest, configPermutations) {
     }
 
     // Read in each test For each test, read:
+    //
     //  1. description - optional text description
-    //  2. should-fail - bool indicator if parsing is expected to file (defaults
-    //     to false
-    //  3. data - configuration text to parse
+    //  2. syntax-error - error text JSON parser should emit including position,
+    //     defaults to blank (i.e. no error)
+    //  3. logic-error - bool indicator if post-JSON element processing should
+    //     fail
+    //     (defaults to false)
+    //  4. data - configuration text to parse
     //
     // Next attempt to parse the configuration by passing it into
     // D2CfgMgr::parseConfig().  Then check the parsing outcome against the
-    // expected outcome as given by should-fail.
+    // expected outcome as given by logic-error.
     isc::data::ConstElementPtr test;
     ASSERT_TRUE(tests->get("test-list"));
     BOOST_FOREACH(test, tests->get("test-list")->listValue()) {
@@ -1714,12 +1729,20 @@ TEST_F(D2CfgMgrTest, configPermutations) {
             elem->getValue(description);
         }
 
-        // Grab the outcome flag, should-fail, defaults to false if it's
+        // Grab the outcome flag, logic-error, defaults to false if it's
         // not specified.
-        bool should_fail = false;
-        elem = test->get("should-fail");
+        bool logic_error = false;
+        elem = test->get("logic-error");
         if (elem)  {
-            elem->getValue(should_fail);
+            elem->getValue(logic_error);
+        }
+
+        // If the JSON parsing is expected to detect an error, the test
+        // should have specified the error message text.
+        std::string expected_syntax_error = "";
+        elem = test->get("syntax-error");
+        if (elem) {
+            elem->getValue(expected_syntax_error);
         }
 
         // Grab the test's configuration data.
@@ -1727,12 +1750,41 @@ TEST_F(D2CfgMgrTest, configPermutations) {
         ASSERT_TRUE(data) << "No data for test: "
                           << " : " << test->getPosition();
 
-        // Attempt to parse the configuration. We verify that we get the expected
-        // outcome, and if it was supposed to fail if the explanation contains
-        // position information.
+        // Submit the configuration text to the D2Parser.  This is somewhat
+        // artifical as normally the JSON parsing is invoked by @c
+        // DController::configFromFile().  Doing it here, explicitly, allows us
+        // test both syntax and logic errors without the weight of a full
+        // server.  Currently the assumption is that the test data is the
+        // content permitted within a DhcpDdns element only.
+        try {
+            // First we turn the test data back into JSON text
+            D2ParserContext context;
+            stringstream os;
+            data->toJSON(os);
+            // Parse the test data
+            data = context.parseString(os.str(),
+                                       D2ParserContext::PARSER_SUB_DHCPDDNS);
+        } catch (const std::exception& ex) {
+            if (expected_syntax_error.empty()) {
+                // We have an unexpected syntax error.
+                ADD_FAILURE() << description << ", "
+                              << "Unexpected syntax error:" << ex.what();
+            } else {
+                // We expected and got a syntax error, we need to make sure
+                // we got the right one.
+                EXPECT_EQ(expected_syntax_error, ex.what())
+                            << description << ", syntax error mismatch";
+
+                // Expected or not, skip logic testing on syntax errors.
+                continue;
+           }
+        }
+
+        // Attempt to Element parse the configuration. We verify that we get the
+        // expected outcome, and if it was supposed to fail that the explanation
+        // contains position information.
         checkAnswerWithError(cfg_mgr_->parseConfig(data),
-                             (should_fail ? SHOULD_FAIL : SHOULD_PASS),
-                             test_file);
+                             (logic_error ? SHOULD_FAIL : SHOULD_PASS));
     }
 }
 
diff --git a/src/bin/d2/tests/d2_simple_parser_unittest.cc b/src/bin/d2/tests/d2_simple_parser_unittest.cc
new file mode 100644 (file)
index 0000000..30369f1
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+#include <gtest/gtest.h>
+#include <d2/d2_simple_parser.h>
+#include <d2/tests/parser_unittest.h>
+#include <cc/data.h>
+
+#include <boost/lexical_cast.hpp>
+
+using namespace isc;
+using namespace isc::data;
+using namespace isc::d2;
+
+namespace {
+
+/// @brief Text fixture class for D2SimpleParser
+class D2SimpleParserTest : public ::testing::Test {
+public:
+    /// @brief Checks if specified element matches the given integer default
+    ///
+    /// @param element defaulted element to check
+    /// @param deflt SimpleDefault which supplied the default valaue
+    void checkIntegerValue(const ConstElementPtr& element, const SimpleDefault& deflt)  {
+        ASSERT_TRUE(element);
+
+        // Verify it is an integer.
+        ASSERT_EQ(Element::integer, element->getType());
+
+        // Turn default value string into an int.
+        int64_t default_value = 0;
+        ASSERT_NO_THROW(default_value = boost::lexical_cast<int64_t>(deflt.value_));
+
+        // Verify it has the expected value.
+        EXPECT_EQ(default_value, element->intValue());
+    }
+
+    /// @brief Checks if specified element matches the given boolean default
+    ///
+    /// @param element defaulted element to check
+    /// @param deflt SimpleDefault which supplied the default valaue
+    void checkBooleanValue(const ConstElementPtr& element, const SimpleDefault& deflt)  {
+        ASSERT_TRUE(element);
+
+        // Verify it is a bool.
+        ASSERT_EQ(Element::boolean, element->getType());
+
+        // Turn default value string into a bool.
+        bool default_value = false;
+        ASSERT_NO_THROW(boost::lexical_cast<bool>(deflt.value_));
+
+        // Verify it has the expected value.
+        EXPECT_EQ(default_value, element->boolValue());
+    }
+
+    /// @brief Checks if specified element matches the given string default
+    ///
+    /// @param element defaulted element to check
+    /// @param deflt SimpleDefault which supplied the default valaue
+    void checkStringValue(const ConstElementPtr& element, const SimpleDefault& deflt)  {
+        ASSERT_TRUE(element);
+
+        // Verify it's a string
+        ASSERT_EQ(Element::string, element->getType());
+
+        // Verify it has the expected value
+        EXPECT_EQ(deflt.value_, element->stringValue());
+    }
+};
+
+// This test checks if global defaults are properly set for D2.
+TEST_F(D2SimpleParserTest, globalD2Defaults) {
+
+    ElementPtr empty = isc::d2::test::parseJSON("{ }");
+    size_t num = 0;
+
+    EXPECT_NO_THROW(num = D2SimpleParser::setAllDefaults(empty));
+
+    // We expect 5 parameters to be inserted.
+    EXPECT_EQ(num, 5);
+
+    // Let's go over all parameters we have defaults for.
+    BOOST_FOREACH(SimpleDefault deflt, D2SimpleParser::D2_GLOBAL_DEFAULTS) {
+        ConstElementPtr x;
+        ASSERT_NO_THROW(x = empty->get(deflt.name_));
+        
+        EXPECT_TRUE(x); 
+        if (x) {
+            if (deflt.type_ == Element::integer) {
+                checkIntegerValue(x, deflt);
+            } else if (deflt.type_ == Element::boolean) {
+                checkBooleanValue(x, deflt);
+            } else if (deflt.type_ == Element::string) {
+                checkStringValue(x, deflt);
+            } else {
+                // add them if we need to. Like what do you if it's a map?
+                ADD_FAILURE() << "default type not supported:" << deflt.name_
+                            << " ,type: " << deflt.type_;
+            } 
+        }
+    }
+}
+
+};
+
diff --git a/src/bin/d2/tests/parser_unittest.cc b/src/bin/d2/tests/parser_unittest.cc
new file mode 100644 (file)
index 0000000..1469171
--- /dev/null
@@ -0,0 +1,586 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <gtest/gtest.h>
+#include <cc/data.h>
+#include <d2/parser_context.h>
+#include <d2/tests/parser_unittest.h>
+#include <testutils/io_utils.h>
+
+using namespace isc::data;
+using namespace std;
+
+namespace isc {
+namespace d2 {
+namespace test {
+
+/// @brief compares two JSON trees
+///
+/// If differences are discovered, gtest failure is reported (using EXPECT_EQ)
+///
+/// @param a first to be compared
+/// @param b second to be compared
+void compareJSON(ConstElementPtr a, ConstElementPtr b) {
+    ASSERT_TRUE(a);
+    ASSERT_TRUE(b);
+    EXPECT_EQ(a->str(), b->str());
+}
+
+/// @brief Tests if the input string can be parsed with specific parser
+///
+/// The input text will be passed to bison parser of specified type.
+/// Then the same input text is passed to legacy JSON parser and outputs
+/// from both parsers are compared. The legacy comparison can be disabled,
+/// if the feature tested is not supported by the old parser (e.g.
+/// new comment styles)
+///
+/// @param txt text to be compared
+/// @param parser_type bison parser type to be instantiated
+/// @param compare whether to compare the output with legacy JSON parser
+void testParser(const std::string& txt, D2ParserContext::ParserType parser_type,
+    bool compare = true) {
+    ConstElementPtr test_json;
+
+    ASSERT_NO_THROW({
+            try {
+                D2ParserContext ctx;
+                test_json = ctx.parseString(txt, parser_type);
+            } catch (const std::exception &e) {
+                cout << "EXCEPTION: " << e.what() << endl;
+                throw;
+            }
+
+    });
+
+    if (!compare) {
+        return;
+    }
+
+    // Now compare if both representations are the same.
+    ElementPtr reference_json;
+    ASSERT_NO_THROW(reference_json = Element::fromJSON(txt, true));
+    compareJSON(reference_json, test_json);
+}
+
+// Generic JSON parsing tests
+TEST(ParserTest, mapInMap) {
+    string txt = "{ \"xyzzy\": { \"foo\": 123, \"baz\": 456 } }";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, listInList) {
+    string txt = "[ [ \"Britain\", \"Wales\", \"Scotland\" ], "
+                 "[ \"Pomorze\", \"Wielkopolska\", \"Tatry\"] ]";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, nestedMaps) {
+    string txt = "{ \"europe\": { \"UK\": { \"London\": { \"street\": \"221B Baker\" }}}}";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, nestedLists) {
+    string txt = "[ \"half\", [ \"quarter\", [ \"eighth\", [ \"sixteenth\" ]]]]";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, listsInMaps) {
+    string txt = "{ \"constellations\": { \"orion\": [ \"rigel\", \"betelguese\" ], "
+                    "\"cygnus\": [ \"deneb\", \"albireo\"] } }";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, mapsInLists) {
+    string txt = "[ { \"body\": \"earth\", \"gravity\": 1.0 },"
+                 " { \"body\": \"mars\", \"gravity\": 0.376 } ]";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, types) {
+    string txt = "{ \"string\": \"foo\","
+                   "\"integer\": 42,"
+                   "\"boolean\": true,"
+                   "\"map\": { \"foo\": \"bar\" },"
+                   "\"list\": [ 1, 2, 3 ],"
+                   "\"null\": null }";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+TEST(ParserTest, keywordJSON) {
+    string txt = "{ \"name\": \"user\","
+                   "\"type\": \"password\","
+                   "\"user\": \"name\","
+                   "\"password\": \"type\" }";
+    testParser(txt, D2ParserContext::PARSER_JSON);
+}
+
+// PARSER_DHCPDDNS parser tests
+TEST(ParserTest, keywordDhcpDdns) {
+    string txt =
+        "{ \"DhcpDdns\" : \n"
+           "{ \n"
+            " \"ip-address\": \"192.168.77.1\", \n"
+            " \"port\": 777 , \n "
+            " \"ncr-protocol\": \"UDP\", \n"
+            "\"tsig-keys\": [], \n"
+            "\"forward-ddns\" : {}, \n"
+            "\"reverse-ddns\" : {} \n"
+            "} \n"
+         "} \n";
+     testParser(txt, D2ParserContext::PARSER_DHCPDDNS);
+}
+
+TEST(ParserTest, keywordDhcp6) {
+     string txt = "{ \"Dhcp6\": { \"interfaces-config\": {"
+                  " \"interfaces\": [ \"type\", \"htype\" ] },\n"
+                  "\"preferred-lifetime\": 3000,\n"
+                  "\"rebind-timer\": 2000, \n"
+                  "\"renew-timer\": 1000, \n"
+                  "\"subnet6\": [ { "
+                  "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+                  "    \"subnet\": \"2001:db8:1::/48\", "
+                  "    \"interface\": \"test\" } ],\n"
+                   "\"valid-lifetime\": 4000 } }";
+     testParser(txt, D2ParserContext::PARSER_DHCPDDNS);
+}
+
+TEST(ParserTest, keywordDhcp4) {
+    string txt = "{ \"Dhcp4\": { \"interfaces-config\": {"
+                  " \"interfaces\": [ \"type\", \"htype\" ] },\n"
+                  "\"rebind-timer\": 2000, \n"
+                  "\"renew-timer\": 1000, \n"
+                  "\"subnet4\": [ { "
+                  "  \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ],"
+                  "  \"subnet\": \"192.0.2.0/24\", "
+                  "  \"interface\": \"test\" } ],\n"
+                   "\"valid-lifetime\": 4000 } }";
+     testParser(txt, D2ParserContext::PARSER_DHCPDDNS);
+}
+
+TEST(ParserTest, Logging) {
+    string txt = "{ \"Logging\": { \n"
+                 "    \"loggers\": [ \n"
+                 "        { \n"
+                 "            \"name\": \"kea-dhcp6\", \n"
+                 "            \"output_options\": [ \n"
+                 "                { \n"
+                 "                    \"output\": \"stdout\" \n"
+                 "                } \n"
+                 "            ], \n"
+                 "            \"debuglevel\": 0, \n"
+                 "            \"severity\": \"INFO\" \n"
+                 "        } \n"
+                 "    ] }\n"
+                 "} \n";
+     testParser(txt, D2ParserContext::PARSER_DHCPDDNS);
+}
+
+
+// Tests if bash (#) comments are supported. That's the only comment type that
+// was supported by the old parser.
+TEST(ParserTest, bashComments) {
+    string txt= "{ \"Dhcp6\": { \"interfaces-config\": {"
+                "  \"interfaces\": [ \"*\" ]"
+                "},\n"
+                "\"preferred-lifetime\": 3000,\n"
+                "# this is a comment\n"
+                "\"rebind-timer\": 2000, \n"
+                "# lots of comments here\n"
+                "# and here\n"
+                "\"renew-timer\": 1000, \n"
+                "\"subnet6\": [ { "
+                "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+                "    \"subnet\": \"2001:db8:1::/48\", "
+                "    \"interface\": \"eth0\""
+                " } ],"
+                "\"valid-lifetime\": 4000 } }";
+    testParser(txt, D2ParserContext::PARSER_DHCPDDNS);
+}
+
+// Tests if C++ (//) comments can start anywhere, not just in the first line.
+TEST(ParserTest, cppComments) {
+    string txt= "{ \"Dhcp6\": { \"interfaces-config\": {"
+                "  \"interfaces\": [ \"*\" ]"
+                "},\n"
+                "\"preferred-lifetime\": 3000, // this is a comment \n"
+                "\"rebind-timer\": 2000, // everything after // is ignored\n"
+                "\"renew-timer\": 1000, // this will be ignored, too\n"
+                "\"subnet6\": [ { "
+                "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+                "    \"subnet\": \"2001:db8:1::/48\", "
+                "    \"interface\": \"eth0\""
+                " } ],"
+                "\"valid-lifetime\": 4000 } }";
+    testParser(txt, D2ParserContext::PARSER_DHCPDDNS, false);
+}
+
+// Tests if bash (#) comments can start anywhere, not just in the first line.
+TEST(ParserTest, bashCommentsInline) {
+    string txt= "{ \"Dhcp6\": { \"interfaces-config\": {"
+                "  \"interfaces\": [ \"*\" ]"
+                "},\n"
+                "\"preferred-lifetime\": 3000, # this is a comment \n"
+                "\"rebind-timer\": 2000, # everything after # is ignored\n"
+                "\"renew-timer\": 1000, # this will be ignored, too\n"
+                "\"subnet6\": [ { "
+                "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+                "    \"subnet\": \"2001:db8:1::/48\", "
+                "    \"interface\": \"eth0\""
+                " } ],"
+                "\"valid-lifetime\": 4000 } }";
+    testParser(txt, D2ParserContext::PARSER_DHCPDDNS, false);
+}
+
+// Tests if multi-line C style comments are handled correctly.
+TEST(ParserTest, multilineComments) {
+    string txt= "{ \"Dhcp6\": { \"interfaces-config\": {"
+                "  \"interfaces\": [ \"*\" ]"
+                "},\n"
+                "\"preferred-lifetime\": 3000, /* this is a C style comment\n"
+                "that\n can \n span \n multiple \n lines */ \n"
+                "\"rebind-timer\": 2000,\n"
+                "\"renew-timer\": 1000, \n"
+                "\"subnet6\": [ { "
+                "    \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
+                "    \"subnet\": \"2001:db8:1::/48\", "
+                "    \"interface\": \"eth0\""
+                " } ],"
+                "\"valid-lifetime\": 4000 } }";
+    testParser(txt, D2ParserContext::PARSER_DHCPDDNS, false);
+}
+
+/// @brief Loads specified example config file
+///
+/// This test loads specified example file twice: first, using the legacy
+/// JSON file and then second time using bison parser. Two created Element
+/// trees are then compared. The input is decommented before it is passed
+/// to legacy parser (as legacy support for comments is very limited).
+///
+/// @param fname name of the file to be loaded
+void testFile(const std::string& fname) {
+    ElementPtr reference_json;
+    ConstElementPtr test_json;
+
+    string decommented = dhcp::test::decommentJSONfile(fname);
+    EXPECT_NO_THROW(reference_json = Element::fromJSONFile(decommented, true));
+
+    // remove the temporary file
+    EXPECT_NO_THROW(::remove(decommented.c_str()));
+
+    EXPECT_NO_THROW(
+    try {
+        D2ParserContext ctx;
+        test_json = ctx.parseFile(fname, D2ParserContext::PARSER_DHCPDDNS);
+    } catch (const std::exception &x) {
+        cout << "EXCEPTION: " << x.what() << endl;
+        throw;
+    });
+
+    ASSERT_TRUE(reference_json);
+    ASSERT_TRUE(test_json);
+
+    compareJSON(reference_json, test_json);
+}
+
+// This test loads all available existing files. Each config is loaded
+// twice: first with the existing Element::fromJSONFile() and then
+// the second time with D2Parser. Both JSON trees are then compared.
+TEST(ParserTest, file) {
+    vector<string> configs;
+    configs.push_back("sample1.json");
+    configs.push_back("template.json");
+
+    for (int i = 0; i<configs.size(); i++) {
+        testFile(string(CFG_EXAMPLES) + "/" + configs[i]);
+    }
+}
+
+/// @brief Tests error conditions in D2Parser
+///
+/// @param txt text to be parsed
+/// @param parser_type type of the parser to be used in the test
+/// @param msg expected content of the exception
+void testError(const std::string& txt,
+               D2ParserContext::ParserType parser_type,
+               const std::string& msg)
+{
+    try {
+        D2ParserContext ctx;
+        ConstElementPtr parsed = ctx.parseString(txt, parser_type);
+        FAIL() << "Expected D2ParseError but nothing was raised (expected: "
+               << msg << ")";
+    }
+    catch (const D2ParseError& ex) {
+        EXPECT_EQ(msg, ex.what());
+    }
+    catch (...) {
+        FAIL() << "Expected D2ParseError but something else was raised";
+    }
+}
+
+// Verify that error conditions are handled correctly.
+TEST(ParserTest, errors) {
+    // no input
+    testError("", D2ParserContext::PARSER_JSON,
+              "<string>:1.1: syntax error, unexpected end of file");
+    testError(" ", D2ParserContext::PARSER_JSON,
+              "<string>:1.2: syntax error, unexpected end of file");
+    testError("\n", D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file");
+    testError("\t", D2ParserContext::PARSER_JSON,
+              "<string>:1.2: syntax error, unexpected end of file");
+    testError("\r", D2ParserContext::PARSER_JSON,
+              "<string>:1.2: syntax error, unexpected end of file");
+
+    // comments
+    testError("# nothing\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file");
+    testError(" #\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file");
+    testError("// nothing\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file");
+    testError("/* nothing */\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file");
+    testError("/* no\nthing */\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:3.1: syntax error, unexpected end of file");
+    testError("/* no\nthing */\n\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:4.1: syntax error, unexpected end of file");
+    testError("/* nothing\n",
+              D2ParserContext::PARSER_JSON,
+              "Comment not closed. (/* in line 1");
+    testError("\n\n\n/* nothing\n",
+              D2ParserContext::PARSER_JSON,
+              "Comment not closed. (/* in line 4");
+    testError("{ /* */*/ }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3-8: Invalid character: *");
+    testError("{ /* // *// }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3-11: Invalid character: /");
+    testError("{ /* // *///  }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:2.1: syntax error, unexpected end of file, "
+              "expecting }");
+
+    // includes
+    testError("<?\n",
+              D2ParserContext::PARSER_JSON,
+              "Directive not closed.");
+    testError("<?include\n",
+              D2ParserContext::PARSER_JSON,
+              "Directive not closed.");
+    string file = string(CFG_EXAMPLES) + "/" + "sample1.json";
+    testError("<?include \"" + file + "\"\n",
+              D2ParserContext::PARSER_JSON,
+              "Directive not closed.");
+    testError("<?include \"/foo/bar\" ?>/n",
+              D2ParserContext::PARSER_JSON,
+              "Can't open include file /foo/bar");
+
+    // JSON keywords
+    testError("{ \"foo\": True }",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.10-13: JSON true reserved keyword is lower case only");
+    testError("{ \"foo\": False }",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.10-14: JSON false reserved keyword is lower case only");
+    testError("{ \"foo\": NULL }",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.10-13: JSON null reserved keyword is lower case only");
+    testError("{ \"foo\": Tru }",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.10: Invalid character: T");
+    testError("{ \"foo\": nul }",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.10: Invalid character: n");
+
+    // numbers
+    testError("123",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-3: syntax error, unexpected integer, "
+              "expecting {");
+    testError("-456",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-4: syntax error, unexpected integer, "
+              "expecting {");
+    testError("-0001",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-5: syntax error, unexpected integer, "
+              "expecting {");
+    testError("1234567890123456789012345678901234567890",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-40: Failed to convert "
+              "1234567890123456789012345678901234567890"
+              " to an integer.");
+    testError("-3.14e+0",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-8: syntax error, unexpected floating point, "
+              "expecting {");
+    testError("1e50000",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-7: Failed to convert 1e50000 "
+              "to a floating point.");
+
+    // strings
+    testError("\"aabb\"",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-6: syntax error, unexpected constant string, "
+              "expecting {");
+    testError("{ \"aabb\"err",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.9: Invalid character: e");
+    testError("{ err\"aabb\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3: Invalid character: e");
+    testError("\"a\n\tb\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-6: Invalid control in \"a\n\tb\"");
+    testError("\"a\\n\\tb\"",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1-8: syntax error, unexpected constant string, "
+              "expecting {");
+    testError("\"a\\x01b\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-8: Bad escape in \"a\\x01b\"");
+    testError("\"a\\u0162\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-9: Unsupported unicode escape in \"a\\u0162\"");
+    testError("\"a\\u062z\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-9: Bad escape in \"a\\u062z\"");
+    testError("\"abc\\\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1-6: Overflow escape in \"abc\\\"");
+
+    // from data_unittest.c
+    testError("\\a",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1: Invalid character: \\");
+    testError("\\",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1: Invalid character: \\");
+    testError("\\\"\\\"",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.1: Invalid character: \\");
+
+    // want a map
+    testError("[]\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1: syntax error, unexpected [, "
+              "expecting {");
+    testError("[]\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.1: syntax error, unexpected [, "
+              "expecting {");
+    testError("{ 123 }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3-5: syntax error, unexpected integer, "
+              "expecting }");
+    testError("{ 123 }\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.3-5: syntax error, unexpected integer");
+    testError("{ \"foo\" }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.9: syntax error, unexpected }, "
+              "expecting :");
+    testError("{ \"foo\" }\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.9: syntax error, unexpected }, expecting :");
+    testError("{ \"foo\":null }\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.3-7: got unexpected keyword "
+              "\"foo\" in toplevel map.");
+    testError("{ \"Dhcp6\" }\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:1.11: syntax error, unexpected }, "
+              "expecting :");
+    testError("{ \"Dhcp4\":[]\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:2.1: syntax error, unexpected end of file, "
+              "expecting \",\" or }");
+    testError("{}{}\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3: syntax error, unexpected {, "
+              "expecting end of file");
+
+    // bad commas
+    testError("{ , }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3: syntax error, unexpected \",\", "
+              "expecting }");
+    testError("{ , \"foo\":true }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.3: syntax error, unexpected \",\", "
+              "expecting }");
+    testError("{ \"foo\":true, }\n",
+              D2ParserContext::PARSER_JSON,
+              "<string>:1.15: syntax error, unexpected }, "
+              "expecting constant string");
+
+    // bad type
+    testError("{ \"DhcpDdns\":{\n"
+              "  \"dns-server-timeout\":false }}\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:2.24-28: syntax error, unexpected boolean, "
+              "expecting integer");
+
+    // unknown keyword
+    testError("{ \"DhcpDdns\":{\n"
+              " \"totally-bogus\":600 }}\n",
+              D2ParserContext::PARSER_DHCPDDNS,
+              "<string>:2.2-16: got unexpected keyword "
+              "\"totally-bogus\" in DhcpDdns map.");
+}
+
+// Check unicode escapes
+TEST(ParserTest, unicodeEscapes) {
+    ConstElementPtr result;
+    string json;
+
+    // check we can reread output
+    for (char c = -128; c < 127; ++c) {
+        string ins(" ");
+        ins[1] = c;
+        ConstElementPtr e(new StringElement(ins));
+        json = e->str();
+        ASSERT_NO_THROW(
+        try {
+            D2ParserContext ctx;
+            result = ctx.parseString(json, D2ParserContext::PARSER_JSON);
+        } catch (const std::exception &x) {
+            cout << "EXCEPTION: " << x.what() << endl;
+            throw;
+        });
+        ASSERT_EQ(Element::string, result->getType());
+        EXPECT_EQ(ins, result->stringValue());
+    }
+}
+
+// This test checks that all representations of a slash is recognized properly.
+TEST(ParserTest, unicodeSlash) {
+    // check the 4 possible encodings of solidus '/'
+    ConstElementPtr result;
+    string json = "\"/\\/\\u002f\\u002F\"";
+    ASSERT_NO_THROW(
+    try {
+        D2ParserContext ctx;
+        result = ctx.parseString(json, D2ParserContext::PARSER_JSON);
+    } catch (const std::exception &x) {
+        cout << "EXCEPTION: " << x.what() << endl;
+        throw;
+    });
+    ASSERT_EQ(Element::string, result->getType());
+    EXPECT_EQ("////", result->stringValue());
+}
+
+};
+};
+};
diff --git a/src/bin/d2/tests/parser_unittest.h b/src/bin/d2/tests/parser_unittest.h
new file mode 100644 (file)
index 0000000..8db80ad
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef PARSER_UNITTEST_H
+#define PARSER_UNITTEST_H
+
+#include <gtest/gtest.h>
+#include <cc/data.h>
+#include <d2/parser_context.h>
+#include <testutils/io_utils.h>
+
+using namespace isc::data;
+using namespace std;
+
+namespace isc {
+namespace d2 {
+namespace test {
+
+/// @brief Runs parser in JSON mode, useful for parser testing
+///
+/// @param in string to be parsed
+/// @return ElementPtr structure representing parsed JSON
+inline isc::data::ElementPtr
+parseJSON(const std::string& in)
+{
+    isc::d2::D2ParserContext ctx;
+    return (ctx.parseString(in, isc::d2::D2ParserContext::PARSER_JSON));
+}
+
+};
+};
+};
+
+#endif // PARSER_UNITTEST_H
index 1969396f4542c7363606fdbad41fe034dd24e067..7e3b5b03f6c994d600ccf7b519c54658b8dc22a0 100644 (file)
@@ -9,13 +9,16 @@
 # Each test entry consists of:
 #
 # description - text describing the test (optional)
-# should-fail - indicates whether parsing is expected to fail, defaults to
-#               false
+# syntax-error - syntax error the JSON parsing should emit for this test
+#               defaults to "" = no error
+# logic-error - indicates whether a post-JSON parsing logic error should occur
+#               defaults to false
 # data {} - Configuration text to submit for parsing.
 #
 # The vast majority of the tests in this file are invalid and are expected
-# to fail.  There are some that should succeed and are used more or less
-# as sanity checks.
+# to fail either as a syntax error caught by the JSON parser or a logic error
+# caught during element processing. There are some that should succeed and are
+# used more or less as sanity checks.
 
 { "test-list" : [
 #-----
@@ -24,7 +27,7 @@
 # as well as validating this as the smallest config which makes writing
 # permutations easier.
 "description" : "D2 smallest, valid config",
-"should-fail" : false,
+"logic-error" : false,
 "data" :
     {
     "forward-ddns" : {},
@@ -36,7 +39,7 @@
 #-----
 ,{
 "description" : "D2 missing forward-ddns map",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "reverse-ddns" : {},
@@ -47,7 +50,7 @@
 #-----
 ,{
 "description" : "D2 missing reverse-ddns map",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
@@ -59,7 +62,7 @@
 #-----
 ,{
 "description" : "D2 missing tsig-keys list",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
@@ -70,7 +73,7 @@
 #-----
 ,{
 "description" : "D2 unknown scalar",
-"should-fail" : true,
+"syntax-error" : "<string>:1.3-16: got unexpected keyword \"bogus-scalar\" in DhcpDdns map.",
 "data" :
     {
     "bogus-scalar" : true,
@@ -83,7 +86,7 @@
 #-----
 ,{
 "description" : "D2 unknown map",
-"should-fail" : true,
+"syntax-error" : "<string>:1.3-13: got unexpected keyword \"bogus-map\" in DhcpDdns map.",
 "data" :
     {
     "bogus-map" : {},
@@ -96,7 +99,7 @@
 #-----
 ,{
 "description" : "D2 unknown list",
-"should-fail" : true,
+"syntax-error" : "<string>:1.3-14: got unexpected keyword \"bogus-list\" in DhcpDdns map.",
 "data" :
     {
     "bogus-list" : [],
 #-----
 ,{
 "description" : "D2Params.ip-address invalid value",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "ip-address" : "bogus",
 #-----
 ,{
 "description" : "D2Params.port can't be 0",
-"should-fail" : true,
+"syntax-error" : "<string>:1.33: port must be greater than zero",
 "data" :
     {
     "port" : 0,
 #-----
 ,{
 "description" : "D2Params.port, non numeric",
-"should-fail" : true,
+"syntax-error" : "<string>:1.33-39: syntax error, unexpected constant string, expecting integer",
 "data" :
     {
     "port" : "bogus",
 #-----
 ,{
 "description" : "D2Params.dns-server-timeout can't be 0",
-"should-fail" : true,
+"syntax-error" : "<string>:1.25: dns-server-timeout must be greater than zero",
 "data" :
     {
     "dns-server-timeout" : 0,
 #-----
 ,{
 "description" : "D2Params.dns-server-timeout, non numeric",
-"should-fail" : true,
+"syntax-error" : "<string>:1.25-31: syntax error, unexpected constant string, expecting integer",
 "data" :
     {
     "dns-server-timeout" : "bogus",
 #-----
 ,{
 "description" : "D2Params.ncr-protocol, unsupported TCP",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "ncr-protocol" : "TCP",
 #-----
 ,{
 "description" : "D2Params.ncr-protocol, invalid value",
-"should-fail" : true,
+"syntax-error" : "<string>:1.41-47: syntax error, unexpected constant string, expecting UDP or TCP",
 "data" :
     {
     "ncr-protocol" : "bogus",
 #-----
 ,{
 "description" : "D2Params.ncr-format, invalid value",
-"should-fail" : true,
+"syntax-error" : "<string>:1.39-45: syntax error, unexpected constant string, expecting JSON",
 "data" :
     {
     "ncr-format" : "bogus",
 #-----
 ,{
 "description" : "D2.tsig-keys, missing key name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, blank key name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, duplicate key name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.tsig-keys, algorithm tests
 ,{
 "description" : "D2.tsig-keys, missing algorithm",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, blank algorithm",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid algorithm",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid digest-bits",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-MD5",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA1",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA224",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA256",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA384",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, too small truncated HMAC-SHA512",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.tsig-keys, secret tests
 ,{
 "description" : "D2.tsig-keys, missing secret",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, blank secret",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.tsig-keys, invalid secret",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #------
 ,{
 "description" : "D2.forward-ddns, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #------
 ,{
 "description" : "D2.forward-ddns, duplicate domain",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #----- D2.forward-ddns.dhcp-ddns  tests
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #----- D2.forward-ddns.dhcp-ddns.name tests
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns, no name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns, blank name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #------ "D2.forward-ddns.dhcp-ddns, key-name tests
 ,{
 "description" : "D2.forward-ddns, no matching key name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #----- D2.forward-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers, no servers",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #----- D2.forward-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers.hostname unsupported",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers.ip-address invalid address ",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #-----
 ,{
 "description" : "D2.forward-ddns.dhcp-ddns.dns-servers.port cannot be 0 ",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" :
 #------
 ,{
 "description" : "D2.reverse-ddns, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #------
 ,{
 "description" : "D2.reverse-ddns, duplicate domain",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.reverse-ddns.dhcp-ddns  tests
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.reverse-ddns.dhcp-ddns.name tests
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns, no name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns, blank name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #------ "D2.reverse-ddns.dhcp-ddns, key-name tests
 ,{
 "description" : "D2.reverse-ddns, no matching key name",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.reverse-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers, no servers",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #----- D2.reverse-ddns.dhcp-ddns.dns-servers tests
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers, unknown parameter",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers.hostname unsupported",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers.ip-address invalid value",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
 #-----
 ,{
 "description" : "D2.reverse-ddns.dhcp-ddns.dns-servers.port cannot be 0 ",
-"should-fail" : true,
+"logic-error" : true,
 "data" :
     {
     "forward-ddns" : {},
index 13e75d7a8b54f76be8deec35899c90a67e4b639a..95feb6adee6107e3a3a4fa9ff7c89e82525f2235 100644 (file)
@@ -186,7 +186,7 @@ public:
         if ((position_.file_ != "") ||          \
             (position_.line_ != 0) ||           \
             (position_.pos_ != 0)) {            \
-            msg_ += " in " + position_.str();   \
+            msg_ += " in (" + position_.str() + ")";   \
         }                                       \
         isc_throw(TypeError, msg_);             \
     }
index 6c0d74a474e709c202da895c20626b7b54184929..91c17245cb9f2696b5ef7cc9e2667c807813e40e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -101,8 +101,16 @@ size_t SimpleParser::setDefaults(isc::data::ElementPtr scope,
             break;
         }
         case Element::integer: {
-            int int_value = boost::lexical_cast<int>(def_value.value_);
-            x.reset(new IntElement(int_value, pos));
+            try {
+                int int_value = boost::lexical_cast<int>(def_value.value_);
+                x.reset(new IntElement(int_value, pos));
+            }
+            catch (const std::exception& ex) {
+                isc_throw(BadValue, "Internal error. Integer value expected for: "
+                                    << def_value.name_ << ", value is: "
+                                    << def_value.value_ );
+            }
+
             break;
         }
         case Element::boolean: {