Commit fb11b9fc authored by Daniel Salzman's avatar Daniel Salzman

zscanner: refactor state parsing

parent cd9c98f5
This diff is collapsed.
This diff is collapsed.
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -86,12 +86,12 @@ typedef struct {
/*! \brief Scanner states describing the result. */
typedef enum {
ZS_STATE_NONE, /*!< Initial state. */
ZS_STATE_NONE, /*!< Initial state (no data). */
ZS_STATE_DATA, /*!< A record parsed. */
ZS_STATE_ERROR, /*!< An error occurred. */
ZS_STATE_INCLUDE, /*!< An include directive parsed. */
ZS_STATE_INCLUDE, /*!< An include directive (see include_filename, buffer). */
ZS_STATE_EOF, /*!< The end of the current input reached. */
ZS_STATE_STOP /*!< Finished parsing. */
ZS_STATE_STOP /*!< Early stop (possibly set from a callback). */
} zs_state_t;
/*!
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -334,9 +334,6 @@ static void parse(
// Initialization of the last r_data byte.
uint8_t *rdata_stop = s->r_data + MAX_RDATA_LENGTH - 1;
// External processing interrupt indicator.
bool escape = false;
// Write scanner body (in C).
%% write exec;
......@@ -391,39 +388,45 @@ int zs_parse_record(
return -1;
}
// Stop parsing if stop or after the final parsing.
if (s->state == ZS_STATE_STOP || s->input.eof) {
return -1;
// Check if parsing is possible.
switch (s->state) {
case ZS_STATE_NONE:
case ZS_STATE_DATA:
case ZS_STATE_INCLUDE:
break;
case ZS_STATE_ERROR:
if (s->error.fatal) {
return -1;
}
break;
default:
// Return if stop or end of file.
return 0;
}
// Check for the end of the input.
if (s->input.current != s->input.end) {
// Try to parse another item.
s->state = ZS_STATE_NONE;
// Parse the next item.
parse(s);
return 0;
}
switch (s->state) {
case ZS_STATE_NONE:
// Indicate end of the input.
s->state = ZS_STATE_EOF;
return 0;
case ZS_STATE_EOF:
// Parse the final block.
if (zs_set_input_string(s, "\n", 1) != 0) {
return -1;
}
s->input.eof = true;
parse(s);
if (s->state == ZS_STATE_EOF) {
return -1;
// Finish if nothing was parsed.
if (s->state == ZS_STATE_NONE) {
// Parse the final block.
if (zs_set_input_string(s, "\n", 1) != 0) {
return -1;
}
s->input.eof = true;
parse(s);
if (s->state == ZS_STATE_NONE) {
s->state = ZS_STATE_EOF;
}
}
return 0;
default:
return -1;;
} else {
s->state = ZS_STATE_EOF;
}
return 0;
}
__attribute__((visibility("default")))
......@@ -439,8 +442,8 @@ int zs_parse_all(
// Parse input block.
parse(s);
// Parse trailing newline-char block if not stop.
if (s->state != ZS_STATE_STOP) {
// Parse trailing newline-char block if it makes sense.
if (s->state != ZS_STATE_STOP && !s->error.fatal) {
if (zs_set_input_string(s, "\n", 1) != 0) {
return -1;
}
......@@ -448,7 +451,7 @@ int zs_parse_all(
parse(s);
}
// Check if any errors has occurred.
// Check if any errors have occurred.
if (s->error.counter > 0) {
return -1;
}
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -109,33 +109,26 @@
if (s->process.error != NULL) {
s->process.error(s);
// Stop the scanner if required.
// Stop if required from the callback.
if (s->state == ZS_STATE_STOP) {
fbreak;
}
}
// Stop the scanner if fatal.
// Stop the scanner if fatal error.
if (s->error.fatal) {
s->state = ZS_STATE_STOP;
fbreak;
}
fgoto main;
} else {
// Return if external processing.
escape = true;
}
}
action _err_line_exit_final {
if (escape) {
fnext main; fbreak;
} else {
fgoto main;
fhold; fnext main; fbreak;
}
}
# Fill rest of the line to buffer and skip to main loop.
err_line := (^newline $_err_line)* >_err_line_init
%_err_line_exit . newline @_err_line_exit_final;
%_err_line_exit . newline;
# END
# BEGIN - Domain name labels processing
......@@ -743,10 +736,7 @@
}
// Let the caller to solve the include.
if (!s->process.automatic) {
s->state = ZS_STATE_INCLUDE;
escape = true;
} else {
if (s->process.automatic) {
// Create new scanner for included zone file.
zs_scanner_t *ss = malloc(sizeof(zs_scanner_t));
if (ss == NULL) {
......@@ -775,6 +765,9 @@
}
zs_deinit(ss);
free(ss);
} else {
s->state = ZS_STATE_INCLUDE;
fhold; fnext main; fbreak;
}
}
......@@ -797,9 +790,6 @@
# Remove stop processing flag.
action _directive_exit {
NOERR;
if (escape) {
fnext main; fbreak;
}
}
action _directive_error {
ERR(ZS_BAD_DIRECTIVE);
......@@ -2045,7 +2035,7 @@
if (s->process.record != NULL) {
s->process.record(s);
// Stop the scanner if required.
// Stop if required from the callback.
if (s->state == ZS_STATE_STOP) {
fbreak;
}
......
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -70,11 +70,10 @@ static int time_test(void)
return EXIT_SUCCESS;
}
int state_parsing(
zs_scanner_t *s)
{
zs_scanner_t *ss;
static int include(zs_scanner_t *s);
static int state_parsing(zs_scanner_t *s)
{
while (zs_parse_record(s) == 0) {
switch (s->state) {
case ZS_STATE_DATA:
......@@ -91,45 +90,50 @@ int state_parsing(
}
break;
case ZS_STATE_INCLUDE:
ss = malloc(sizeof(zs_scanner_t));
if (ss == NULL) {
return -1;
}
if (zs_init(ss, (char *)s->buffer, s->default_class, s->default_ttl) != 0 ||
zs_set_input_file(ss, (char *)(s->include_filename)) != 0 ||
zs_set_processing(ss, s->process.record, s->process.error, s->process.data) != 0 ||
state_parsing(ss) != 0 ||
ss->error.counter > 0) {
if (ss->error.counter > 0) {
s->error.code = ZS_UNPROCESSED_INCLUDE;
} else {
s->error.code = ss->error.code;
}
s->error.counter++;
s->error.fatal = true;
if (s->process.error != NULL) {
s->process.error(s);
}
zs_deinit(ss);
free(ss);
if (include(s) != 0) {
return -1;
}
zs_deinit(ss);
free(ss);
break;
case ZS_STATE_NONE:
break;
case ZS_STATE_EOF:
// Set the next input string block.
break;
case ZS_STATE_STOP:
return 0;
default:
return (s->error.counter == 0) ? 0 : -1;
}
}
return 0;
return -1;
}
static int include(zs_scanner_t *s)
{
zs_scanner_t *ss;
int ret = 0;
if ((ss = malloc(sizeof(zs_scanner_t))) == NULL ||
zs_init(ss, (char *)s->buffer, s->default_class, s->default_ttl) != 0 ||
zs_set_input_file(ss, (char *)(s->include_filename)) != 0 ||
zs_set_processing(ss, s->process.record, s->process.error, s->process.data) != 0 ||
state_parsing(ss) != 0) {
if (ss->error.counter > 0) {
s->error.counter += ss->error.counter;
s->error.code = ZS_UNPROCESSED_INCLUDE;
} else {
s->error.code = ss->error.code;
}
if (s->process.error != NULL) {
s->buffer[0] = '\0'; // Clear unrelated content.
s->buffer_length = 0;
s->error.counter++;
s->error.fatal = true;
s->process.error(s);
}
ret = -1;
}
zs_deinit(ss);
free(ss);
return ret;
}
int main(int argc, char *argv[])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment