Filters: permit variables of prefix types, cleanup around
variables. TODO list added, hopefully complete. Use new features of filters in bird.conf
This commit is contained in:
parent
c79ec2ec19
commit
d3dd620b96
4 changed files with 110 additions and 60 deletions
41
bird.conf
41
bird.conf
|
@ -13,7 +13,7 @@ function callme (int arg1; int arg2;)
|
||||||
print "Function callme called arguments " arg1 " and " arg2;
|
print "Function callme called arguments " arg1 " and " arg2;
|
||||||
|
|
||||||
case arg1 {
|
case arg1 {
|
||||||
2: { print "dva"; print "jeste jednou dva"; }
|
2: print "dva"; print "jeste jednou dva";
|
||||||
[ 3 .. 5 ]: print "tri az pet";
|
[ 3 .. 5 ]: print "tri az pet";
|
||||||
else: print "neco jineho";
|
else: print "neco jineho";
|
||||||
}
|
}
|
||||||
|
@ -22,37 +22,30 @@ function callme (int arg1; int arg2;)
|
||||||
function startup ()
|
function startup ()
|
||||||
int i;
|
int i;
|
||||||
prefix px;
|
prefix px;
|
||||||
|
|
||||||
{
|
{
|
||||||
print "Bird filter language: selftesting...";
|
print "Testing filter language:";
|
||||||
i = 4;
|
i = 4;
|
||||||
i = 1230 + i;
|
i = 1230 + i;
|
||||||
print "Testing arithmetics: 1234 = " i;
|
print " arithmetics: 1234 = " i;
|
||||||
if i = 4 then { print "*** FAIL: if 0"; quitbird; } else print "test 1 passed";
|
printn " if statements ";
|
||||||
if 1234 = i then print "test 2 passed"; else { print "*** FAIL: if 1 else"; }
|
if i = 4 then { print "*** FAIL: if 0"; quitbird; } else printn ".";
|
||||||
if 1 <= 1 then print "test 3 passed"; else { print "*** FAIL: test 3"; }
|
if 1234 = i then printn "."; else { print "*** FAIL: if 1 else"; }
|
||||||
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "test 4 passed";
|
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
||||||
|
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
||||||
|
|
||||||
print "Testing IP addresses: 1.2.3.4 = " 1.2.3.4;
|
print " data types; must be true: " 1.2.3.4 = 1.2.3.4 "," 1 ~ [1,2,3] "," 5 ~ [1..20] "," 2 ~ [ 1, 2, 3 ] "," 5 ~ [ 4 .. 7 ] "," 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ];
|
||||||
print "Testing sets of ints = " [ 1, 2, 3 ];
|
print " data types: must be false: " 1 ~ [ 2, 3, 4 ] "," 5 ~ [ 2, 3, 4, 7..11 ] "," 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ] "," (1,2) > (2,2) "," (1,1) > (1,1);
|
||||||
print "Testing sets of ints = " [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ];
|
|
||||||
print "Testing sets of IPs = " [ 1.2.3.4, 2.3.4.5, 3.4.5.6 ];
|
|
||||||
print "Sets: true = " 1 ~ [ 1, 2, 3 ];
|
|
||||||
print " false = " 1 ~ [ 2, 3, 4 ];
|
|
||||||
print "a..b: true = " 5 ~ [ 4 .. 7 ];
|
|
||||||
print " false = " 5 ~ [ 2, 3, 4, 7..11 ];
|
|
||||||
print "IPsets: true = " 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ];
|
|
||||||
print " false = " 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ];
|
|
||||||
|
|
||||||
print "Testing prefixes: 1.2.3.4/18 = " 1.2.3.4/18;
|
px = 1.2.3.4/18;
|
||||||
|
print "Testing prefixes: 1.2.3.4/18 = " px;
|
||||||
print "Testing pairs: (1,2) = " (1,2);
|
print "Testing pairs: (1,2) = " (1,2);
|
||||||
|
|
||||||
print "Testing functions...";
|
print "Testing functions...";
|
||||||
callme ( 1, 2, );
|
callme ( 1, 2 );
|
||||||
callme ( 2, 2, );
|
callme ( 2, 2 );
|
||||||
callme ( 3, 2, );
|
callme ( 3, 2 );
|
||||||
callme ( 4, 2, );
|
callme ( 4, 2 );
|
||||||
callme ( 7, 2, );
|
callme ( 7, 2 );
|
||||||
|
|
||||||
print "done";
|
print "done";
|
||||||
quitbird;
|
quitbird;
|
||||||
|
|
|
@ -5,16 +5,13 @@
|
||||||
*
|
*
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*
|
*
|
||||||
FIXME: prefix variables, make prefix.ip and prefix.length work
|
|
||||||
FIXME: define keyword
|
FIXME: define keyword
|
||||||
FIXME: case without { }'s
|
FIXME: make px+, px- px^pair work in prefix sets
|
||||||
FIXME: allow px+, px- px^pair in prefix sets
|
|
||||||
FIXME: create ip.mask(x) function
|
FIXME: create ip.mask(x) function
|
||||||
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
|
FIXME: whole system of paths, path ~ string, path.prepend(), path.originate
|
||||||
FIXME: create community lists
|
FIXME: create community lists
|
||||||
FIXME: access to dynamic attributes
|
FIXME: access to dynamic attributes
|
||||||
FIXME: do not allow function call by callme(1,2,)
|
FIXME: make case faster
|
||||||
FIXME: pairs of integers: define compare
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
@ -29,12 +26,12 @@ CF_HDR
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(FUNCTION, PRINT, CONST,
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST,
|
||||||
ACCEPT, REJECT, ERROR, QUITBIRD,
|
ACCEPT, REJECT, ERROR, QUITBIRD,
|
||||||
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
INT, BOOL, IP, PREFIX, PAIR, SET, STRING,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE,
|
TRUE, FALSE,
|
||||||
RTA, FROM, GW, NET,
|
RTA, FROM, GW, NET, MASK,
|
||||||
LEN,
|
LEN,
|
||||||
IMPOSSIBLE,
|
IMPOSSIBLE,
|
||||||
FILTER
|
FILTER
|
||||||
|
@ -42,9 +39,9 @@ CF_KEYWORDS(FUNCTION, PRINT, CONST,
|
||||||
|
|
||||||
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body
|
%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body
|
||||||
%type <f> filter filter_body
|
%type <f> filter filter_body
|
||||||
%type <i> type break_command
|
%type <i> type break_command pair
|
||||||
%type <e> set_item set_items
|
%type <e> set_item set_items
|
||||||
%type <v> set_atom
|
%type <v> set_atom prefix prefix_s ipa
|
||||||
%type <s> decls function_params
|
%type <s> decls function_params
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
@ -80,6 +77,12 @@ decls: /* EMPTY */ { $$ = NULL; }
|
||||||
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
|
||||||
printf( "New variable %s type %x\n", $2->name, $1 );
|
printf( "New variable %s type %x\n", $2->name, $1 );
|
||||||
$2->aux = $4;
|
$2->aux = $4;
|
||||||
|
{
|
||||||
|
struct f_val * val;
|
||||||
|
val = cfg_alloc(sizeof(struct f_val));
|
||||||
|
val->type = $1;
|
||||||
|
$2->aux2 = val;
|
||||||
|
}
|
||||||
$$=$2;
|
$$=$2;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -146,10 +149,36 @@ block:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple types, their bison value is int
|
||||||
|
*/
|
||||||
|
pair:
|
||||||
|
'(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complex types, their bison value is struct f_val
|
||||||
|
*/
|
||||||
|
prefix_s:
|
||||||
|
IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; printf( "ook, we have prefix here\n" ); }
|
||||||
|
;
|
||||||
|
|
||||||
|
prefix:
|
||||||
|
prefix_s { $$ = $1; }
|
||||||
|
| prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
|
||||||
|
| prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
|
||||||
|
/* | prefix_s '{' NUM ',' NUM '}' How should this be done? */
|
||||||
|
;
|
||||||
|
|
||||||
|
ipa:
|
||||||
|
IPA { $$.type = T_IP; $$.val.ip = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
set_atom:
|
set_atom:
|
||||||
NUM { $$.type = T_INT; $$.val.i = $1; }
|
NUM { $$.type = T_INT; $$.val.i = $1; }
|
||||||
| IPA { $$.type = T_IP; $$.val.ip = $1; }
|
| pair { $$.type = T_PAIR; $$.val.i = $1; }
|
||||||
|
| ipa { $$ = $1; }
|
||||||
|
| prefix { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
set_item:
|
set_item:
|
||||||
|
@ -162,15 +191,16 @@ set_items:
|
||||||
| set_items ',' set_item { $$ = $3; $$->left = $1; }
|
| set_items ',' set_item { $$ = $3; $$->left = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
constant:
|
constant:
|
||||||
CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
|
CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; }
|
||||||
| NUM { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $1; }
|
| NUM { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $1; }
|
||||||
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1; }
|
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1; }
|
||||||
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0; }
|
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0; }
|
||||||
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
|
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; }
|
||||||
| '(' NUM ',' NUM ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $2 << 16 | $4; }
|
| pair { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $1; }
|
||||||
| IPA { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.ip = $1; }
|
| ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| IPA '/' NUM { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_PREFIX; val->val.px.ip = $1; val->val.px.len = $3; printf( "ook, we have prefix here\n" ); }
|
| prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
|
||||||
| '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); }
|
| '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -188,9 +218,11 @@ term:
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
switch ($1->class) {
|
switch ($1->class) {
|
||||||
case SYM_VARIABLE | T_INT:
|
case SYM_VARIABLE | T_INT:
|
||||||
$$->code = 'i';
|
case SYM_VARIABLE | T_PAIR:
|
||||||
$$->a1.i = T_INT;
|
case SYM_VARIABLE | T_PREFIX:
|
||||||
$$->a2.p = &($1->aux);
|
case SYM_VARIABLE | T_IP:
|
||||||
|
$$->code = 'C';
|
||||||
|
$$->a1.p = $1->aux2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cf_error("Can not use this class of symbol as variable." );
|
cf_error("Can not use this class of symbol as variable." );
|
||||||
|
@ -204,6 +236,7 @@ term:
|
||||||
|
|
||||||
| term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
|
| term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; }
|
||||||
| term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
|
| term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; }
|
||||||
|
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; }
|
||||||
;
|
;
|
||||||
|
|
||||||
break_command:
|
break_command:
|
||||||
|
@ -212,6 +245,7 @@ break_command:
|
||||||
| REJECT { $$ = F_REJECT }
|
| REJECT { $$ = F_REJECT }
|
||||||
| ERROR { $$ = F_ERROR }
|
| ERROR { $$ = F_ERROR }
|
||||||
| PRINT { $$ = F_NOP }
|
| PRINT { $$ = F_NOP }
|
||||||
|
| PRINTN { $$ = F_NONL }
|
||||||
;
|
;
|
||||||
|
|
||||||
ifthen:
|
ifthen:
|
||||||
|
@ -236,7 +270,13 @@ print_list: /* EMPTY */ { $$ = NULL; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
var_list: /* EMPTY */ { $$ = NULL; }
|
var_list: term {
|
||||||
|
$$ = f_new_inst();
|
||||||
|
$$->code = 's';
|
||||||
|
$$->a1.p = NULL;
|
||||||
|
$$->a2.p = $1;
|
||||||
|
$$->next = NULL;
|
||||||
|
}
|
||||||
| term ',' var_list {
|
| term ',' var_list {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 's';
|
$$->code = 's';
|
||||||
|
@ -246,15 +286,16 @@ var_list: /* EMPTY */ { $$ = NULL; }
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */
|
||||||
switch_body: /* EMPTY */ { $$ = NULL; }
|
switch_body: /* EMPTY */ { $$ = NULL; }
|
||||||
| term ':' block switch_body {
|
| term ':' cmds switch_body {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 'of';
|
$$->code = 'of';
|
||||||
$$->a1.p = $1;
|
$$->a1.p = $1;
|
||||||
$$->a2.p = $3;
|
$$->a2.p = $3;
|
||||||
$$->next = $4;
|
$$->next = $4;
|
||||||
}
|
}
|
||||||
| ELSE ':' block {
|
| ELSE ':' cmds {
|
||||||
$$ = f_new_inst();
|
$$ = f_new_inst();
|
||||||
$$->code = 'el';
|
$$->code = 'el';
|
||||||
$$->a1.p = NULL;
|
$$->a1.p = NULL;
|
||||||
|
|
|
@ -58,6 +58,7 @@ val_compare(struct f_val v1, struct f_val v2)
|
||||||
return CMP_ERROR;
|
return CMP_ERROR;
|
||||||
switch (v1.type) {
|
switch (v1.type) {
|
||||||
case T_INT:
|
case T_INT:
|
||||||
|
case T_PAIR:
|
||||||
if (v1.val.i == v2.val.i) return 0;
|
if (v1.val.i == v2.val.i) return 0;
|
||||||
if (v1.val.i < v2.val.i) return -1;
|
if (v1.val.i < v2.val.i) return -1;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -209,31 +210,32 @@ interpret(struct f_inst *what)
|
||||||
runtime( "~ applied on unknown type pair" );
|
runtime( "~ applied on unknown type pair" );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Set to consant, a1 = type, a2 = value */
|
/* Set to indirect value, a1 = variable, a2 = value */
|
||||||
case 's':
|
case 's':
|
||||||
ARG(v2, a2.p);
|
ARG(v2, a2.p);
|
||||||
sym = what->a1.p;
|
sym = what->a1.p;
|
||||||
switch (res.type = v2.type) {
|
switch (res.type = v2.type) {
|
||||||
case T_VOID: runtime( "Can not assign void values" );
|
case T_VOID: runtime( "Can not assign void values" );
|
||||||
case T_INT:
|
case T_INT:
|
||||||
if (sym->class != (SYM_VARIABLE | T_INT))
|
case T_IP:
|
||||||
|
case T_PREFIX:
|
||||||
|
case T_PAIR:
|
||||||
|
if (sym->class != (SYM_VARIABLE | v2.type))
|
||||||
runtime( "Variable of bad type" );
|
runtime( "Variable of bad type" );
|
||||||
sym->aux = v2.val.i;
|
* (struct f_val *) sym->aux2 = v2;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
bug( "Set to invalid type\n" );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c': /* integer (or simple type) constant */
|
||||||
res.type = what->a1.i;
|
res.type = what->a1.i;
|
||||||
res.val.i = (int) what->a2.p;
|
res.val.i = what->a2.i;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
res = * ((struct f_val *) what->a1.p);
|
res = * ((struct f_val *) what->a1.p);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
|
||||||
res.type = what->a1.i;
|
|
||||||
res.val.i = * ((int *) what->a2.p);
|
|
||||||
break;
|
|
||||||
case 'p':
|
case 'p':
|
||||||
ONEARG;
|
ONEARG;
|
||||||
val_print(v1);
|
val_print(v1);
|
||||||
|
@ -253,7 +255,8 @@ interpret(struct f_inst *what)
|
||||||
break;
|
break;
|
||||||
case 'p,':
|
case 'p,':
|
||||||
ONEARG;
|
ONEARG;
|
||||||
printf( "\n" );
|
if (what->a2.i != F_NONL)
|
||||||
|
printf( "\n" );
|
||||||
|
|
||||||
switch (what->a2.i) {
|
switch (what->a2.i) {
|
||||||
case F_QUITBIRD:
|
case F_QUITBIRD:
|
||||||
|
@ -265,6 +268,7 @@ interpret(struct f_inst *what)
|
||||||
res.type = T_RETURN;
|
res.type = T_RETURN;
|
||||||
res.val.i = what->a1.i;
|
res.val.i = what->a1.i;
|
||||||
break;
|
break;
|
||||||
|
case F_NONL:
|
||||||
case F_NOP:
|
case F_NOP:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -309,6 +313,10 @@ interpret(struct f_inst *what)
|
||||||
ONEARG;
|
ONEARG;
|
||||||
interpret_switch(what->a2.p, v1);
|
interpret_switch(what->a2.p, v1);
|
||||||
break;
|
break;
|
||||||
|
case 'iM': /* IP.MASK(val) */
|
||||||
|
TWOARGS_C;
|
||||||
|
bug( "Should implement ip.mask\n" );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@ struct f_inst { /* Instruction */
|
||||||
struct prefix {
|
struct prefix {
|
||||||
ip_addr ip;
|
ip_addr ip;
|
||||||
int len;
|
int len;
|
||||||
|
#define LEN_MASK 0xff
|
||||||
|
#define LEN_PLUS 0x10000
|
||||||
|
#define LEN_MINUS 0x20000
|
||||||
|
#define LEN_RANGE 0x40000
|
||||||
|
/* If range then prefix must be in range (len >> 8 & 0xff, len & 0xff) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct f_val {
|
struct f_val {
|
||||||
|
@ -66,11 +71,12 @@ int val_compare(struct f_val v1, struct f_val v2);
|
||||||
void val_print(struct f_val v);
|
void val_print(struct f_val v);
|
||||||
|
|
||||||
#define F_NOP 0
|
#define F_NOP 0
|
||||||
#define F_ACCEPT 1 /* Need to preserve ordering: accepts < rejects! */
|
#define F_NONL 1
|
||||||
#define F_MODIFY 2 /* FIXME: Introduce modification flags instead? */
|
#define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */
|
||||||
#define F_REJECT 3
|
#define F_MODIFY 3 /* FIXME: Introduce modification flags instead? */
|
||||||
#define F_ERROR 4
|
#define F_REJECT 4
|
||||||
#define F_QUITBIRD 5
|
#define F_ERROR 5
|
||||||
|
#define F_QUITBIRD 6
|
||||||
|
|
||||||
#define FILTER_ACCEPT NULL
|
#define FILTER_ACCEPT NULL
|
||||||
#define FILTER_REJECT ((void *) 1)
|
#define FILTER_REJECT ((void *) 1)
|
||||||
|
@ -101,4 +107,6 @@ struct f_tree {
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue