]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[master] Finishing merge of trac5106 (flex 2.6.2 compat)
authorFrancis Dupont <fdupont@isc.org>
Wed, 17 May 2017 14:49:59 +0000 (16:49 +0200)
committerFrancis Dupont <fdupont@isc.org>
Wed, 17 May 2017 14:49:59 +0000 (16:49 +0200)
1  2 
src/bin/agent/agent_lexer.ll
src/bin/d2/d2_lexer.ll
src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp6/dhcp6_lexer.ll
src/lib/eval/lexer.ll

index 8fa65374c2b37fd149002e6e2704392ca0f2c488,0000000000000000000000000000000000000000..b947a977853ec75a00bd3a0a08fbd80f209346b3
mode 100644,000000..100644
--- /dev/null
@@@ -1,695 -1,0 +1,697 @@@
- // Work around an incompatibility in flex (at least versions
- // 2.5.31 through 2.5.33): it generates code that does
- // not conform to C89.  See Debian bug 333231
- // <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.
 +/* 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/. */
 +
 +%{ /* -*- C++ -*- */
 +#include <cerrno>
 +#include <climits>
 +#include <cstdlib>
 +#include <string>
 +#include <agent/parser_context.h>
 +#include <asiolink/io_address.h>
 +#include <boost/lexical_cast.hpp>
 +#include <exceptions/exceptions.h>
 +#include <cc/dhcp_config_error.h>
 +
- // To avoid the call to exit... oops!
++/* Please avoid C++ style comments (// ... eol) as they break flex 2.6.2 */
++
++/* Work around an incompatibility in flex (at least versions
++   2.5.31 through 2.5.33): it generates code that does
++   not conform to C89.  See Debian bug 333231
++   <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
 +# undef yywrap
 +# define yywrap() 1
 +
 +namespace {
 +
 +bool start_token_flag = false;
 +
 +isc::agent::ParserContext::ParserType start_token_value;
 +unsigned int comment_start_line = 0;
 +
 +using namespace isc;
 +using isc::agent::AgentParser;
 +
 +};
 +
- // This code run each time a pattern is matched. It updates the location
- // by moving it ahead by yyleng bytes. yyleng specifies the length of the
- // currently matched token.
++/* To avoid the call to exit... oops! */
 +#define YY_FATAL_ERROR(msg) isc::agent::ParserContext::fatal(msg)
 +%}
 +
 +/* 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
 +   implementation that always returns 1 anyway. */
 +%option noyywrap
 +
 +/* nounput simplifies the lexer, by removing support for putting a character
 +   back into the input stream. We never use such capability anyway. */
 +%option nounput
 +
 +/* batch means that we'll never use the generated lexer interactively. */
 +%option batch
 +
 +/* avoid to get static global variables to remain with C++. */
 +/* in last resort %option reentrant */
 +
 +/* Enables debug mode. To see the debug messages, one needs to also set
 +   yy_flex_debug to 1, then the debug messages will be printed on stderr. */
 +%option debug
 +
 +/* I have no idea what this option does, except it was specified in the bison
 +   examples and Postgres folks added it to remove gcc 4.3 warnings. Let's
 +   be on the safe side and keep it. */
 +%option noinput
 +
 +%x COMMENT
 +%x DIR_ENTER DIR_INCLUDE DIR_EXIT
 +
 +/* These are not token expressions yet, just convenience expressions that
 +   can be used during actual token definitions. Note some can match
 +   incorrect inputs (e.g., IP addresses) which must be checked. */
 +int   \-?[0-9]+
 +blank [ \t\r]
 +
 +UnicodeEscapeSequence           u[0-9A-Fa-f]{4}
 +JSONEscapeCharacter             ["\\/bfnrt]
 +JSONEscapeSequence              {JSONEscapeCharacter}|{UnicodeEscapeSequence}
 +JSONStandardCharacter           [^\x00-\x1f"\\]
 +JSONStringCharacter             {JSONStandardCharacter}|\\{JSONEscapeSequence}
 +JSONString                      \"{JSONStringCharacter}*\"
 +
 +/* for errors */
 +
 +BadUnicodeEscapeSequence        u[0-9A-Fa-f]{0,3}[^0-9A-Fa-f]
 +BadJSONEscapeSequence           [^"\\/bfnrtu]|{BadUnicodeEscapeSequence}
 +ControlCharacter                [\x00-\x1f]
 +ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 +
 +%{
-     // This part of the code is copied over to the verbatim to the top
-     // of the generated yylex function. Explanation:
-     // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html
++/* This code run each time a pattern is matched. It updates the location
++   by moving it ahead by yyleng bytes. yyleng specifies the length of the
++   currently matched token. */
 +#define YY_USER_ACTION  driver.loc_.columns(yyleng);
 +%}
 +
 +%%
 +
 +%{
-     // Code run each time yylex is called.
++    /* This part of the code is copied over to the verbatim to the top
++       of the generated yylex function. Explanation:
++       http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html */
 +
-     // We currently have 3 points of entries defined:
-     // START_JSON - which expects any valid JSON
-     // START_AGENT - which expects full configuration (with outer map and Control-agent
-     //               object in it.
-     // START_SUB_AGENT - which expects only content of the Control-agent, this is
-     //                   primarily useful for testing.
++    /* Code run each time yylex is called. */
 +    driver.loc_.step();
 +
-     // Include directive.
++    /* We currently have 3 points of entries defined:
++       START_JSON - which expects any valid JSON
++       START_AGENT - which expects full configuration (with outer map and Control-agent
++                     object in it.
++       START_SUB_AGENT - which expects only content of the Control-agent, this is
++                         primarily useful for testing. */
 +    if (start_token_flag) {
 +        start_token_flag = false;
 +        switch (start_token_value) {
 +        case ParserContext::PARSER_JSON:
 +        default:
 +            return isc::agent::AgentParser::make_START_JSON(driver.loc_);
 +        case ParserContext::PARSER_AGENT:
 +            return isc::agent::AgentParser::make_START_AGENT(driver.loc_);
 +        case ParserContext::PARSER_SUB_AGENT:
 +            return isc::agent::AgentParser::make_START_SUB_AGENT(driver.loc_);
 +        }
 +    }
 +%}
 +
 +#.* ;
 +
 +"//"(.*) ;
 +
 +"/*" {
 +  BEGIN(COMMENT);
 +  comment_start_line = driver.loc_.end.line;;
 +}
 +
 +<COMMENT>"*/" BEGIN(INITIAL);
 +<COMMENT>. ;
 +<COMMENT><<EOF>> {
 +    isc_throw(ParseError, "Comment not closed. (/* in line " << comment_start_line);
 +}
 +
 +"<?" BEGIN(DIR_ENTER);
 +<DIR_ENTER>"include" BEGIN(DIR_INCLUDE);
 +<DIR_INCLUDE>\"([^\"\n])+\" {
-     // Extract the filename.
++    /* Include directive. */
 +
-     // Ok, we found a with space. Let's ignore it and update loc variable.
++    /* Extract the filename. */
 +    std::string tmp(yytext+1);
 +    tmp.resize(tmp.size() - 1);
 +
 +    driver.includeFile(tmp);
 +}
 +<DIR_ENTER,DIR_INCLUDE,DIR_EXIT><<EOF>> {
 +    isc_throw(ParseError, "Directive not closed.");
 +}
 +<DIR_EXIT>"?>" BEGIN(INITIAL);
 +
 +
 +<*>{blank}+   {
-     // Newline found. Let's update the location and continue.
++    /* Ok, we found a with space. Let's ignore it and update loc variable. */
 +    driver.loc_.step();
 +}
 +
 +<*>[\n]+      {
-     // 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.
-     // for 'foo' we should get foo
++    /* Newline found. Let's update the location and continue. */
 +    driver.loc_.lines(yyleng);
 +    driver.loc_.step();
 +}
 +
 +
 +\"Control-agent\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONFIG:
 +        return AgentParser::make_CONTROL_AGENT(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("Control-agent", driver.loc_);
 +    }
 +}
 +
 +\"http-host\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::AGENT:
 +        return AgentParser::make_HTTP_HOST(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("http-host", driver.loc_);
 +    }
 +}
 +
 +\"http-port\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::AGENT:
 +        return AgentParser::make_HTTP_PORT(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("http-port", driver.loc_);
 +    }
 +}
 +
 +\"control-sockets\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::AGENT:
 +        return AgentParser::make_CONTROL_SOCKETS(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("control-sockets", driver.loc_);
 +    }
 +}
 +
 +\"dhcp4-server\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONTROL_SOCKETS:
 +        return AgentParser::make_DHCP4_SERVER(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("dhcp4-server", driver.loc_);
 +    }
 +}
 +
 +\"dhcp6-server\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONTROL_SOCKETS:
 +        return AgentParser::make_DHCP6_SERVER(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("dhcp6-server", driver.loc_);
 +    }
 +}
 +
 +\"d2-server\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONTROL_SOCKETS:
 +        return AgentParser::make_D2_SERVER(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("d2-server", driver.loc_);
 +    }
 +}
 +
 +\"socket-name\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::SERVER:
 +        return AgentParser::make_SOCKET_NAME(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("socket-name", driver.loc_);
 +    }
 +}
 +
 +\"socket-type\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::SERVER:
 +        return AgentParser::make_SOCKET_TYPE(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("socket-type", driver.loc_);
 +    }
 +}
 +
 +\"unix\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::SOCKET_TYPE:
 +        return AgentParser::make_UNIX(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("unix", driver.loc_);
 +    }
 +}
 +
 +\"hooks-libraries\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::AGENT:
 +        return AgentParser::make_HOOKS_LIBRARIES(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("hooks-libraries", driver.loc_);
 +    }
 +}
 +
 +\"library\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::HOOKS_LIBRARIES:
 +        return AgentParser::make_LIBRARY(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("library", driver.loc_);
 +    }
 +}
 +
 +\"parameters\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::HOOKS_LIBRARIES:
 +        return AgentParser::make_PARAMETERS(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("parameters", driver.loc_);
 +    }
 +}
 +
 +\"Logging\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONFIG:
 +        return AgentParser::make_LOGGING(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("Logging", driver.loc_);
 +    }
 +}
 +
 +\"loggers\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::LOGGING:
 +        return AgentParser::make_LOGGERS(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("loggers", driver.loc_);
 +    }
 +}
 +
 +\"name\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::LOGGERS:
 +        return AgentParser::make_NAME(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("name", driver.loc_);
 +    }
 +}
 +
 +\"output_options\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::LOGGERS:
 +        return AgentParser::make_OUTPUT_OPTIONS(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("output_options", driver.loc_);
 +    }
 +}
 +
 +\"output\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::OUTPUT_OPTIONS:
 +        return AgentParser::make_OUTPUT(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("output", driver.loc_);
 +    }
 +}
 +
 +\"flush\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::OUTPUT_OPTIONS:
 +        return AgentParser::make_FLUSH(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("flush", driver.loc_);
 +    }
 +}
 +
 +\"maxsize\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::OUTPUT_OPTIONS:
 +        return AgentParser::make_MAXSIZE(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("maxsize", driver.loc_);
 +    }
 +}
 +
 +\"maxver\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::OUTPUT_OPTIONS:
 +        return AgentParser::make_MAXVER(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("maxver", driver.loc_);
 +    }
 +}
 +
 +\"debuglevel\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::LOGGERS:
 +        return AgentParser::make_DEBUGLEVEL(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("debuglevel", driver.loc_);
 +    }
 +}
 +
 +\"severity\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::LOGGERS:
 +        return AgentParser::make_SEVERITY(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("severity", driver.loc_);
 +    }
 +}
 +
 +\"Dhcp4\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONFIG:
 +        return AgentParser::make_DHCP4(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("Dhcp4", driver.loc_);
 +    }
 +}
 +
 +\"Dhcp6\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONFIG:
 +        return AgentParser::make_DHCP6(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("Dhcp6", driver.loc_);
 +    }
 +}
 +
 +\"DhcpDdns\" {
 +    switch(driver.ctx_) {
 +    case ParserContext::CONFIG:
 +        return AgentParser::make_DHCPDDNS(driver.loc_);
 +    default:
 +        return AgentParser::make_STRING("DhcpDdns", driver.loc_);
 +    }
 +}
 +
 +{JSONString} {
-             // impossible condition
++    /* 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.
++       for 'foo' we should get foo */
 +    std::string raw(yytext+1);
 +    size_t len = raw.size() - 1;
 +    raw.resize(len);
 +    std::string decoded;
 +    decoded.reserve(len);
 +    for (size_t pos = 0; pos < len; ++pos) {
 +        int b = 0;
 +        char c = raw[pos];
 +        switch (c) {
 +        case '"':
-                 // impossible condition
++            /* impossible condition */
 +            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
 +        case '\\':
 +            ++pos;
 +            if (pos >= len) {
-                 // support only \u0000 to \u00ff
++                /* impossible condition */
 +                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
 +            }
 +            c = raw[pos];
 +            switch (c) {
 +            case '"':
 +            case '\\':
 +            case '/':
 +                decoded.push_back(c);
 +                break;
 +            case 'b':
 +                decoded.push_back('\b');
 +                break;
 +            case 'f':
 +                decoded.push_back('\f');
 +                break;
 +            case 'n':
 +                decoded.push_back('\n');
 +                break;
 +            case 'r':
 +                decoded.push_back('\r');
 +                break;
 +            case 't':
 +                decoded.push_back('\t');
 +                break;
 +            case 'u':
-                     // impossible condition
++                /* support only \u0000 to \u00ff */
 +                ++pos;
 +                if (pos + 4 > len) {
-                     // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_,
 +                                 "Overflow unicode escape in \"" + raw + "\"");
 +                }
 +                if ((raw[pos] != '0') || (raw[pos + 1] != '0')) {
 +                    driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
 +                }
 +                pos += 2;
 +                c = raw[pos];
 +                if ((c >= '0') && (c <= '9')) {
 +                    b = (c - '0') << 4;
 +                } else if ((c >= 'A') && (c <= 'F')) {
 +                    b = (c - 'A' + 10) << 4;
 +                } else if ((c >= 'a') && (c <= 'f')) {
 +                    b = (c - 'a' + 10) << 4;
 +                } else {
-                     // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
 +                }
 +                pos++;
 +                c = raw[pos];
 +                if ((c >= '0') && (c <= '9')) {
 +                    b |= c - '0';
 +                } else if ((c >= 'A') && (c <= 'F')) {
 +                    b |= c - 'A' + 10;
 +                } else if ((c >= 'a') && (c <= 'f')) {
 +                    b |= c - 'a' + 10;
 +                } else {
-                 // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
 +                }
 +                decoded.push_back(static_cast<char>(b & 0xff));
 +                break;
 +            default:
-                 // impossible condition
++                /* impossible condition */
 +                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
 +            }
 +            break;
 +        default:
 +            if ((c >= 0) && (c < 0x20)) {
-     // Bad string with a forbidden control character inside
++                /* impossible condition */
 +                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
 +            }
 +            decoded.push_back(c);
 +        }
 +    }
 +
 +    return AgentParser::make_STRING(decoded, driver.loc_);
 +}
 +
 +\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
