Diff for /embedaddon/bird/filter/config.Y between versions 1.1.1.1 and 1.1.1.2

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

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>