summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bird.conf17
-rw-r--r--conf/conf.h3
-rw-r--r--filter/config.Y177
-rw-r--r--filter/f-util.c11
-rw-r--r--filter/filter.h20
5 files changed, 122 insertions, 106 deletions
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;
-
- printdebug;
- i = 5;
- print( i );
- printdebug;
- i = 1234;
- print( i );
- printdebug;
-}
+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 ); }
+
-/*
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 <x> term
-%type <x> block
-%type <x> cmds
+%type <x> term block cmds cmd function_body
%type <f> filter filter_body
+%type <i> 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
;
-/* Programs */
+function_params:
+ '(' decls ')' { printf( "Have function parameters\n" ); }
+ ;
-cmds:
- term {
- if ($1) {
- $1->next = NULL;
- $$ = $1;
- } else $$ = NULL;
+function_body:
+ decls '{' cmds '}' {
+ $$ = $3;
}
- | term ';' cmds {
+ ;
+
+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: /* EMPTY */ { $$ = NULL; }
+ | cmd cmds {
if ($1) {
- $1->next = $3;
+ $1->next = $2;
$$ = $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 {
+ | PRINTDEBUG ';' {
$$ = f_new_inst();
- $$->code = '!';
- (int) $$->arg1 = F_REJECT;
+ $$->code = 'D';
+ $$->arg1 = $$->arg2 = NULL;
}
- | ERROR {
+ | break_command ';' {
$$ = f_new_inst();
$$->code = '!';
- (int) $$->arg1 = F_ERROR;
+ (int) $$->arg1 = $1;
}
- | PRINTDEBUG {
- $$ = f_new_inst();
- $$->code = 'D';
- $$->arg1 = $$->arg2 = NULL;
- }
;
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