-     // Bad string with a bad escape inside
++    /* Bad string with a forbidden control character inside */
 +    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
 +}
 +
 +\"{JSONStringCharacter}*\\{BadJSONEscapeSequence}[^\x00-\x1f"]*\" {
-     // Bad string with an open escape at the end
++    /* Bad string with a bad escape inside */
 +    driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
 +}
 +
 +\"{JSONStringCharacter}*\\\" {
-     // An integer was found.
++    /* Bad string with an open escape at the end */
 +    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
 +}
 +
 +"["    { return AgentParser::make_LSQUARE_BRACKET(driver.loc_); }
 +"]"    { return AgentParser::make_RSQUARE_BRACKET(driver.loc_); }
 +"{"    { return AgentParser::make_LCURLY_BRACKET(driver.loc_); }
 +"}"    { return AgentParser::make_RCURLY_BRACKET(driver.loc_); }
 +","    { return AgentParser::make_COMMA(driver.loc_); }
 +":"    { return AgentParser::make_COLON(driver.loc_); }
 +
 +{int} {
-         // In substring we want to use negative values (e.g. -1).
-         // In enterprise-id we need to use values up to 0xffffffff.
-         // To cover both of those use cases, we need at least
-         // int64_t.
++    /* An integer was found. */
 +    std::string tmp(yytext);
 +    int64_t integer = 0;
 +    try {
-     // The parser needs the string form as double conversion is no lossless
++        /* In substring we want to use negative values (e.g. -1).
++           In enterprise-id we need to use values up to 0xffffffff.
++           To cover both of those use cases, we need at least
++           int64_t. */
 +        integer = boost::lexical_cast<int64_t>(tmp);
 +    } catch (const boost::bad_lexical_cast &) {
 +        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
 +    }
 +
-     // A floating point was found.
++    /* The parser needs the string form as double conversion is no lossless */
 +    return AgentParser::make_INTEGER(integer, driver.loc_);
 +}
 +
 +[-+]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)? {
-         // fatal() throws an exception so this can't be reached
++    /* A floating point was found. */
 +    std::string tmp(yytext);
 +    double fp = 0.0;
 +    try {
 +        fp = boost::lexical_cast<double>(tmp);
 +    } catch (const boost::bad_lexical_cast &) {
 +        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
 +    }
 +
 +    return AgentParser::make_FLOAT(fp, driver.loc_);
 +}
 +
 +true|false {
 +    string tmp(yytext);
 +    return AgentParser::make_BOOLEAN(tmp == "true", driver.loc_);
 +}
 +
 +null {
 +   return AgentParser::make_NULL_TYPE(driver.loc_);
 +}
 +
 +(?i:true) driver.error (driver.loc_, "JSON true reserved keyword is lower case only");
 +
 +(?i:false) driver.error (driver.loc_, "JSON false reserved keyword is lower case only");
 +
 +(?i:null) driver.error (driver.loc_, "JSON null reserved keyword is lower case only");
 +
 +<*>.   driver.error (driver.loc_, "Invalid character: " + std::string(yytext));
 +
 +<<EOF>> {
 +    if (driver.states_.empty()) {
 +        return AgentParser::make_END(driver.loc_);
 +    }
 +    driver.loc_ = driver.locs_.back();
 +    driver.locs_.pop_back();
 +    driver.file_ = driver.files_.back();
 +    driver.files_.pop_back();
 +    if (driver.sfile_) {
 +        fclose(driver.sfile_);
 +        driver.sfile_ = 0;
 +    }
 +    if (!driver.sfiles_.empty()) {
 +        driver.sfile_ = driver.sfiles_.back();
 +        driver.sfiles_.pop_back();
 +    }
 +    agent__delete_buffer(YY_CURRENT_BUFFER);
 +    agent__switch_to_buffer(driver.states_.back());
 +    driver.states_.pop_back();
 +
 +    BEGIN(DIR_EXIT);
 +}
 +
 +%%
 +
 +using namespace isc::dhcp;
 +
 +void
 +ParserContext::scanStringBegin(const std::string& str, ParserType parser_type)
 +{
 +    start_token_flag = true;
 +    start_token_value = parser_type;
 +
 +    file_ = "<string>";
 +    sfile_ = 0;
 +    loc_.initialize(&file_);
 +    yy_flex_debug = trace_scanning_;
 +    YY_BUFFER_STATE buffer;
 +    buffer = agent__scan_bytes(str.c_str(), str.size());
 +    if (!buffer) {
 +        fatal("cannot scan string");
-     // See dhcp6_lexer.cc header for available definitions
++        /* fatal() throws an exception so this can't be reached */
 +    }
 +}
 +
 +void
 +ParserContext::scanFileBegin(FILE * f,
 +                              const std::string& filename,
 +                              ParserType parser_type)
 +{
 +    start_token_flag = true;
 +    start_token_value = parser_type;
 +
 +    file_ = filename;
 +    sfile_ = f;
 +    loc_.initialize(&file_);
 +    yy_flex_debug = trace_scanning_;
 +    YY_BUFFER_STATE buffer;
 +
-     // Close files
++    /* See agent_lexer.cc header for available definitions */
 +    buffer = agent__create_buffer(f, 65536 /*buffer size*/);
 +    if (!buffer) {
 +        fatal("cannot scan file " + filename);
 +    }
 +    agent__switch_to_buffer(buffer);
 +}
 +
 +void
 +ParserContext::scanEnd() {
 +    if (sfile_)
 +        fclose(sfile_);
 +    sfile_ = 0;
 +    static_cast<void>(agent_lex_destroy());
-     // Delete states
++    /* Close files */
 +    while (!sfiles_.empty()) {
 +        FILE* f = sfiles_.back();
 +        if (f) {
 +            fclose(f);
 +        }
 +        sfiles_.pop_back();
 +    }
- /// To avoid unused function error
++    /* Delete states */
 +    while (!states_.empty()) {
 +        agent__delete_buffer(states_.back());
 +        states_.pop_back();
 +    }
 +}
 +
 +void
 +ParserContext::includeFile(const std::string& filename) {
 +    if (states_.size() > 10) {
 +        fatal("Too many nested include.");
 +    }
 +
 +    FILE* f = fopen(filename.c_str(), "r");
 +    if (!f) {
 +        fatal("Can't open include file " + filename);
 +    }
 +    if (sfile_) {
 +        sfiles_.push_back(sfile_);
 +    }
 +    sfile_ = f;
 +    states_.push_back(YY_CURRENT_BUFFER);
 +    YY_BUFFER_STATE buffer;
 +    buffer = agent__create_buffer(f, 65536 /*buffer size*/);
 +    if (!buffer) {
 +        fatal( "Can't scan include file " + filename);
 +    }
 +    agent__switch_to_buffer(buffer);
 +    files_.push_back(file_);
 +    file_ = filename;
 +    locs_.push_back(loc_);
 +    loc_.initialize(&file_);
 +
 +    BEGIN(INITIAL);
 +}
 +
 +namespace {
-     // cppcheck-suppress unusedPrivateFunction
++/** To avoid unused function error */
 +class Dummy {
++    /* cppcheck-suppress unusedPrivateFunction */
 +    void dummy() { yy_fatal_error("Fix me: how to disable its definition?"); }
 +};
 +}
index 90a1caa45c3e261b318af82ab84bbaf6deb1ddc2,0000000000000000000000000000000000000000..11dff5b016535cc9a9742fb8dc6b70692dfe3a01
mode 100644,000000..100644
--- /dev/null
@@@ -1,760 -1,0 +1,762 @@@
- // Work around an incompatibility in flex (at least versions
- // 2.5.31 through 2.5.33): it generates code that does
- // not conform to C89.  See Debian bug 333231
- // <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.
 +/* 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/. */
 +
 +%{ /* -*- C++ -*- */
 +#include <cerrno>
 +#include <climits>
 +#include <cstdlib>
 +#include <string>
 +#include <d2/parser_context.h>
 +#include <asiolink/io_address.h>
 +#include <boost/lexical_cast.hpp>
 +#include <exceptions/exceptions.h>
 +
- // To avoid the call to exit... oops!
++/* Please avoid C++ style comments (// ... eol) as they break flex 2.6.2 */
++
++/* Work around an incompatibility in flex (at least versions
++   2.5.31 through 2.5.33): it generates code that does
++   not conform to C89.  See Debian bug 333231
++   <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
 +# undef yywrap
 +# define yywrap() 1
 +
 +namespace {
 +
 +bool start_token_flag = false;
 +
 +isc::d2::D2ParserContext::ParserType start_token_value;
 +unsigned int comment_start_line = 0;
 +
 +};
 +
- // This code run each time a pattern is matched. It updates the location
- // by moving it ahead by yyleng bytes. yyleng specifies the length of the
- // currently matched token.
++/* To avoid the call to exit... oops! */
 +#define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
 +%}
 +
 +/* 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
 +   implementation that always returns 1 anyway. */
 +%option noyywrap
 +
 +/* nounput simplifies the lexer, by removing support for putting a character
 +   back into the input stream. We never use such capability anyway. */
 +%option nounput
 +
 +/* batch means that we'll never use the generated lexer interactively. */
 +%option batch
 +
 +/* avoid to get static global variables to remain with C++. */
 +/* in last resort %option reentrant */
 +
 +/* Enables debug mode. To see the debug messages, one needs to also set
 +   yy_flex_debug to 1, then the debug messages will be printed on stderr. */
 +%option debug
 +
 +/* I have no idea what this option does, except it was specified in the bison
 +   examples and Postgres folks added it to remove gcc 4.3 warnings. Let's
 +   be on the safe side and keep it. */
 +%option noinput
 +
 +%x COMMENT
 +%x DIR_ENTER DIR_INCLUDE DIR_EXIT
 +
 +/* These are not token expressions yet, just convenience expressions that
 +   can be used during actual token definitions. Note some can match
 +   incorrect inputs (e.g., IP addresses) which must be checked. */
 +int   \-?[0-9]+
 +blank [ \t\r]
 +
 +UnicodeEscapeSequence           u[0-9A-Fa-f]{4}
 +JSONEscapeCharacter             ["\\/bfnrt]
 +JSONEscapeSequence              {JSONEscapeCharacter}|{UnicodeEscapeSequence}
 +JSONStandardCharacter           [^\x00-\x1f"\\]
 +JSONStringCharacter             {JSONStandardCharacter}|\\{JSONEscapeSequence}
 +JSONString                      \"{JSONStringCharacter}*\"
 +
 +/* for errors */
 +
 +BadUnicodeEscapeSequence        u[0-9A-Fa-f]{0,3}[^0-9A-Fa-f]
 +BadJSONEscapeSequence           [^"\\/bfnrtu]|{BadUnicodeEscapeSequence}
 +ControlCharacter                [\x00-\x1f]
 +ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 +
 +%{
-     // This part of the code is copied over to the verbatim to the top
-     // of the generated yylex function. Explanation:
-     // http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html
++/* This code run each time a pattern is matched. It updates the location
++   by moving it ahead by yyleng bytes. yyleng specifies the length of the
++   currently matched token. */
 +#define YY_USER_ACTION  driver.loc_.columns(yyleng);
 +%}
 +
 +%%
 +
 +%{
-     // Code run each time yylex is called.
++    /* This part of the code is copied over to the verbatim to the top
++       of the generated yylex function. Explanation:
++       http://www.gnu.org/software/bison/manual/html_node/Multiple-start_002dsymbols.html */
 +
-     // Include directive.
++    /* Code run each time yylex is called. */
 +    driver.loc_.step();
 +
 +    if (start_token_flag) {
 +        start_token_flag = false;
 +        switch (start_token_value) {
 +        case D2ParserContext::PARSER_JSON:
 +        default:
 +            return isc::d2::D2Parser::make_TOPLEVEL_JSON(driver.loc_);
 +        case D2ParserContext::PARSER_DHCPDDNS:
 +            return isc::d2::D2Parser::make_TOPLEVEL_DHCPDDNS(driver.loc_);
 +        case D2ParserContext::PARSER_SUB_DHCPDDNS:
 +            return isc::d2::D2Parser::make_SUB_DHCPDDNS(driver.loc_);
 +        case D2ParserContext::PARSER_TSIG_KEY:
 +            return isc::d2::D2Parser::make_SUB_TSIG_KEY(driver.loc_);
 +        case D2ParserContext::PARSER_TSIG_KEYS:
 +            return isc::d2::D2Parser::make_SUB_TSIG_KEYS(driver.loc_);
 +        case D2ParserContext::PARSER_DDNS_DOMAIN:
 +            return isc::d2::D2Parser::make_SUB_DDNS_DOMAIN(driver.loc_);
 +        case D2ParserContext::PARSER_DDNS_DOMAINS:
 +            return isc::d2::D2Parser::make_SUB_DDNS_DOMAINS(driver.loc_);
 +        case D2ParserContext::PARSER_DNS_SERVER:
 +            return isc::d2::D2Parser::make_SUB_DNS_SERVER(driver.loc_);
 +        }
 +    }
 +%}
 +
 +#.* ;
 +
 +"//"(.*) ;
 +
 +"/*" {
 +  BEGIN(COMMENT);
 +  comment_start_line = driver.loc_.end.line;;
 +}
 +
 +<COMMENT>"*/" BEGIN(INITIAL);
 +<COMMENT>. ;
 +<COMMENT><<EOF>> {
 +    isc_throw(D2ParseError, "Comment not closed. (/* in line " << comment_start_line);
 +}
 +
 +"<?" BEGIN(DIR_ENTER);
 +<DIR_ENTER>"include" BEGIN(DIR_INCLUDE);
 +<DIR_INCLUDE>\"([^\"\n])+\" {
-     // Extract the filename.
++    /* Include directive. */
 +
-     // Ok, we found a with space. Let's ignore it and update loc variable.
++    /* Extract the filename. */
 +    std::string tmp(yytext+1);
 +    tmp.resize(tmp.size() - 1);
 +
 +    driver.includeFile(tmp);
 +}
 +<DIR_ENTER,DIR_INCLUDE,DIR_EXIT><<EOF>> {
 +    isc_throw(D2ParseError, "Directive not closed.");
 +}
 +<DIR_EXIT>"?>" BEGIN(INITIAL);
 +
 +
 +<*>{blank}+   {
-     // Newline found. Let's update the location and continue.
++    /* Ok, we found a with space. Let's ignore it and update loc variable. */
 +    driver.loc_.step();
 +}
 +
 +<*>[\n]+      {
-     // 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.
-     // for 'foo' we should get foo
++    /* Newline found. Let's update the location and continue. */
 +    driver.loc_.lines(yyleng);
 +    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::d2::D2ParserContext::DHCPDDNS:
 +    case isc::d2::D2ParserContext::DNS_SERVER:
 +    case isc::d2::D2ParserContext::DNS_SERVERS:
 +        return isc::d2::D2Parser::make_IP_ADDRESS(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("ip-address", driver.loc_);
 +    }
 +}
 +
 +\"port\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::DHCPDDNS:
 +    case isc::d2::D2ParserContext::DNS_SERVER:
 +    case isc::d2::D2ParserContext::DNS_SERVERS:
 +        return isc::d2::D2Parser::make_PORT(driver.loc_);
 +    default:
 +        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::d2::D2ParserContext::DHCPDDNS:
 +        return isc::d2::D2Parser::make_NCR_PROTOCOL(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("ncr-protocol", driver.loc_);
 +    }
 +}
 +
 +\"ncr-format\" {
 +    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_);
 +    }
 +}
 +
 +(?i:\"UDP\") {
 +    /* dhcp-ddns value keywords are case insensitive */
 +    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::d2::D2Parser::make_STRING(tmp, driver.loc_);
 +}
 +
 +(?i:\"TCP\") {
 +    /* 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_);
 +}
 +
 +(?i:\"JSON\") {
 +    /* 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_);
 +}
 +
 +\"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_);
 +    }
 +}
 +
 +\"ddns-domains\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::FORWARD_DDNS:
 +    case isc::d2::D2ParserContext::REVERSE_DDNS:
 +        return isc::d2::D2Parser::make_DDNS_DOMAINS(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("ddns-domains", driver.loc_);
 +    }
 +}
 +
 +\"key-name\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::DDNS_DOMAIN:
 +    case isc::d2::D2ParserContext::DDNS_DOMAINS:
 +        return isc::d2::D2Parser::make_KEY_NAME(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("key-name", driver.loc_);
 +    }
 +}
 +
 +\"dns-servers\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::DDNS_DOMAIN:
 +    case isc::d2::D2ParserContext::DDNS_DOMAINS:
 +        return isc::d2::D2Parser::make_DNS_SERVERS(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("dns-servers", driver.loc_);
 +    }
 +}
 +
 +\"hostname\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::DNS_SERVER:
 +    case isc::d2::D2ParserContext::DNS_SERVERS:
 +        return isc::d2::D2Parser::make_HOSTNAME(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("hostname", 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_);
 +    }
 +}
 +
 +\"algorithm\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::TSIG_KEY:
 +    case isc::d2::D2ParserContext::TSIG_KEYS:
 +        return isc::d2::D2Parser::make_ALGORITHM(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("algorithm", driver.loc_);
 +    }
 +}
 +
 +\"digest-bits\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::TSIG_KEY:
 +    case isc::d2::D2ParserContext::TSIG_KEYS:
 +        return isc::d2::D2Parser::make_DIGEST_BITS(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("digest-bits", driver.loc_);
 +    }
 +}
 +
 +\"secret\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::TSIG_KEY:
 +    case isc::d2::D2ParserContext::TSIG_KEYS:
 +        return isc::d2::D2Parser::make_SECRET(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("secret", driver.loc_);
 +    }
 +}
 +
 +
 +\"Logging\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::CONFIG:
 +        return isc::d2::D2Parser::make_LOGGING(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("Logging", driver.loc_);
 +    }
 +}
 +
 +\"loggers\" {
 +    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_);
 +    }
 +}
 +
 +\"output_options\" {
 +    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_);
 +    }
 +}
 +
 +\"output\" {
 +    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_);
 +    }
 +}
 +
 +\"flush\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
 +        return isc::d2::D2Parser::make_FLUSH(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("flush", driver.loc_);
 +    }
 +}
 +
 +\"maxsize\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
 +        return isc::d2::D2Parser::make_MAXSIZE(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("maxsize", driver.loc_);
 +    }
 +}
 +
 +\"maxver\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::OUTPUT_OPTIONS:
 +        return isc::d2::D2Parser::make_MAXVER(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("maxver", driver.loc_);
 +    }
 +}
 +
 +\"name\" {
 +    switch(driver.ctx_) {
 +    case isc::d2::D2ParserContext::LOGGERS:
 +    case isc::d2::D2ParserContext::TSIG_KEY:
 +    case isc::d2::D2ParserContext::TSIG_KEYS:
 +    case isc::d2::D2ParserContext::DDNS_DOMAIN:
 +    case isc::d2::D2ParserContext::DDNS_DOMAINS:
 +        return isc::d2::D2Parser::make_NAME(driver.loc_);
 +    default:
 +        return isc::d2::D2Parser::make_STRING("name", driver.loc_);
 +    }
 +}
 +
 +\"debuglevel\" {
 +    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_);
 +    }
 +}
 +
 +\"severity\" {
 +    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_);
 +    }
 +}
 +
 +\"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} {
-             // impossible condition
++    /* 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.
++       for 'foo' we should get foo */
 +    std::string raw(yytext+1);
 +    size_t len = raw.size() - 1;
 +    raw.resize(len);
 +    std::string decoded;
 +    decoded.reserve(len);
 +    for (size_t pos = 0; pos < len; ++pos) {
 +        int b = 0;
 +        char c = raw[pos];
 +        switch (c) {
 +        case '"':
-                 // impossible condition
++            /* impossible condition */
 +            driver.error(driver.loc_, "Bad quote in \"" + raw + "\"");
 +        case '\\':
 +            ++pos;
 +            if (pos >= len) {
-                 // support only \u0000 to \u00ff
++                /* impossible condition */
 +                driver.error(driver.loc_, "Overflow escape in \"" + raw + "\"");
 +            }
 +            c = raw[pos];
 +            switch (c) {
 +            case '"':
 +            case '\\':
 +            case '/':
 +                decoded.push_back(c);
 +                break;
 +            case 'b':
 +                decoded.push_back('\b');
 +                break;
 +            case 'f':
 +                decoded.push_back('\f');
 +                break;
 +            case 'n':
 +                decoded.push_back('\n');
 +                break;
 +            case 'r':
 +                decoded.push_back('\r');
 +                break;
 +            case 't':
 +                decoded.push_back('\t');
 +                break;
 +            case 'u':
-                     // impossible condition
++                /* support only \u0000 to \u00ff */
 +                ++pos;
 +                if (pos + 4 > len) {
-                     // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_,
 +                                 "Overflow unicode escape in \"" + raw + "\"");
 +                }
 +                if ((raw[pos] != '0') || (raw[pos + 1] != '0')) {
 +                    driver.error(driver.loc_, "Unsupported unicode escape in \"" + raw + "\"");
 +                }
 +                pos += 2;
 +                c = raw[pos];
 +                if ((c >= '0') && (c <= '9')) {
 +                    b = (c - '0') << 4;
 +                } else if ((c >= 'A') && (c <= 'F')) {
 +                    b = (c - 'A' + 10) << 4;
 +                } else if ((c >= 'a') && (c <= 'f')) {
 +                    b = (c - 'a' + 10) << 4;
 +                } else {
-                     // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
 +                }
 +                pos++;
 +                c = raw[pos];
 +                if ((c >= '0') && (c <= '9')) {
 +                    b |= c - '0';
 +                } else if ((c >= 'A') && (c <= 'F')) {
 +                    b |= c - 'A' + 10;
 +                } else if ((c >= 'a') && (c <= 'f')) {
 +                    b |= c - 'a' + 10;
 +                } else {
-                 // impossible condition
++                    /* impossible condition */
 +                    driver.error(driver.loc_, "Not hexadecimal in unicode escape in \"" + raw + "\"");
 +                }
 +                decoded.push_back(static_cast<char>(b & 0xff));
 +                break;
 +            default:
-                 // impossible condition
++                /* impossible condition */
 +                driver.error(driver.loc_, "Bad escape in \"" + raw + "\"");
 +            }
 +            break;
 +        default:
 +            if ((c >= 0) && (c < 0x20)) {
-     // Bad string with a forbidden control character inside
++                /* impossible condition */
 +                driver.error(driver.loc_, "Invalid control in \"" + raw + "\"");
 +            }
 +            decoded.push_back(c);
 +        }
 +    }
 +
 +    return isc::d2::D2Parser::make_STRING(decoded, driver.loc_);
 +}
 +
 +\"{JSONStringCharacter}*{ControlCharacter}{ControlCharacterFill}*\" {
