diff --git a/bird.conf b/bird.conf index 09b03d43..1b5b5347 100644 --- a/bird.conf +++ b/bird.conf @@ -8,19 +8,11 @@ router id 62.168.0.1 define xyzzy = 120+10 -function test() { - int i; +function startup () int i; { printdebug; printdebug; i = 5; print( i ); i = 1234 + i; print( i ); if 0 then { puts( "You must not ever see this" ); quitbird; } print( 2 ); if 1 then puts( "jedna dve honza jde" ); quitbird; } + +filter testf int j; { j = const(4321); print( j ); } - printdebug; - i = 5; - print( i ); - printdebug; - i = 1234; - print( i ); - printdebug; -} -/* protocol rip MyRIP_test { preference xyzzy debug all @@ -29,7 +21,6 @@ protocol rip MyRIP_test { garbagetime 30 interface "*" } -*/ protocol device { disabled diff --git a/conf/conf.h b/conf/conf.h index 5ceb4af0..83d92c3f 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -58,10 +58,11 @@ struct symbol { #define SYM_PROTO 1 #define SYM_NUMBER 2 #define SYM_STAT 3 /* statement */ -#define SYM_VARIABLE_INT 4 #define SYM_FUNCTION 5 #define SYM_FILTER 6 +#define SYM_VARIABLE 0x100 /* Reserved 0x100..0x1ff */ + extern int conf_lino; void cf_lex_init_tables(void); diff --git a/filter/config.Y b/filter/config.Y index 6d51dc74..de178e7c 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -18,29 +18,19 @@ CF_HDR CF_DECLS -CF_KEYWORDS(FUNCTION, FILTER, PRINTDEBUG, INT, PRINT, CONST, VAR, PUTS, IF, - ACCEPT, REJECT, ERROR, QUITBIRD) +CF_KEYWORDS(FUNCTION, PRINTDEBUG, PRINT, CONST, PUTS, + ACCEPT, REJECT, ERROR, QUITBIRD, + INT, BOOL, IP, PREFIX, PAIR, SET, STRING, + IF, THEN, + FILTER + ) -%type term -%type block -%type cmds +%type term block cmds cmd function_body %type filter filter_body +%type type break_command CF_GRAMMAR -CF_ADDTO(conf, function) -function: - FUNCTION SYM '(' ')' '{' cmds '}' { - extern struct f_inst *autoexec_func; - if ($2->class != SYM_VOID) cf_error("Symbol already defined" ); - $2->class = SYM_FUNCTION; - $2->def = $6; - if (!strcasecmp($2->name, "autoexec")) - autoexec_func = $6; - printf("Hmm, we've got one function here\n"); - } - ; - CF_ADDTO(conf, filter_def) filter_def: FILTER SYM filter_body { @@ -52,11 +42,36 @@ filter_def: } ; +type: + INT { $$ = T_INT; } + | BOOL { $$ = T_BOOL; } + | IP { $$ = T_IP; } + | PREFIX { $$ = T_PREFIX; } + | PAIR { $$ = T_PAIR; } + | STRING { $$ = T_STRING; } + | type SET { + switch ($1) { + default: + cf_error( "You can not create sets of this type\n" ); + case T_INT: case T_IP: case T_PREFIX: case T_PAIR: + } + $$ = $1 | T_SET; + } + ; + +decls: /* EMPTY */ + | type SYM ';' decls { + if ($2->class != SYM_VOID) cf_error("Symbol already defined, can not use as variable\n" ); + $2->class = SYM_VARIABLE | $1; + printf( "New variable %s type %x\n", $2->name, $1 ); + } + ; + filter_body: - '{' cmds '}' { + function_body { struct filter *f = cfg_alloc(sizeof(struct filter)); f->name = NULL; - f->root = $2; + f->root = $1; $$ = f; } ; @@ -69,25 +84,42 @@ filter: | filter_body ; +function_params: + '(' decls ')' { printf( "Have function parameters\n" ); } + ; + +function_body: + decls '{' cmds '}' { + $$ = $3; + } + ; + +CF_ADDTO(conf, function_def) +function_def: + FUNCTION SYM function_params function_body { + extern struct f_inst *startup_func; + if ($2->class != SYM_VOID) cf_error("Symbol already defined" ); + $2->class = SYM_FUNCTION; + $2->def = $4; + if (!strcasecmp($2->name, "startup")) + startup_func = $4; + printf("Hmm, we've got one function here - %s\n", $2->name); + } + ; + /* Programs */ -cmds: - term { +cmds: /* EMPTY */ { $$ = NULL; } + | cmd cmds { if ($1) { - $1->next = NULL; + $1->next = $2; $$ = $1; - } else $$ = NULL; - } - | term ';' cmds { - if ($1) { - $1->next = $3; - $$ = $1; - } else $$ = $3; + } else $$ = $2; } ; block: - term ';' { + cmd { $$=$1; } | '{' cmds '}' { @@ -96,31 +128,16 @@ block: ; term: - /* EMPTY */ { - $$ = NULL; - } - | term '+' term { + term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->arg1 = $1; $$->arg2 = $3; } - | IF '(' term ')' block { - $$ = 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 { $$ = f_new_inst(); switch ($1->class) { - case SYM_VARIABLE_INT: + case SYM_VARIABLE | T_INT: $$->code = 'i'; $$->arg1 = &($1->aux); break; @@ -128,73 +145,63 @@ term: cf_error("Can not use this class of symbol as variable" ); } } - | VAR '(' SYM ')' { + | CONST '(' expr ')' { $$ = 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" ); - } + $$->code = 'c'; + $$->arg1 = $3; } | NUM { $$ = f_new_inst(); $$->code = 'c'; $$->arg1 = $1 } - | CONST '(' expr ')' { + ; + +break_command: + QUITBIRD { $$ = F_QUITBIRD } + | ACCEPT { $$ = F_ACCEPT } + | REJECT { $$ = F_REJECT } + | ERROR { $$ = F_ERROR } + ; + +cmd: + IF term THEN block { $$ = f_new_inst(); - $$->code = 'c'; - $$->arg1 = $3; + $$->code = '?'; + $$->arg1 = $2; + $$->arg2 = $4; } - | SYM '=' term { + | SYM '=' term ';' { $$ = f_new_inst(); printf( "Ook, we'll set value\n" ); - if ($1->class != SYM_VARIABLE_INT) - cf_error( "You may only set variables\n" ); + if (($1->class & ~T_MASK) != SYM_VARIABLE) + cf_error( "You may only set variables, and this is %x.\n", $1->class ); $$->code = '='; $$->arg1 = $1; $$->arg2 = $3; } - | PRINT '(' term ')' { + | PRINT '(' term ')' ';' { $$ = f_new_inst(); printf( "Ook, we'll print something\n" ); $$->code = 'p'; $$->arg1 = $3; $$->arg2 = NULL; } - | PUTS '(' TEXT ')' { + | PUTS '(' TEXT ')' ';' { $$ = f_new_inst(); $$->code = 'd'; $$->arg1 = $3; } - | QUITBIRD { - $$ = f_new_inst(); - $$->code = '!'; - (int) $$->arg1 = F_QUITBIRD; - } - | ACCEPT { - $$ = f_new_inst(); - $$->code = '!'; - (int) $$->arg1 = F_ACCEPT; - } - | REJECT { - $$ = f_new_inst(); - $$->code = '!'; - (int) $$->arg1 = F_REJECT; - } - | ERROR { - $$ = f_new_inst(); - $$->code = '!'; - (int) $$->arg1 = F_ERROR; - } - | PRINTDEBUG { + | PRINTDEBUG ';' { $$ = f_new_inst(); $$->code = 'D'; $$->arg1 = $$->arg2 = NULL; - } + } + | break_command ';' { + $$ = f_new_inst(); + $$->code = '!'; + (int) $$->arg1 = $1; + } ; CF_END diff --git a/filter/f-util.c b/filter/f-util.c index 1f757ff4..ee7ea2de 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -22,7 +22,7 @@ #include "conf/conf.h" #include "filter/filter.h" -struct f_inst *autoexec_func = NULL; +struct f_inst *startup_func = NULL; #define runtime(x) do { \ log( L_ERR, x ); \ @@ -71,7 +71,7 @@ interpret(struct f_inst *what) switch (res.type = v2.type) { case T_VOID: runtime( "Can not assign void values" ); case T_INT: - if (sym->class != SYM_VARIABLE_INT) + if (sym->class != (SYM_VARIABLE | T_INT)) runtime( "Variable of bad type" ); sym->aux = v2.val.i; break; @@ -163,6 +163,9 @@ f_run(struct filter *filter, struct rte *rtein, struct rte **rteout) void filters_postconfig(void) { - if (autoexec_func) - interpret(autoexec_func); + printf( "Launching startup function..." ); + if (startup_func) + interpret(startup_func); + printf( "done\n" ); + exit(0); } diff --git a/filter/filter.h b/filter/filter.h index 379a4ac9..ba8dc853 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -40,10 +40,24 @@ int f_run(struct filter *filter, struct rte *rtein, struct rte **rteout); #define F_ERROR 4 #define F_QUITBIRD 5 +/* Type numbers must be in 0..0xff range */ +#define T_MASK 0xff + +/* Internal types */ #define T_VOID 0 #define T_RETURN 1 -#define T_INT 10 -#define T_PX 11 /* prefix */ -#define T_INTLIST 12 + +/* User visible types, which fit in int */ +#define T_INT 0x10 +#define T_BOOL 0x11 +#define T_PAIR 0x12 +#define T_ENUM 0x13 + +/* Bigger ones */ +#define T_IP 0x20 +#define T_PREFIX 0x21 +#define T_STRING 0x22 + +#define T_SET 0x80 #endif