]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
Add support for scoping and symbol binding
authorPatrick McHardy <kaber@trash.net>
Fri, 20 Mar 2009 07:12:18 +0000 (08:12 +0100)
committerPatrick McHardy <kaber@trash.net>
Fri, 20 Mar 2009 07:12:18 +0000 (08:12 +0100)
As a first step towards stand-alone sets, add support for scoping and
binding symbols. This will be used for user-defined constants, as well
as declarations of modifiable (stand-alone) sets once the kernel side
is ready.

Scopes are currently limited to three nesting levels: the global scope,
table block scopes and chain block scopes.

Signed-off-by: Patrick McHardy <kaber@trash.net>
include/parser.h
include/rule.h
src/parser.y
src/rule.c

index a47bd0f078327abe76a0a41d7e0de50be7553d15..f5dd6f4bb597ac4d2e7587068cf1af2761b98116 100644 (file)
@@ -2,6 +2,7 @@
 #define NFTABLES_PARSER_H
 
 #include <list.h>
+#include <rule.h> // FIXME
 
 #define MAX_INCLUDE_DEPTH              16
 #define TABSIZE                                8
 #define YYLTYPE_IS_TRIVIAL             0
 #define YYENABLE_NLS                   0
 
+#define SCOPE_NEST_MAX                 3
+
 struct parser_state {
        struct input_descriptor         *indesc;
        struct input_descriptor         indescs[MAX_INCLUDE_DEPTH];
        unsigned int                    indesc_idx;
 
        struct list_head                *msgs;
+
+       struct scope                    top_scope;
+       struct scope                    *scopes[SCOPE_NEST_MAX];
+       unsigned int                    scope;
+
        struct list_head                cmds;
 };
 
index 991d1125284cb28d70627ce2d524c515440d9acb..4e5da06408c37caad017df471ba005aa1abd3d73 100644 (file)
@@ -23,6 +23,37 @@ struct handle {
 extern void handle_merge(struct handle *dst, const struct handle *src);
 extern void handle_free(struct handle *h);
 
+/**
+ * struct scope
+ *
+ * @parent:    pointer to parent scope
+ * @symbols:   symbols bound in the scope
+ */
+struct scope {
+       const struct scope      *parent;
+       struct list_head        symbols;
+};
+
+extern struct scope *scope_init(struct scope *scope, const struct scope *parent);
+
+/**
+ * struct symbol
+ *
+ * @list:      scope symbol list node
+ * @identifier:        identifier
+ * @expr:      initializer
+ */
+struct symbol {
+       struct list_head        list;
+       const char              *identifier;
+       struct expr             *expr;
+};
+
+extern void symbol_bind(struct scope *scope, const char *identifier,
+                       struct expr *expr);
+extern struct symbol *symbol_lookup(const struct scope *scope,
+                                   const char *identifier);
+
 /**
  * struct table - nftables table
  *
@@ -33,6 +64,7 @@ extern void handle_free(struct handle *h);
 struct table {
        struct list_head        list;
        struct handle           handle;
+       struct scope            scope;
        struct list_head        chains;
 };
 
@@ -55,6 +87,7 @@ struct chain {
        struct handle           handle;
        unsigned int            hooknum;
        unsigned int            priority;
+       struct scope            scope;
        struct list_head        rules;
 };
 
index b13e932e84494b13685945c3962af8c3ea14c92c..1ca5981b3c715bb3626610642011e1a66680cac4 100644 (file)
@@ -33,6 +33,7 @@ void parser_init(struct parser_state *state, struct list_head *msgs)
        memset(state, 0, sizeof(*state));
        init_list_head(&state->cmds);
        state->msgs = msgs;
+       state->scopes[0] = scope_init(&state->top_scope, NULL);
 }
 
 static void yyerror(struct location *loc, void *scanner,
@@ -41,6 +42,22 @@ static void yyerror(struct location *loc, void *scanner,
        erec_queue(error(loc, "%s", s), state->msgs);
 }
 
+static struct scope *current_scope(const struct parser_state *state)
+{
+       return state->scopes[state->scope];
+}
+
+static void open_scope(struct parser_state *state, struct scope *scope)
+{
+       scope_init(scope, current_scope(state));
+       state->scopes[++state->scope] = scope;
+}
+
+static void close_scope(struct parser_state *state)
+{
+       state->scope--;
+}
+
 static void location_init(void *scanner, struct parser_state *state,
                          struct location *loc)
 {
@@ -474,6 +491,7 @@ add_cmd                     :       TABLE           table_spec
                                                '{'     table_block     '}'
                        {
                                handle_merge(&$3->handle, &$2);
+                               close_scope(state);
                                $$ = cmd_alloc(CMD_ADD, CMD_OBJ_TABLE, &$2, $5);
                        }
                        |       CHAIN           chain_spec
@@ -484,6 +502,7 @@ add_cmd                     :       TABLE           table_spec
                                                '{'     chain_block     '}'
                        {
                                handle_merge(&$3->handle, &$2);
+                               close_scope(state);
                                $$ = cmd_alloc(CMD_ADD, CMD_OBJ_CHAIN, &$2, $5);
                        }
                        |       RULE            ruleid_spec     rule
@@ -530,7 +549,11 @@ flush_cmd          :       TABLE           table_spec
                        }
                        ;
 
-table_block_alloc      :       /* empty */     { $$ = table_alloc(); }
+table_block_alloc      :       /* empty */
+                       {
+                               $$ = table_alloc();
+                               open_scope(state, &$$->scope);
+                       }
                        ;
 
 table_block            :       /* empty */     { $$ = $<table>-1; }
@@ -547,11 +570,16 @@ table_line                :       CHAIN           chain_identifier        chain_block_alloc
                                                '{'     chain_block     '}'
                        {
                                handle_merge(&$3->handle, &$2);
+                               close_scope(state);
                                $$ = $3;
                        }
                        ;
 
-chain_block_alloc      :       /* empty */     { $$ = chain_alloc(NULL); }
+chain_block_alloc      :       /* empty */
+                       {
+                               $$ = chain_alloc(NULL);
+                               open_scope(state, &$$->scope);
+                       }
                        ;
 
 chain_block            :       /* empty */     { $$ = $<chain>-1; }
index e86c78aae979b6345bfb8649627c7b8b92f15ae3..8efbd887b4db919a7328c06b65e9c30dcb411545 100644 (file)
@@ -68,6 +68,38 @@ void rule_print(const struct rule *rule)
        printf("\n");
 }
 
+struct scope *scope_init(struct scope *scope, const struct scope *parent)
+{
+       scope->parent = parent;
+       init_list_head(&scope->symbols);
+       return scope;
+}
+
+void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr)
+{
+       struct symbol *sym;
+
+       sym = xzalloc(sizeof(*sym));
+       sym->identifier = xstrdup(identifier);
+       sym->expr = expr;
+
+       list_add_tail(&sym->list, &scope->symbols);
+}
+
+struct symbol *symbol_lookup(const struct scope *scope, const char *identifier)
+{
+       struct symbol *sym;
+
+       while (scope != NULL) {
+               list_for_each_entry(sym, &scope->symbols, list) {
+                       if (!strcmp(sym->identifier, identifier))
+                               return sym;
+               }
+               scope = scope->parent;
+       }
+       return NULL;
+}
+
 struct chain *chain_alloc(const char *name)
 {
        struct chain *chain;