From d253fa956809a1497583212109d33fd4f1a05b31 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Fri, 20 May 2011 09:17:20 +0300 Subject: Fix bind parser. * src/bind-gram.y: Special handling for the controls block. * src/bind-lex.l: Handle "controls" separately. * src/lookup.c (grecs_find_node): Handle single dot path (root node). (grecs_match_first): Likewise. (grecs_match_next): Return NULL if buf is NULL. * tests/parser-bind.at: Update. --- src/bind-gram.y | 86 +++++++++++++++++++++++++++++---------------------------- src/bind-lex.l | 3 +- src/lookup.c | 6 ++++ 3 files changed, 52 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/bind-gram.y b/src/bind-gram.y index 621070e..fadd3f5 100644 --- a/src/bind-gram.y +++ b/src/bind-gram.y @@ -49,12 +49,12 @@ static struct grecs_value *stmtlist_to_value(struct grecs_node *node); struct { struct grecs_node *head, *tail; } node_list; } -%token BIND_IDENT +%token BIND_IDENT BIND_CONTROLS %token BIND_STRING %type string -%type value +%type value ctlsub %type vallist tag -%type vlist +%type vlist ctllist %type stmt simple block %type stmtlist @@ -110,31 +110,38 @@ simple : BIND_IDENT vallist ';' } ; -block : BIND_IDENT tag '{' stmtlist '}' opt_sc +block : BIND_IDENT tag '{' stmtlist '}' ';' { $$ = grecs_node_create(grecs_node_block, &$1.locus); $$->ident = $1.string; $$->v.value = $2; grecs_node_bind($$, $4.head, 1); } + | BIND_CONTROLS '{' ctlsub '}' ';' + /* Special case: + + controls { + inet 127.0.0.1 port 953 + allow { 127.0.0.1; 127.0.0.2; } keys { "rndc-key"; }; + }; + + This produces: + + .controls: (inet, 127.0.0.1, port, 953, allow, \ + (127.0.0.1, 127.0.0.2), keys, (rndc-key)) + */ + { + $$ = grecs_node_create(grecs_node_stmt, &$1.locus); + $$->ident = $1.string; + $$->v.value = grecs_value_ptr_from_static(&$3); + } ; tag : /* empty */ { $$ = NULL; } - | BIND_IDENT - { - $$ = grecs_malloc(sizeof($$[0])); - $$->type = GRECS_TYPE_STRING; - $$->v.string = $1.string; - } - | BIND_STRING - { - $$ = grecs_malloc(sizeof($$[0])); - $$->type = GRECS_TYPE_STRING; - $$->v.string = $1; - } + | vallist ; vallist : vlist @@ -169,30 +176,6 @@ vlist : value { grecs_list_append($1, grecs_value_ptr_from_static(&$2)); } - | vlist BIND_IDENT '{' stmtlist '}' - /* This production handles constructs that don't fit well into - hierarchical structure, namely, the "controls" statement, e.g.: - - controls { - inet 127.0.0.1 port 953 - allow { 127.0.0.1; 127.0.0.2; } keys { "rndc-key"; }; - }; - - This statement produces: - - .controls.inet: 127.0.0.1 port 953 allow (127.0.0.1) keys - (rndc-key) - */ - { - struct grecs_value *val = grecs_malloc(sizeof(*val)); - val->type = GRECS_TYPE_STRING; - val->v.string = $2.string; - grecs_list_append($1, val); - - val = stmtlist_to_value($4.head); - /* FIXME: Free $4 */ - grecs_list_append($1, val); - } ; value : string @@ -209,8 +192,27 @@ string : BIND_STRING } ; -opt_sc : /* empty */ - | ';' +ctlsub : ctllist ';' + { + $$.type = GRECS_TYPE_LIST; + $$.v.list = $1; + } + ; + +ctllist : value + { + $$ = grecs_value_list_create(); + grecs_list_append($$, grecs_value_ptr_from_static(&$1)); + } + | ctllist value + { + grecs_list_append($1, grecs_value_ptr_from_static(&$2)); + } + | ctllist '{' stmtlist '}' + { + grecs_list_append($1, stmtlist_to_value($3.head)); + /* FIXME: Free $3 */ + } ; %% diff --git a/src/bind-lex.l b/src/bind-lex.l index 926785e..f5fd66d 100644 --- a/src/bind-lex.l +++ b/src/bind-lex.l @@ -57,7 +57,8 @@ P [1-9][0-9]* grecs_line_add(yytext, yyleng); yylval.ident.string = grecs_line_finish(); yylval.ident.locus = grecs_current_locus; - return BIND_IDENT; + return strcmp(yylval.ident.string, "controls") == 0 ? + BIND_CONTROLS : BIND_IDENT; } /* Strings */ [a-zA-Z0-9_\.\*/:@-]+ { grecs_line_begin(); diff --git a/src/lookup.c b/src/lookup.c index 95b7aac..a67edb9 100644 --- a/src/lookup.c +++ b/src/lookup.c @@ -320,6 +320,8 @@ grecs_find_node(struct grecs_node *node, const char *path) int rc; struct grecs_match_buf buf; + if (strcmp(path, ".") == 0) + return node; rc = split_cfg_path(path, &buf.argc, &buf.argv, &buf.labelv); if (rc || !buf.argc) return NULL; @@ -434,6 +436,8 @@ grecs_match(struct grecs_match_buf *buf) struct grecs_node * grecs_match_next(struct grecs_match_buf *buf) { + if (!buf) + return NULL; while (buf->node = grecs_next_node(buf->node)) if (grecs_match(buf)) break; @@ -453,6 +457,8 @@ grecs_match_first(struct grecs_node *tree, const char *pattern, return NULL; } errno = 0; + if (strcmp(pattern, ".") == 0) + return tree; buf = grecs_zalloc(sizeof(*buf)); if (split_cfg_path(pattern, &buf->argc, &buf->argv, &buf->labelv)) { -- cgit v1.2.1