-     // Bad string with a bad escape inside
++    /* Bad string with a forbidden control character inside */
 +    driver.error(driver.loc_, "Invalid control in " + std::string(yytext));
 +}
 +
 +\"{JSONStringCharacter}*\\{BadJSONEscapeSequence}[^\x00-\x1f"]*\" {
-     // Bad string with an open escape at the end
++    /* Bad string with a bad escape inside */
 +    driver.error(driver.loc_, "Bad escape in " + std::string(yytext));
 +}
 +
 +\"{JSONStringCharacter}*\\\" {
-     // An integer was found.
++    /* Bad string with an open escape at the end */
 +    driver.error(driver.loc_, "Overflow escape in " + std::string(yytext));
 +}
 +
 +"["    { 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} {
-         // In substring we want to use negative values (e.g. -1).
-         // In enterprise-id we need to use values up to 0xffffffff.
-         // To cover both of those use cases, we need at least
-         // int64_t.
++    /* An integer was found. */
 +    std::string tmp(yytext);
 +    int64_t integer = 0;
 +    try {
-     // The parser needs the string form as double conversion is no lossless
++        /* In substring we want to use negative values (e.g. -1).
++           In enterprise-id we need to use values up to 0xffffffff.
++           To cover both of those use cases, we need at least
++           int64_t. */
 +        integer = boost::lexical_cast<int64_t>(tmp);
 +    } catch (const boost::bad_lexical_cast &) {
 +        driver.error(driver.loc_, "Failed to convert " + tmp + " to an integer.");
 +    }
 +
-     // A floating point was found.
++    /* The parser needs the string form as double conversion is no lossless */
 +    return isc::d2::D2Parser::make_INTEGER(integer, driver.loc_);
 +}
 +
 +[-+]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)? {
-         // fatal() throws an exception so this can't be reached
++    /* A floating point was found. */
 +    std::string tmp(yytext);
 +    double fp = 0.0;
 +    try {
 +        fp = boost::lexical_cast<double>(tmp);
 +    } catch (const boost::bad_lexical_cast &) {
 +        driver.error(driver.loc_, "Failed to convert " + tmp + " to a floating point.");
 +    }
 +
 +    return isc::d2::D2Parser::make_FLOAT(fp, driver.loc_);
 +}
 +
 +true|false {
 +    string tmp(yytext);
 +    return isc::d2::D2Parser::make_BOOLEAN(tmp == "true", driver.loc_);
 +}
 +
 +null {
 +   return isc::d2::D2Parser::make_NULL_TYPE(driver.loc_);
 +}
 +
 +(?i:true) driver.error (driver.loc_, "JSON true reserved keyword is lower case only");
 +
 +(?i:false) driver.error (driver.loc_, "JSON false reserved keyword is lower case only");
 +
 +(?i:null) driver.error (driver.loc_, "JSON null reserved keyword is lower case only");
 +
 +<*>.   driver.error (driver.loc_, "Invalid character: " + std::string(yytext));
 +
 +<<EOF>> {
 +    if (driver.states_.empty()) {
 +        return isc::d2::D2Parser::make_END(driver.loc_);
 +    }
 +    driver.loc_ = driver.locs_.back();
 +    driver.locs_.pop_back();
 +    driver.file_ = driver.files_.back();
 +    driver.files_.pop_back();
 +    if (driver.sfile_) {
 +        fclose(driver.sfile_);
 +        driver.sfile_ = 0;
 +    }
 +    if (!driver.sfiles_.empty()) {
 +        driver.sfile_ = driver.sfiles_.back();
 +        driver.sfiles_.pop_back();
 +    }
 +    d2_parser__delete_buffer(YY_CURRENT_BUFFER);
 +    d2_parser__switch_to_buffer(driver.states_.back());
 +    driver.states_.pop_back();
 +
 +    BEGIN(DIR_EXIT);
 +}
 +
 +%%
 +
 +using namespace isc::dhcp;
 +
 +void
 +D2ParserContext::scanStringBegin(const std::string& str, ParserType parser_type)
 +{
 +    start_token_flag = true;
 +    start_token_value = parser_type;
 +
 +    file_ = "<string>";
 +    sfile_ = 0;
 +    loc_.initialize(&file_);
 +    yy_flex_debug = trace_scanning_;
 +    YY_BUFFER_STATE buffer;
 +    buffer = d2_parser__scan_bytes(str.c_str(), str.size());
 +    if (!buffer) {
 +        fatal("cannot scan string");
-     // See d2_lexer.cc header for available definitions
++        /* fatal() throws an exception so this can't be reached */
 +    }
 +}
 +
 +void
 +D2ParserContext::scanFileBegin(FILE * f,
 +                              const std::string& filename,
 +                              ParserType parser_type)
 +{
 +    start_token_flag = true;
 +    start_token_value = parser_type;
 +
 +    file_ = filename;
 +    sfile_ = f;
 +    loc_.initialize(&file_);
 +    yy_flex_debug = trace_scanning_;
 +    YY_BUFFER_STATE buffer;
 +
-     // Close files
++    /* See d2_lexer.cc header for available definitions */
 +    buffer = d2_parser__create_buffer(f, 65536 /*buffer size*/);
 +    if (!buffer) {
 +        fatal("cannot scan file " + filename);
 +    }
 +    d2_parser__switch_to_buffer(buffer);
 +}
 +
 +void
 +D2ParserContext::scanEnd() {
 +    if (sfile_)
 +        fclose(sfile_);
 +    sfile_ = 0;
 +    static_cast<void>(d2_parser_lex_destroy());
-     // Delete states
++    /* Close files */
 +    while (!sfiles_.empty()) {
 +        FILE* f = sfiles_.back();
 +        if (f) {
 +            fclose(f);
 +        }
 +        sfiles_.pop_back();
 +    }
- /// To avoid unused function error
++    /* Delete states */
 +    while (!states_.empty()) {
 +        d2_parser__delete_buffer(states_.back());
 +        states_.pop_back();
 +    }
 +}
 +
 +void
 +D2ParserContext::includeFile(const std::string& filename) {
 +    if (states_.size() > 10) {
 +        fatal("Too many nested include.");
 +    }
 +
 +    FILE* f = fopen(filename.c_str(), "r");
 +    if (!f) {
 +        fatal("Can't open include file " + filename);
 +    }
 +    if (sfile_) {
 +        sfiles_.push_back(sfile_);
 +    }
 +    sfile_ = f;
 +    states_.push_back(YY_CURRENT_BUFFER);
 +    YY_BUFFER_STATE buffer;
 +    buffer = d2_parser__create_buffer(f, 65536 /*buffer size*/);
 +    if (!buffer) {
 +        fatal( "Can't scan include file " + filename);
 +    }
 +    d2_parser__switch_to_buffer(buffer);
 +    files_.push_back(file_);
 +    file_ = filename;
 +    locs_.push_back(loc_);
 +    loc_.initialize(&file_);
 +
 +    BEGIN(INITIAL);
 +}
 +
 +namespace {
-     // cppcheck-suppress unusedPrivateFunction
++/** To avoid unused function error */
 +class Dummy {
++    /* cppcheck-suppress unusedPrivateFunction */
 +    void dummy() { yy_fatal_error("Fix me: how to disable its definition?"); }
 +};
 +}
