From: Michal 'vorner' Vaner Date: Fri, 14 Dec 2012 14:21:23 +0000 (+0100) Subject: [2427] Handle the initial whitespace X-Git-Tag: bind10-1.0.0-beta-release~13^2^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=79b7e9ce53c8bf6fc47285795599630cc9dc3ef8;p=thirdparty%2Fkea.git [2427] Handle the initial whitespace --- diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 46446590ea..85ec9894e7 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -56,6 +56,8 @@ public: lexer_(), zone_origin_(zone_origin), active_origin_(zone_origin), + last_name_(Name::ROOT_NAME()), // Initialize with something, + // we don't care zone_class_(zone_class), callbacks_(callbacks), add_callback_(add_callback), @@ -64,6 +66,7 @@ public: initialized_(false), ok_(true), many_errors_((options & MANY_ERRORS) != 0), + seen_name_(false), complete_(false), seen_error_(false) {} @@ -205,6 +208,7 @@ private: const Name zone_origin_; Name active_origin_; // The origin used during parsing // (modifiable by $ORIGIN) + Name last_name_; // Last seen name during the parsing. const RRClass zone_class_; MasterLoaderCallbacks callbacks_; AddRRCallback add_callback_; @@ -215,6 +219,7 @@ private: bool ok_; // Is it OK to continue loading? const bool many_errors_; // Are many errors allowed (or should we abort // on the first) + bool seen_name_; // Did we parse at least one name? public: bool complete_; // All work done. bool seen_error_; // Was there at least one error during the @@ -236,11 +241,26 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) { size_t count = 0; while (ok_ && count < count_limit) { try { + MasterToken initial_token(MasterToken::NO_TOKEN_PRODUCED); // Skip all EOLNs (empty lines) and finish on EOF - bool empty = true; do { - const MasterToken& empty_token(lexer_.getNextToken()); - if (empty_token.getType() == MasterToken::END_OF_FILE) { + initial_token = lexer_.getNextToken(MasterLexer::QSTRING | + MasterLexer::INITIAL_WS); + if (initial_token.getType() == MasterToken::INITIAL_WS) { + // The INITIAL_WS is interesting only if something is + // after it. So peek there and if there's EOLN or EOF, + // ignore it. + const MasterToken& peek_token(lexer_.getNextToken()); + if (peek_token.getType() == MasterToken::END_OF_LINE || + peek_token.getType() == MasterToken::END_OF_FILE) { + initial_token = peek_token; + } else { + // It is something interesting. Return it back and + // keep the whitespace. + lexer_.ungetToken(); + } + } + if (initial_token.getType() == MasterToken::END_OF_FILE) { if (!popSource()) { return (true); } else { @@ -251,29 +271,45 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) { continue; } } - empty = empty_token.getType() == MasterToken::END_OF_LINE; - } while (empty); - // Return the last token, as it was not empty - lexer_.ungetToken(); + } while (initial_token.getType() == MasterToken::END_OF_LINE || + initial_token.getType() == MasterToken::END_OF_FILE); + + if (initial_token.getType() == MasterToken::QSTRING || + initial_token.getType() == MasterToken::STRING) { + // If it is name (or directive), handle it. + const MasterToken::StringRegion& + name_string(initial_token.getStringRegion()); + + if (name_string.len > 0 && name_string.beg[0] == '$') { + // This should have either thrown (and the error handler + // will read up until the end of line) or read until the + // end of line. + + // Exclude the $ from the string on this point. + handleDirective(name_string.beg + 1, name_string.len - 1); + // So, get to the next line, there's nothing more interesting + // in this one. + continue; + } - const MasterToken::StringRegion& - name_string(lexer_.getNextToken(MasterToken::QSTRING). - getStringRegion()); - - if (name_string.len > 0 && name_string.beg[0] == '$') { - // This should have either thrown (and the error handler - // will read up until the end of line) or read until the - // end of line. - - // Exclude the $ from the string on this point. - handleDirective(name_string.beg + 1, name_string.len - 1); - // So, get to the next line, there's nothing more interesting - // in this one. - continue; + last_name_ = Name(name_string.beg, name_string.len, + &active_origin_); + seen_name_ = true; + } else if (initial_token.getType() == MasterToken::INITIAL_WS) { + // This means the same name as previous. + if (!seen_name_) { + isc_throw(InternalException, "No previous name to use in " + "place of initial whitespace"); + } + } else if (initial_token.getType() == MasterToken::ERROR) { + // Error token here. + isc_throw(InternalException, initial_token.getErrorText()); + } else { + // Some other token (what could that be?) + isc_throw(InternalException, "Parser got confused (unexpected " + "token " << initial_token.getType() << ")"); } - const Name name(name_string.beg, name_string.len, - &active_origin_); // TODO: Some more flexibility. We don't allow omitting // anything yet @@ -301,7 +337,7 @@ MasterLoader::MasterLoaderImpl::loadIncremental(size_t count_limit) { // callbacks_ already. We need to decide if we want to continue // or not. if (data) { - add_callback_(name, rrclass, rrtype, ttl, data); + add_callback_(last_name_, rrclass, rrtype, ttl, data); // Good, we loaded another one ++count;