]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filters are now a tiny bit stronger (if is actually working ;-)
authorPavel Machek <pavel@ucw.cz>
Mon, 8 Mar 1999 20:30:06 +0000 (20:30 +0000)
committerPavel Machek <pavel@ucw.cz>
Mon, 8 Mar 1999 20:30:06 +0000 (20:30 +0000)
conf/confbase.Y
filter/config.Y
filter/f-util.c
filter/filter.h

index a5d6838216ce3594b52c7ce781af16c24be20e73..aa46e51d991f3679fda6ff123448b2e22bdb0b26 100644 (file)
@@ -25,7 +25,7 @@ CF_DECLS
   ip_addr a;
   struct symbol *s;
   char *t;
-  struct f_instruction *x; 
+  struct f_inst *x; 
 }
 
 %token END
index 73a75888a84b9282099a251887a8d798e127cab3..bdaedaaf9b19021a8140488807bc0cd05cd6fe6c 100644 (file)
@@ -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';
index 66bf5f1bb716fb351d3db9a5f40b240a19ccf0a1..ba748041a31e5010a7c64e7a6e0c011c4d7bfb76 100644 (file)
 #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;
index aed264739e29360025c644fb232ee7904bc63729..e0f4723034fc5f2f5cbaf0e52cf0580e6b97774d 100644 (file)
 
 #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