Simple merge
Simple merge
index 8958ed4bf20041bee75d818b6a138c976246941d,8b1313605232da7b6c1e864a9acb56648bc61f2e..f49aa1954313a88ed90dba0f49f545464add5d39
  # undef yywrap
  # define yywrap() 1
  
- // The location of the current token. The lexer will keep updating it. This
- // variable will be useful for logging errors.
+ /* The location of the current token. The lexer will keep updating it. This
+    variable will be useful for logging errors. */
  static isc::eval::location loc;
  
- // To avoid the call to exit... oops!
 +namespace {
 +    bool start_token_flag = false;
 +    isc::eval::EvalContext::ParserType start_token_value;
 +};
 +
+ /* To avoid the call to exit... oops! */
  #define YY_FATAL_ERROR(msg) isc::eval::EvalContext::fatal(msg)
  %}
  
@@@ -80,20 -77,8 +82,20 @@@ addr6 [0-9a-fA-F]*\:[0-9a-fA-F]*\:[0-9a
  %%
  
  %{
-     // Code run each time evallex is called.
+     /* Code run each time evallex is called. */
      loc.step();
 +
 +    if (start_token_flag) {
 +        start_token_flag = false;
 +        switch (start_token_value) {
 +        case EvalContext::PARSER_BOOL:
 +            return isc::eval::EvalParser::make_TOPLEVEL_BOOL(loc);
 +        default:
 +        case EvalContext::PARSER_STRING:
 +            return isc::eval::EvalParser::make_TOPLEVEL_STRING(loc);
 +        }
 +    }
 +
  %}
  
  {blank}+   {