version 1.1.1.1, 2017/08/22 12:33:54
|
version 1.1.1.2, 2021/03/17 19:50:23
|
Line 12 CF_HDR
|
Line 12 CF_HDR
|
|
|
CF_DEFINES |
CF_DEFINES |
|
|
#define P(a,b) ((a << 8) | b) |
|
|
|
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } |
static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } |
static inline u32 pair_a(u32 p) { return p >> 16; } |
static inline u32 pair_a(u32 p) { return p >> 16; } |
static inline u32 pair_b(u32 p) { return p & 0xFFFF; } |
static inline u32 pair_b(u32 p) { return p & 0xFFFF; } |
Line 112 f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf
|
Line 110 f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf
|
{ |
{ |
u64 fm, to; |
u64 fm, to; |
|
|
if (ipv4_used || (key >= 0x10000)) { | if ((kind != EC_GENERIC) && (ipv4_used || (key >= 0x10000))) { |
check_u16(vf); |
check_u16(vf); |
if (vt == EC_ALL) |
if (vt == EC_ALL) |
vt = 0xFFFF; |
vt = 0xFFFF; |
Line 157 f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3,
|
Line 155 f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3,
|
} |
} |
|
|
static inline struct f_inst * |
static inline struct f_inst * |
f_generate_empty(struct f_inst *dyn) | f_generate_empty(struct f_dynamic_attr dyn) |
{ |
{ |
struct f_inst *e = f_new_inst(); | struct f_inst *e = f_new_inst(FI_EMPTY); |
e->code = 'E'; | |
|
|
switch (dyn->aux & EAF_TYPE_MASK) { | switch (dyn.type & EAF_TYPE_MASK) { |
case EAF_TYPE_AS_PATH: |
case EAF_TYPE_AS_PATH: |
e->aux = T_PATH; |
e->aux = T_PATH; |
break; |
break; |
Line 179 f_generate_empty(struct f_inst *dyn)
|
Line 176 f_generate_empty(struct f_inst *dyn)
|
cf_error("Can't empty that attribute"); |
cf_error("Can't empty that attribute"); |
} |
} |
|
|
dyn->code = P('e','S'); | struct f_inst *s = f_new_inst_da(FI_EA_SET, dyn); |
dyn->a1.p = e; | s->a1.p = e; |
return dyn; | return s; |
} |
} |
|
|
|
|
Line 190 f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
|
Line 187 f_generate_dpair(struct f_inst *t1, struct f_inst *t2)
|
{ |
{ |
struct f_inst *rv; |
struct f_inst *rv; |
|
|
if ((t1->code == 'c') && (t2->code == 'c')) { | if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT)) { |
if ((t1->aux != T_INT) || (t2->aux != T_INT)) |
if ((t1->aux != T_INT) || (t2->aux != T_INT)) |
cf_error( "Can't operate with value of non-integer type in pair constructor"); |
cf_error( "Can't operate with value of non-integer type in pair constructor"); |
|
|
check_u16(t1->a2.i); |
check_u16(t1->a2.i); |
check_u16(t2->a2.i); |
check_u16(t2->a2.i); |
|
|
rv = f_new_inst(); | rv = f_new_inst(FI_CONSTANT); |
rv->code = 'c'; | |
rv->aux = T_PAIR; |
rv->aux = T_PAIR; |
rv->a2.i = pair(t1->a2.i, t2->a2.i); |
rv->a2.i = pair(t1->a2.i, t2->a2.i); |
} |
} |
else { |
else { |
rv = f_new_inst(); | rv = f_new_inst(FI_PAIR_CONSTRUCT); |
rv->code = P('m', 'p'); | |
rv->a1.p = t1; |
rv->a1.p = t1; |
rv->a2.p = t2; |
rv->a2.p = t2; |
} |
} |
Line 219 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
Line 214 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
int c1 = 0, c2 = 0, ipv4_used = 0; |
int c1 = 0, c2 = 0, ipv4_used = 0; |
u32 key = 0, val2 = 0; |
u32 key = 0, val2 = 0; |
|
|
if (tk->code == 'c') { | if (tk->fi_code == FI_CONSTANT) { |
c1 = 1; |
c1 = 1; |
|
|
if (tk->aux == T_INT) { |
if (tk->aux == T_INT) { |
Line 234 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
Line 229 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
|
|
#ifndef IPV6 |
#ifndef IPV6 |
/* IP->Quad implicit conversion */ |
/* IP->Quad implicit conversion */ |
else if (tk->code == 'C') { | else if (tk->fi_code == FI_CONSTANT_INDIRECT) { |
c1 = 1; |
c1 = 1; |
struct f_val *val = tk->a1.p; |
struct f_val *val = tk->a1.p; |
|
|
Line 252 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
Line 247 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
} |
} |
#endif |
#endif |
|
|
if (tv->code == 'c') { | if (tv->fi_code == FI_CONSTANT) { |
if (tv->aux != T_INT) |
if (tv->aux != T_INT) |
cf_error("Can't operate with value of non-integer type in EC constructor"); |
cf_error("Can't operate with value of non-integer type in EC constructor"); |
c2 = 1; |
c2 = 1; |
Line 278 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
Line 273 f_generate_ec(u16 kind, struct f_inst *tk, struct f_in
|
} |
} |
|
|
NEW_F_VAL; |
NEW_F_VAL; |
rv = f_new_inst(); | rv = f_new_inst(FI_CONSTANT_INDIRECT); |
rv->code = 'C'; | |
rv->a1.p = val; |
rv->a1.p = val; |
val->type = T_EC; |
val->type = T_EC; |
val->val.ec = ec; |
val->val.ec = ec; |
} |
} |
else { |
else { |
rv = f_new_inst(); | rv = f_new_inst(FI_EC_CONSTRUCT); |
rv->code = P('m','c'); | |
rv->aux = kind; |
rv->aux = kind; |
rv->a1.p = tk; |
rv->a1.p = tk; |
rv->a2.p = tv; |
rv->a2.p = tv; |
Line 300 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
Line 293 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
{ |
{ |
struct f_inst *rv; |
struct f_inst *rv; |
|
|
if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) { | if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT) && (t3->fi_code == FI_CONSTANT)) { |
if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT)) |
if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT)) |
cf_error( "LC - Can't operate with value of non-integer type in tuple constructor"); |
cf_error( "LC - Can't operate with value of non-integer type in tuple constructor"); |
|
|
rv = f_new_inst(); | rv = f_new_inst(FI_CONSTANT_INDIRECT); |
rv->code = 'C'; | |
|
|
NEW_F_VAL; |
NEW_F_VAL; |
rv->a1.p = val; |
rv->a1.p = val; |
Line 316 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
Line 308 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
{ |
{ |
rv = cfg_allocz(sizeof(struct f_inst3)); |
rv = cfg_allocz(sizeof(struct f_inst3)); |
rv->lineno = ifs->lino; |
rv->lineno = ifs->lino; |
rv->code = P('m','l'); | rv->fi_code = FI_LC_CONSTRUCT; |
rv->a1.p = t1; |
rv->a1.p = t1; |
rv->a2.p = t2; |
rv->a2.p = t2; |
INST3(rv).p = t3; |
INST3(rv).p = t3; |
Line 325 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
Line 317 f_generate_lc(struct f_inst *t1, struct f_inst *t2, st
|
return rv; |
return rv; |
} |
} |
|
|
|
static inline struct f_inst * |
|
f_generate_path_mask(struct f_path_mask *t) |
|
{ |
|
struct f_path_mask *tt; |
|
for (tt = t; tt; tt = tt->next) { |
|
if (tt->kind == PM_ASN_EXPR) { |
|
struct f_inst *mrv = f_new_inst(FI_PATHMASK_CONSTRUCT); |
|
mrv->a1.p = t; |
|
return mrv; |
|
} |
|
} |
|
|
|
NEW_F_VAL; |
|
val->type = T_PATH_MASK; |
|
val->val.path_mask = t; |
|
|
|
struct f_inst *rv = f_new_inst(FI_CONSTANT_INDIRECT); |
|
rv->a1.p = val; |
|
|
|
return rv; |
|
} |
|
|
|
|
CF_DECLS |
CF_DECLS |
|
|
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, |
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, |
Line 348 CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
Line 361 CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
%nonassoc THEN |
%nonassoc THEN |
%nonassoc ELSE |
%nonassoc ELSE |
|
|
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr | %type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr |
| %type <fda> dynamic_attr |
| %type <fsa> static_attr |
%type <f> filter filter_body where_filter |
%type <f> filter filter_body where_filter |
%type <i> type break_command ec_kind |
%type <i> type break_command ec_kind |
%type <i32> cnum |
%type <i32> cnum |
Line 461 where_filter:
|
Line 476 where_filter:
|
/* Construct 'IF term THEN ACCEPT; REJECT;' */ |
/* Construct 'IF term THEN ACCEPT; REJECT;' */ |
struct filter *f = cfg_alloc(sizeof(struct filter)); |
struct filter *f = cfg_alloc(sizeof(struct filter)); |
struct f_inst *i, *acc, *rej; |
struct f_inst *i, *acc, *rej; |
acc = f_new_inst(); /* ACCEPT */ | acc = f_new_inst(FI_PRINT_AND_DIE); /* ACCEPT */ |
acc->code = P('p',','); | |
acc->a1.p = NULL; |
acc->a1.p = NULL; |
acc->a2.i = F_ACCEPT; |
acc->a2.i = F_ACCEPT; |
rej = f_new_inst(); /* REJECT */ | rej = f_new_inst(FI_PRINT_AND_DIE); /* REJECT */ |
rej->code = P('p',','); | |
rej->a1.p = NULL; |
rej->a1.p = NULL; |
rej->a2.i = F_REJECT; |
rej->a2.i = F_REJECT; |
i = f_new_inst(); /* IF */ | i = f_new_inst(FI_CONDITION); /* IF */ |
i->code = '?'; | |
i->a1.p = $2; |
i->a1.p = $2; |
i->a2.p = acc; |
i->a2.p = acc; |
i->next = rej; |
i->next = rej; |
Line 489 function_body:
|
Line 501 function_body:
|
decls '{' cmds '}' { |
decls '{' cmds '}' { |
if ($1) { |
if ($1) { |
/* Prepend instruction to clear local variables */ |
/* Prepend instruction to clear local variables */ |
$$ = f_new_inst(); | $$ = f_new_inst(FI_CLEAR_LOCAL_VARS); |
$$->code = P('c','v'); | |
$$->a1.p = $1; |
$$->a1.p = $1; |
$$->next = $3; |
$$->next = $3; |
} else |
} else |
Line 680 switch_body: /* EMPTY */ { $$ = NULL; }
|
Line 691 switch_body: /* EMPTY */ { $$ = NULL; }
|
} |
} |
; |
; |
|
|
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */ | /* CONST '(' expr ')' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $3; } */ |
|
|
bgp_path_expr: |
bgp_path_expr: |
symbol { $$ = $1; } |
symbol { $$ = $1; } |
Line 708 bgp_path_tail2:
|
Line 719 bgp_path_tail2:
|
; |
; |
|
|
constant: |
constant: |
NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; } | NUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $1; } |
| TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; } | | TRUE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 1; } |
| FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; } | | FALSE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 0; } |
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | | TEXT { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_STRING; $$->a2.p = $1; } |
| fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | | fipa { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; } |
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | | fprefix_s {NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; } |
| RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; } | | RTRID { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_QUAD; $$->a2.i = $1; } |
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } | | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(FI_CONSTANT); $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } |
| '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; } | | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_PREFIX_SET; $$->a2.p = $2; } |
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } | | ENUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } |
| bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } | |
; |
; |
|
|
constructor: |
constructor: |
'(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } |
'(' term ',' term ')' { $$ = f_generate_dpair($2, $4); } |
| '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } |
| '(' ec_kind ',' term ',' term ')' { $$ = f_generate_ec($2, $4, $6); } |
| '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); } |
| '(' term ',' term ',' term ')' { $$ = f_generate_lc($2, $4, $6); } |
|
| bgp_path { $$ = f_generate_path_mask($1); } |
; |
; |
|
|
|
|
Line 733 constructor:
|
Line 744 constructor:
|
* For such cases, we force the dynamic_attr list to contain |
* For such cases, we force the dynamic_attr list to contain |
* at least an invalid token, so it is syntantically correct. |
* at least an invalid token, so it is syntantically correct. |
*/ |
*/ |
CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; }) | CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = (struct f_dynamic_attr) {}; }) |
|
|
rtadot: /* EMPTY, we are not permitted RTA. prefix */ |
rtadot: /* EMPTY, we are not permitted RTA. prefix */ |
; |
; |
Line 745 function_call:
|
Line 756 function_call:
|
if ($1->class != SYM_FUNCTION) |
if ($1->class != SYM_FUNCTION) |
cf_error("You can't call something which is not a function. Really."); |
cf_error("You can't call something which is not a function. Really."); |
DBG("You are calling function %s\n", $1->name); |
DBG("You are calling function %s\n", $1->name); |
$$ = f_new_inst(); | $$ = f_new_inst(FI_CALL); |
$$->code = P('c','a'); | |
$$->a1.p = inst; |
$$->a1.p = inst; |
$$->a2.p = $1->def; |
$$->a2.p = $1->def; |
sym = $1->aux2; |
sym = $1->aux2; |
Line 763 function_call:
|
Line 773 function_call:
|
|
|
symbol: |
symbol: |
SYM { |
SYM { |
$$ = f_new_inst(); |
|
|
|
switch ($1->class & 0xff00) { |
switch ($1->class & 0xff00) { |
case SYM_CONSTANT: $$->code = 'C'; break; | case SYM_CONSTANT: $$ = f_new_inst(FI_CONSTANT_INDIRECT); break; |
case SYM_VARIABLE: $$->code = 'V'; break; | case SYM_VARIABLE: $$ = f_new_inst(FI_VARIABLE); break; |
default: cf_error("%s: variable expected.", $1->name); |
default: cf_error("%s: variable expected.", $1->name); |
} |
} |
|
|
Line 776 symbol:
|
Line 784 symbol:
|
} |
} |
|
|
static_attr: |
static_attr: |
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_FROM; $$->a1.i = 1; } | FROM { $$ = f_new_static_attr(T_IP, SA_FROM, 1); } |
| GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_GW; $$->a1.i = 1; } | | GW { $$ = f_new_static_attr(T_IP, SA_GW, 1); } |
| NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = SA_NET; } | | NET { $$ = f_new_static_attr(T_PREFIX, SA_NET, 0); } |
| PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; } | | PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 0); } |
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; } | | SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 0); } |
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; } | | SCOPE { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE, 1); } |
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; } | | CAST { $$ = f_new_static_attr(T_ENUM_RTC, SA_CAST, 0); } |
| DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = SA_DEST; $$->a1.i = 1; } | | DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 1); } |
| IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_IFNAME; } | | IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 1); } |
| IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = SA_IFINDEX; } | | IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 0); } |
; |
; |
|
|
term: |
term: |
'(' term ')' { $$ = $2; } | '(' term ')' { $$ = $2; } |
| term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; } | | term '+' term { $$ = f_new_inst(FI_ADD); $$->a1.p = $1; $$->a2.p = $3; } |
| term '-' term { $$ = f_new_inst(); $$->code = '-'; $$->a1.p = $1; $$->a2.p = $3; } | | term '-' term { $$ = f_new_inst(FI_SUBTRACT); $$->a1.p = $1; $$->a2.p = $3; } |
| term '*' term { $$ = f_new_inst(); $$->code = '*'; $$->a1.p = $1; $$->a2.p = $3; } | | term '*' term { $$ = f_new_inst(FI_MULTIPLY); $$->a1.p = $1; $$->a2.p = $3; } |
| term '/' term { $$ = f_new_inst(); $$->code = '/'; $$->a1.p = $1; $$->a2.p = $3; } | | term '/' term { $$ = f_new_inst(FI_DIVIDE); $$->a1.p = $1; $$->a2.p = $3; } |
| term AND term { $$ = f_new_inst(); $$->code = '&'; $$->a1.p = $1; $$->a2.p = $3; } | | term AND term { $$ = f_new_inst(FI_AND); $$->a1.p = $1; $$->a2.p = $3; } |
| term OR term { $$ = f_new_inst(); $$->code = '|'; $$->a1.p = $1; $$->a2.p = $3; } | | term OR term { $$ = f_new_inst(FI_OR); $$->a1.p = $1; $$->a2.p = $3; } |
| term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; } | | term '=' term { $$ = f_new_inst(FI_EQ); $$->a1.p = $1; $$->a2.p = $3; } |
| term NEQ term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $3; } | | term NEQ term { $$ = f_new_inst(FI_NEQ); $$->a1.p = $1; $$->a2.p = $3; } |
| term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; } | | term '<' term { $$ = f_new_inst(FI_LT); $$->a1.p = $1; $$->a2.p = $3; } |
| term LEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $3; } | | term LEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $1; $$->a2.p = $3; } |
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; } | | term '>' term { $$ = f_new_inst(FI_LT); $$->a1.p = $3; $$->a2.p = $1; } |
| term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; } | | term GEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $3; $$->a2.p = $1; } |
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; } | | term '~' term { $$ = f_new_inst(FI_MATCH); $$->a1.p = $1; $$->a2.p = $3; } |
| term NMA term { $$ = f_new_inst(); $$->code = P('!','~'); $$->a1.p = $1; $$->a2.p = $3; } | | term NMA term { $$ = f_new_inst(FI_NOT_MATCH);$$->a1.p = $1; $$->a2.p = $3; } |
| '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; } | | '!' term { $$ = f_new_inst(FI_NOT); $$->a1.p = $2; } |
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; } | | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED); $$->a1.p = $3; } |
|
|
| symbol { $$ = $1; } |
| symbol { $$ = $1; } |
| constant { $$ = $1; } |
| constant { $$ = $1; } |
| constructor { $$ = $1; } |
| constructor { $$ = $1; } |
|
|
| PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; } | | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); } |
|
|
| rtadot static_attr { $$ = $2; $$->code = 'a'; } | | rtadot static_attr { $$ = f_new_inst_sa(FI_RTA_GET, $2); } |
|
|
| rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); } | | rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); } |
|
|
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; } | | term '.' IP { $$ = f_new_inst(FI_IP); $$->a1.p = $1; $$->aux = T_IP; } |
| term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; } | | term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a1.p = $1; } |
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; } | | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a1.p = $1; $$->a2.p = $5; } |
| term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; } | | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a1.p = $1; } |
| term '.' LAST { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; } | | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a1.p = $1; } |
| term '.' LAST_NONAGGREGATED { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; } | | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a1.p = $1; } |
|
|
/* Communities */ |
/* Communities */ |
/* This causes one shift/reduce conflict |
/* This causes one shift/reduce conflict |
Line 832 term:
|
Line 840 term:
|
| rtadot dynamic_attr '.' RESET{ } |
| rtadot dynamic_attr '.' RESET{ } |
*/ |
*/ |
|
|
| '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; } | | '+' EMPTY '+' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_PATH; } |
| '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; } | | '-' EMPTY '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_CLIST; } |
| '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; } | | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_ECLIST; } |
| '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; } | | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_LCLIST; } |
| PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } | | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND); $$->a1.p = $3; $$->a2.p = $5; } |
| ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } | | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } |
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } | | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } |
| FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } | | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } |
|
|
| ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); } |
| ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); } |
| ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); } |
| ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); } |
|
|
/* | term '.' LEN { $$->code = P('P','l'); } */ |
|
|
|
/* function_call is inlined here */ |
/* function_call is inlined here */ |
| SYM '(' var_list ')' { |
| SYM '(' var_list ')' { |
struct symbol *sym; |
struct symbol *sym; |
Line 853 term:
|
Line 859 term:
|
if ($1->class != SYM_FUNCTION) |
if ($1->class != SYM_FUNCTION) |
cf_error("You can't call something which is not a function. Really."); |
cf_error("You can't call something which is not a function. Really."); |
DBG("You are calling function %s\n", $1->name); |
DBG("You are calling function %s\n", $1->name); |
$$ = f_new_inst(); | $$ = f_new_inst(FI_CALL); |
$$->code = P('c','a'); | |
$$->a1.p = inst; |
$$->a1.p = inst; |
$$->a2.p = $1->def; |
$$->a2.p = $1->def; |
sym = $1->aux2; |
sym = $1->aux2; |
Line 879 break_command:
|
Line 884 break_command:
|
; |
; |
|
|
print_one: |
print_one: |
term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; } | term { $$ = f_new_inst(FI_PRINT); $$->a1.p = $1; $$->a2.p = NULL; } |
; |
; |
|
|
print_list: /* EMPTY */ { $$ = NULL; } |
print_list: /* EMPTY */ { $$ = NULL; } |
Line 893 print_list: /* EMPTY */ { $$ = NULL; }
|
Line 898 print_list: /* EMPTY */ { $$ = NULL; }
|
; |
; |
|
|
var_listn: term { |
var_listn: term { |
$$ = f_new_inst(); | $$ = f_new_inst(FI_SET); |
$$->code = 's'; | |
$$->a1.p = NULL; |
$$->a1.p = NULL; |
$$->a2.p = $1; |
$$->a2.p = $1; |
$$->next = NULL; |
$$->next = NULL; |
} |
} |
| term ',' var_listn { |
| term ',' var_listn { |
$$ = f_new_inst(); | $$ = f_new_inst(FI_SET); |
$$->code = 's'; | |
$$->a1.p = NULL; |
$$->a1.p = NULL; |
$$->a2.p = $1; |
$$->a2.p = $1; |
$$->next = $3; |
$$->next = $3; |
Line 914 var_list: /* EMPTY */ { $$ = NULL; }
|
Line 917 var_list: /* EMPTY */ { $$ = NULL; }
|
|
|
cmd: |
cmd: |
IF term THEN block { |
IF term THEN block { |
$$ = f_new_inst(); | $$ = f_new_inst(FI_CONDITION); |
$$->code = '?'; | |
$$->a1.p = $2; |
$$->a1.p = $2; |
$$->a2.p = $4; |
$$->a2.p = $4; |
} |
} |
| IF term THEN block ELSE block { |
| IF term THEN block ELSE block { |
struct f_inst *i = f_new_inst(); | struct f_inst *i = f_new_inst(FI_CONDITION); |
i->code = '?'; | |
i->a1.p = $2; |
i->a1.p = $2; |
i->a2.p = $4; |
i->a2.p = $4; |
$$ = f_new_inst(); | $$ = f_new_inst(FI_CONDITION); |
$$->code = '?'; | |
$$->a1.p = i; |
$$->a1.p = i; |
$$->a2.p = $6; |
$$->a2.p = $6; |
} |
} |
| SYM '=' term ';' { |
| SYM '=' term ';' { |
$$ = f_new_inst(); |
|
DBG( "Ook, we'll set value\n" ); |
DBG( "Ook, we'll set value\n" ); |
if (($1->class & ~T_MASK) != SYM_VARIABLE) |
if (($1->class & ~T_MASK) != SYM_VARIABLE) |
cf_error( "You may set only variables." ); |
cf_error( "You may set only variables." ); |
$$->code = 's'; | $$ = f_new_inst(FI_SET); |
$$->a1.p = $1; |
$$->a1.p = $1; |
$$->a2.p = $3; |
$$->a2.p = $3; |
} |
} |
| RETURN term ';' { |
| RETURN term ';' { |
$$ = f_new_inst(); |
|
DBG( "Ook, we'll return the value\n" ); |
DBG( "Ook, we'll return the value\n" ); |
$$->code = 'r'; | $$ = f_new_inst(FI_RETURN); |
$$->a1.p = $2; |
$$->a1.p = $2; |
} |
} |
| rtadot dynamic_attr '=' term ';' { |
| rtadot dynamic_attr '=' term ';' { |
$$ = $2; | $$ = f_new_inst_da(FI_EA_SET, $2); |
$$->code = P('e','S'); | |
$$->a1.p = $4; |
$$->a1.p = $4; |
} |
} |
| rtadot static_attr '=' term ';' { |
| rtadot static_attr '=' term ';' { |
$$ = $2; | $$ = f_new_inst_sa(FI_RTA_SET, $2); |
if (!$$->a1.i) |
if (!$$->a1.i) |
cf_error( "This static attribute is read-only."); |
cf_error( "This static attribute is read-only."); |
$$->code = P('a','S'); |
|
$$->a1.p = $4; |
$$->a1.p = $4; |
} |
} |
| PREFERENCE '=' term ';' { |
| PREFERENCE '=' term ';' { |
$$ = f_new_inst(); | $$ = f_new_inst(FI_PREF_SET); |
$$->code = P('P','S'); | |
$$->a1.p = $3; |
$$->a1.p = $3; |
} |
} |
| UNSET '(' rtadot dynamic_attr ')' ';' { |
| UNSET '(' rtadot dynamic_attr ')' ';' { |
$$ = $4; | $$ = f_new_inst_da(FI_EA_SET, $4); |
$$->aux = EAF_TYPE_UNDEF | EAF_TEMP; |
$$->aux = EAF_TYPE_UNDEF | EAF_TEMP; |
$$->code = P('e','S'); |
|
$$->a1.p = NULL; |
$$->a1.p = NULL; |
} |
} |
| break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; } | | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a1.p = $2; $$->a2.i = $1; } |
| function_call ';' { $$ = $1; } |
| function_call ';' { $$ = $1; } |
| CASE term '{' switch_body '}' { |
| CASE term '{' switch_body '}' { |
$$ = f_new_inst(); | $$ = f_new_inst(FI_SWITCH); |
$$->code = P('S','W'); | |
$$->a1.p = $2; |
$$->a1.p = $2; |
$$->a2.p = build_tree( $4 ); |
$$->a2.p = build_tree( $4 ); |
} |
} |
|
|
|
|
| rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } |
| rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } |
| rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); } | | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, 'x', $2, $6 ); } |
| rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } | | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'a', $2, $6 ); } |
| rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } | | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'd', $2, $6 ); } |
| rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); } | | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'f', $2, $6 ); } |
; |
; |
|
|
CF_END |
CF_END |