diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 51 | ||||
-rw-r--r-- | filter/f-util.c | 85 | ||||
-rw-r--r-- | filter/filter.h | 19 |
3 files changed, 128 insertions, 27 deletions
diff --git a/filter/config.Y b/filter/config.Y index 73a75888..bdaedaaf 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -19,7 +19,7 @@ CF_HDR CF_DECLS -CF_KEYWORDS(FUNCTION, FILTER, PRINTDEBUG, INT, PRINT) +CF_KEYWORDS(FUNCTION, FILTER, PRINTDEBUG, INT, PRINT, CONST, VAR, PUTS, DIE, IF) %type <x> term %type <x> cmds @@ -29,7 +29,7 @@ CF_GRAMMAR CF_ADDTO(conf, function) function: FUNCTION SYM '(' ')' '{' cmds '}' { - extern struct f_instruction *last_func; + extern struct f_inst *last_func; if ($2->class != SYM_VOID) cf_error("Symbol already defined" ); $2->class = SYM_FUNCTION; $2->def = $6; @@ -69,13 +69,47 @@ term: /* EMPTY */ { $$ = NULL; } + | term '+' term { + $$ = f_new_inst(); + $$->code = '+'; + $$->arg1 = $1; + $$->arg2 = $3; + } + | IF '(' term ')' '{' cmds '}' { + $$ = f_new_inst(); + $$->code = '?'; + $$->arg1 = $3; + $$->arg2 = $6; + } + | IF '(' term ')' term { + $$ = f_new_inst(); + $$->code = '?'; + $$->arg1 = $3; + $$->arg2 = $5; + } | INT SYM { if ($2->class != SYM_VOID) cf_error("Symbol already defined, can not use as variable\n" ); $2->class = SYM_VARIABLE_INT; printf( "New variable\n" ); $$ = NULL; } - | SYM '=' expr { + | VAR '(' SYM ')' { + $$ = f_new_inst(); + switch ($3->class) { + case SYM_VARIABLE_INT: + $$->code = 'i'; + $$->arg1 = &($3->aux); + break; + default: + cf_error("Can not use this class of symbol as variable" ); + } + } + | CONST '(' expr ')' { + $$ = f_new_inst(); + $$->code = 'c'; + $$->arg1 = $3; + } + | SYM '=' term { $$ = f_new_inst(); printf( "Ook, we'll set value\n" ); if ($1->class != SYM_VARIABLE_INT) @@ -84,13 +118,22 @@ term: $$->arg1 = $1; $$->arg2 = $3; } - | PRINT '(' SYM ')' { + | PRINT '(' term ')' { $$ = f_new_inst(); printf( "Ook, we'll print something\n" ); $$->code = 'p'; $$->arg1 = $3; $$->arg2 = NULL; } + | PUTS '(' TEXT ')' { + $$ = f_new_inst(); + $$->code = 'd'; + $$->arg1 = $3; + } + | DIE { + $$ = f_new_inst(); + $$->code = '!'; + } | PRINTDEBUG { $$ = f_new_inst(); $$->code = 'D'; diff --git a/filter/f-util.c b/filter/f-util.c index 66bf5f1b..ba748041 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -21,33 +21,73 @@ #include "conf/conf.h" #include "filter/filter.h" -struct f_instruction *last_func = NULL; +struct f_inst *last_func = NULL; -static void -interpret(struct f_instruction *what) +#define runtime die + +static struct f_val +interpret(struct f_inst *what) { struct symbol *sym; + struct f_val v1, v2, res; + + res.type = T_VOID; if (!what) - return; + return res; + switch(what->code) { case ',': interpret(what->arg1); interpret(what->arg2); break; + case '+': + v1 = interpret(what->arg1); + v2 = interpret(what->arg2); + if (v1.type != v2.type) + runtime( "Can not operate with values of incompatible types" ); + + switch (res.type = v1.type) { + case T_VOID: runtime( "Can not operate with values of type void" ); + case T_INT: res.val.i = v1.val.i + v2.val.i; break; + default: runtime( "Usage of unknown type" ); + } + break; case '=': + v1 = interpret(what->arg2); sym = what->arg1; - sym->aux = (int) what->arg2; + switch (res.type = v1.type) { + case T_VOID: runtime( "Can not assign void values" ); + case T_INT: + if (sym->class != SYM_VARIABLE_INT) + runtime( "Variable of bad type" ); + sym->aux = v1.val.i; + break; + } + break; + case 'c': + res.type = T_INT; + res.val.i = (int) what->arg1; + break; + case 'i': + res.type = T_INT; + res.val.i = * ((int *) what->arg1); break; case 'p': - sym = what->arg1; - switch(sym->class) { - case SYM_VARIABLE_INT: - printf( "Printing: %d\n", sym->aux ); - break; - default: - printf( "Unknown type passed to print\n" ); - break; + v1 = interpret(what->arg1); + printf( "Printing: " ); + switch (v1.type) { + case T_VOID: printf( "(void)" ); break; + case T_INT: printf( "%d", v1.val.i ); break; + default: runtime( "Print of variable of unknown type" ); } + printf( "\n" ); + break; + case '?': + v1 = interpret(what->arg1); + if (v1.type != T_INT) + runtime( "If requires integer expression" ); + if (v1.val.i) + res = interpret(what->arg2); break; case 'D': printf( "DEBUGGING PRINT\n" ); @@ -55,8 +95,17 @@ interpret(struct f_instruction *what) case '0': printf( "No operation\n" ); break; + case 'd': + printf( "Puts: %s\n", what->arg1 ); + break; + case '!': + die( "Filter asked me to die" ); + default: + die( "Unknown insruction %d(%c)", what->code, what->code & 0xff); } - interpret(what->next); + if (what->next) + return interpret(what->next); + return res; } void @@ -69,11 +118,11 @@ filters_postconfig(void) } } -struct f_instruction * +struct f_inst * f_new_inst(void) { - struct f_instruction * ret; - ret = cfg_alloc(sizeof(struct f_instruction)); + struct f_inst * ret; + ret = cfg_alloc(sizeof(struct f_inst)); ret->code = 0; ret->arg1 = ret->arg2 = ret->next = NULL; return ret; @@ -82,7 +131,7 @@ f_new_inst(void) int f_run(struct symbol *filter, struct rte *rtein, struct rte **rteout) { - struct f_instruction *inst; + struct f_inst *inst; debug( "Running filter `%s'...", filter->name ); inst = filter->def; diff --git a/filter/filter.h b/filter/filter.h index aed26473..e0f47230 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -11,19 +11,28 @@ #include "lib/resource.h" -/* Lexer */ - -struct f_instruction { - struct f_instruction *next; /* Structure is 16 bytes, anyway */ +struct f_inst { /* Instruction */ + struct f_inst *next; /* Structure is 16 bytes, anyway */ int code; void *arg1, *arg2; }; +struct f_val { + int type; + union { + int i; + } val; +}; + void filters_postconfig(void); -struct f_instruction *f_new_inst(void); +struct f_inst *f_new_inst(void); #define F_ACCEPT 1 #define F_REJECT 2 #define F_MODIFY 3 +#define T_VOID 0 +#define T_INT 1 +#define T_PX 2 + #endif |