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),
initialized_(false),
ok_(true),
many_errors_((options & MANY_ERRORS) != 0),
+ seen_name_(false),
complete_(false),
seen_error_(false)
{}
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_;
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
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 {
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
// 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;