diff options
-rw-r--r-- | include/expression.h | 2 | ||||
-rw-r--r-- | src/evaluate.c | 37 | ||||
-rw-r--r-- | src/expression.c | 2 | ||||
-rw-r--r-- | src/parser.y | 27 | ||||
-rw-r--r-- | src/scanner.l | 3 |
5 files changed, 59 insertions, 12 deletions
diff --git a/include/expression.h b/include/expression.h index e9d21cfc..d4222060 100644 --- a/include/expression.h +++ b/include/expression.h @@ -55,6 +55,7 @@ enum expr_types { enum ops { OP_INVALID, + OP_IMPLICIT, /* Unary operations */ OP_HTON, OP_NTOH, @@ -172,6 +173,7 @@ struct expr { struct { /* EXPR_SYMBOL */ const struct datatype *sym_type; + const struct scope *scope; const char *identifier; }; struct { diff --git a/src/evaluate.c b/src/evaluate.c index 0deff9ad..706ec2e5 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -102,13 +102,25 @@ static int byteorder_conversion(struct eval_ctx *ctx, struct expr **expr, static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) { struct error_record *erec; + struct symbol *sym; struct expr *new; (*expr)->sym_type = ctx->ectx.dtype; - erec = symbol_parse(*expr, &new); - if (erec != NULL) { - erec_queue(erec, ctx->msgs); - return -1; + + if ((*expr)->scope != NULL) { + sym = symbol_lookup((*expr)->scope, (*expr)->identifier); + if (sym == NULL) + return expr_error(ctx, *expr, + "undefined identifier '%s'", + (*expr)->identifier); + // FIXME: need to copy (on write) + new = expr_get(sym->expr); + } else { + erec = symbol_parse(*expr, &new); + if (erec != NULL) { + erec_queue(erec, ctx->msgs); + return -1; + } } expr_free(*expr); @@ -702,6 +714,23 @@ static int expr_evaluate_relational(struct eval_ctx *ctx, struct expr **expr) "constant value", expr_op_symbols[rel->op]); + if (rel->op == OP_IMPLICIT) { + switch (right->ops->type) { + case EXPR_RANGE: + rel->op = OP_RANGE; + break; + case EXPR_SET: + rel->op = OP_LOOKUP; + break; + case EXPR_LIST: + rel->op = OP_FLAGCMP; + break; + default: + rel->op = OP_EQ; + break; + } + } + switch (rel->op) { case OP_LOOKUP: /* Data for range lookups needs to be in big endian order */ diff --git a/src/expression.c b/src/expression.c index 66a8793f..4b3e1e04 100644 --- a/src/expression.c +++ b/src/expression.c @@ -162,7 +162,7 @@ struct expr *verdict_expr_alloc(const struct location *loc, static void symbol_expr_print(const struct expr *expr) { - printf("%s", expr->identifier); + printf("%s%s", expr->scope != NULL ? "$" : "", expr->identifier); } static void symbol_expr_destroy(struct expr *expr) diff --git a/src/parser.y b/src/parser.y index 1ca5981b..d9da115a 100644 --- a/src/parser.y +++ b/src/parser.y @@ -151,6 +151,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SET "set" %token INCLUDE "include" +%token DEFINE "define" %token HOOK "hook" %token <val> HOOKNUM "hooknum" @@ -379,8 +380,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %type <expr> set_expr set_list_expr set_list_member_expr %destructor { expr_free($$); } set_expr set_list_expr set_list_member_expr -%type <expr> expr -%destructor { expr_free($$); } expr +%type <expr> expr initializer_expr +%destructor { expr_free($$); } expr initializer_expr %type <expr> match_expr %destructor { expr_free($$); } match_expr @@ -461,6 +462,11 @@ common_block : INCLUDE QUOTED_STRING stmt_seperator } xfree($2); } + | DEFINE identifier '=' initializer_expr stmt_seperator + { + symbol_bind(current_scope(state), $2, $4); + xfree($2); + } ; line : common_block { $$ = NULL; } @@ -809,6 +815,12 @@ symbol_expr : string $$ = symbol_expr_alloc(&@$, $1); xfree($1); } + | '$' identifier + { + $$ = symbol_expr_alloc(&@$, $2); + $$->scope = current_scope(state); + xfree($2); + } ; integer_expr : NUM @@ -985,17 +997,18 @@ expr : concat_expr | multiton_expr ; +initializer_expr : expr + | set_expr + | list_expr + ; + match_expr : relational_expr | membership_expr ; relational_expr : expr /* implicit */ expr { - enum ops op; - - /* RHS determines operation */ - op = ($2->ops->type == EXPR_RANGE) ? OP_RANGE : OP_EQ; - $$ = relational_expr_alloc(&@$, op, $1, $2); + $$ = relational_expr_alloc(&@$, OP_IMPLICIT, $1, $2); } | expr /* implicit */ list_expr { diff --git a/src/scanner.l b/src/scanner.l index 3b22bb9e..7fc01f77 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -207,6 +207,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "-" { return DASH; } "*" { return ASTERISK; } "@" { return AT; } +"$" { return '$'; } +"=" { return '='; } "=>" { return ARROW; } "map" { return MAP; } "vmap" { return VMAP; } @@ -219,6 +221,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "NF_INET_POST_ROUTING" { yylval->val = NF_INET_POST_ROUTING; return HOOKNUM; } "include" { return INCLUDE; } +"define" { return DEFINE; } "describe" { return DESCRIBE; } |