summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org.ua>2011-05-20 06:17:20 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2011-05-20 06:17:20 (GMT)
commitd253fa956809a1497583212109d33fd4f1a05b31 (patch) (side-by-side diff)
treebf48aced94192d54b49ac09755ed2e6d88514d70 /src
parentbcab0df28d7e87f99da29a32327787c25261273e (diff)
downloadgrecs-d253fa956809a1497583212109d33fd4f1a05b31.tar.gz
grecs-d253fa956809a1497583212109d33fd4f1a05b31.tar.bz2
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.
Diffstat (limited to 'src') (more/less context) (ignore whitespace changes)
-rw-r--r--src/bind-gram.y86
-rw-r--r--src/bind-lex.l3
-rw-r--r--src/lookup.c6
3 files changed, 52 insertions, 43 deletions
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 <ident> BIND_IDENT
+%token <ident> BIND_IDENT BIND_CONTROLS
%token <string> BIND_STRING
%type <string> string
-%type <svalue> value
+%type <svalue> value ctlsub
%type <pvalue> vallist tag
-%type <list> vlist
+%type <list> vlist ctllist
%type <node> stmt simple block
%type <node_list> 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)) {

Return to:

Send suggestions and report system problems to the System administrator.