| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  *	BIRD - filters | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2000-05-15 10:49:38 +00:00
										 |  |  |  *	Copyright 1998--2000 Pavel Machek | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *	Can be freely distributed and used under the terms of the GNU GPL. | 
					
						
							| 
									
										
										
										
											1999-10-07 13:38:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2000-06-01 08:34:30 +00:00
										 |  |  | 	FIXME: priority of ! should be lower | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CF_HDR | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-28 15:11:10 +00:00
										 |  |  | CF_DEFINES | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  | #define P(a,b) ((a<<8) | b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  | CF_DECLS | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-09 13:21:40 +00:00
										 |  |  | CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | 	ACCEPT, REJECT, ERROR, QUITBIRD, | 
					
						
							| 
									
										
										
										
											2000-04-12 13:31:39 +00:00
										 |  |  | 	INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST, | 
					
						
							| 
									
										
										
										
											1999-09-29 14:24:58 +00:00
										 |  |  | 	IF, THEN, ELSE, CASE, | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  | 	TRUE, FALSE, | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:37 +01:00
										 |  |  | 	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE, | 
					
						
							| 
									
										
										
										
											1999-04-19 18:41:56 +00:00
										 |  |  | 	LEN, | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  | 	DEFINED, | 
					
						
							| 
									
										
										
										
											2000-04-10 15:07:43 +00:00
										 |  |  | 	ADD, DELETE, CONTAINS, RESET, | 
					
						
							| 
									
										
										
										
											2000-04-17 10:42:28 +00:00
										 |  |  | 	PREPEND, MATCH, | 
					
						
							| 
									
										
										
										
											2000-04-17 10:16:47 +00:00
										 |  |  | 	EMPTY, | 
					
						
							| 
									
										
										
										
											2000-05-15 10:49:38 +00:00
										 |  |  | 	FILTER, WHERE, EVAL) | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  | %nonassoc THEN | 
					
						
							| 
									
										
										
										
											1999-11-11 13:27:59 +00:00
										 |  |  | %nonassoc ELSE | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 10:23:04 +00:00
										 |  |  | %type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call | 
					
						
							| 
									
										
										
										
											1999-12-02 14:04:44 +00:00
										 |  |  | %type <f> filter filter_body where_filter | 
					
						
							| 
									
										
										
										
											1999-11-11 13:55:39 +00:00
										 |  |  | %type <i> type break_command pair | 
					
						
							| 
									
										
										
										
											1999-10-28 21:03:36 +00:00
										 |  |  | %type <e> set_item set_items switch_body | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  | %type <trie> fprefix_set | 
					
						
							| 
									
										
										
										
											2000-05-15 11:48:23 +00:00
										 |  |  | %type <v> set_atom fprefix fprefix_s fipa | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | %type <s> decls declsn one_decl function_params  | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  | %type <h> bgp_path bgp_path_tail1 bgp_path_tail2 | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | CF_GRAMMAR | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-17 14:29:39 +00:00
										 |  |  | CF_ADDTO(conf, filter_def) | 
					
						
							|  |  |  | filter_def: | 
					
						
							| 
									
										
										
										
											1999-11-10 13:44:29 +00:00
										 |  |  |    FILTER SYM { cf_push_scope( $2 ); } filter_body { | 
					
						
							| 
									
										
										
										
											2000-06-04 19:30:55 +00:00
										 |  |  |      $2 = cf_define_symbol($2, SYM_FILTER, $4); | 
					
						
							| 
									
										
										
										
											1999-11-04 14:03:45 +00:00
										 |  |  |      $4->name = $2->name; | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG( "We have new filter defined (%s)\n", $2->name ); | 
					
						
							| 
									
										
										
										
											1999-11-04 14:03:45 +00:00
										 |  |  |      cf_pop_scope(); | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-15 10:49:38 +00:00
										 |  |  | CF_ADDTO(conf, filter_eval) | 
					
						
							|  |  |  | filter_eval: | 
					
						
							|  |  |  |    EVAL term { f_eval_int($2); } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | type: | 
					
						
							|  |  |  |    INT { $$ = T_INT; } | 
					
						
							|  |  |  |  | BOOL { $$ = T_BOOL; } | 
					
						
							|  |  |  |  | IP { $$ = T_IP; } | 
					
						
							|  |  |  |  | PREFIX { $$ = T_PREFIX; } | 
					
						
							|  |  |  |  | PAIR { $$ = T_PAIR; } | 
					
						
							|  |  |  |  | STRING { $$ = T_STRING; } | 
					
						
							| 
									
										
										
										
											2000-04-12 13:31:39 +00:00
										 |  |  |  | BGPMASK { $$ = T_PATH_MASK; } | 
					
						
							|  |  |  |  | BGPPATH { $$ = T_PATH; } | 
					
						
							|  |  |  |  | CLIST { $$ = T_CLIST; } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  | type SET {  | 
					
						
							|  |  |  | 	switch ($1) { | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  | 	  case T_INT: | 
					
						
							|  |  |  | 	  case T_IP: | 
					
						
							|  |  |  | 	  case T_PAIR: | 
					
						
							|  |  |  | 	       $$ = T_SET; | 
					
						
							|  |  |  | 	       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  case T_PREFIX: | 
					
						
							|  |  |  | 	       $$ = T_PREFIX_SET; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | 	  default: | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  | 		cf_error( "You can't create sets of this type." ); | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | one_decl: | 
					
						
							|  |  |  |    type SYM { | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      struct f_val * val = cfg_alloc(sizeof(struct f_val));  | 
					
						
							|  |  |  |      val->type = $1;  | 
					
						
							|  |  |  |      $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val); | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG( "New variable %s type %x\n", $2->name, $1 ); | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $2->aux2 = NULL; | 
					
						
							| 
									
										
										
										
											1999-07-01 09:11:21 +00:00
										 |  |  |      $$=$2; | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | /* Decls with ';' at the end */ | 
					
						
							|  |  |  | decls: /* EMPTY */ { $$ = NULL; } | 
					
						
							|  |  |  |  | one_decl ';' decls { | 
					
						
							|  |  |  |      $$ = $1; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $$->aux2 = $3; | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-04 14:05:40 +00:00
										 |  |  | /* Declarations that have no ';' at the end. */ | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | declsn: one_decl { $$ = $1; } | 
					
						
							|  |  |  |  | declsn ';' one_decl { | 
					
						
							| 
									
										
										
										
											1999-11-11 13:55:39 +00:00
										 |  |  |      $$ = $1; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $$->aux2 = $3; | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-17 14:29:39 +00:00
										 |  |  | filter_body: | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |    function_body { | 
					
						
							| 
									
										
										
										
											1999-03-17 14:29:39 +00:00
										 |  |  |      struct filter *f = cfg_alloc(sizeof(struct filter)); | 
					
						
							|  |  |  |      f->name = NULL; | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |      f->root = $1; | 
					
						
							| 
									
										
										
										
											1999-03-17 14:29:39 +00:00
										 |  |  |      $$ = f; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | filter: | 
					
						
							|  |  |  |    SYM { | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  |      if ($1->class != SYM_FILTER) cf_error("No such filter."); | 
					
						
							| 
									
										
										
										
											1999-03-17 14:29:39 +00:00
										 |  |  |      $$ = $1->def; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  | filter_body | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-02 14:04:44 +00:00
										 |  |  | where_filter: | 
					
						
							|  |  |  |    WHERE term { | 
					
						
							|  |  |  |      /* Construct 'IF term THEN ACCEPT; REJECT;' */ | 
					
						
							|  |  |  |      struct filter *f = cfg_alloc(sizeof(struct filter)); | 
					
						
							|  |  |  |      struct f_inst *i, *acc, *rej; | 
					
						
							|  |  |  |      acc = f_new_inst();		/* ACCEPT */ | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      acc->code = P('p',','); | 
					
						
							| 
									
										
										
										
											1999-12-02 14:04:44 +00:00
										 |  |  |      acc->a1.p = NULL; | 
					
						
							|  |  |  |      acc->a2.i = F_ACCEPT; | 
					
						
							|  |  |  |      rej = f_new_inst();		/* REJECT */ | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      rej->code = P('p',','); | 
					
						
							| 
									
										
										
										
											1999-12-02 14:04:44 +00:00
										 |  |  |      rej->a1.p = NULL; | 
					
						
							|  |  |  |      rej->a2.i = F_REJECT; | 
					
						
							|  |  |  |      i = f_new_inst();			/* IF */ | 
					
						
							|  |  |  |      i->code = '?'; | 
					
						
							|  |  |  |      i->a1.p = $2; | 
					
						
							|  |  |  |      i->a2.p = acc; | 
					
						
							|  |  |  |      i->next = rej; | 
					
						
							|  |  |  |      f->name = NULL; | 
					
						
							|  |  |  |      f->root = i; | 
					
						
							|  |  |  |      $$ = f; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | function_params: | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |    '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; } | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  |  | '(' ')' { $$=NULL; } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  ; | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  | function_body: | 
					
						
							|  |  |  |    decls '{' cmds '}' { | 
					
						
							|  |  |  |      $$ = $3; | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CF_ADDTO(conf, function_def) | 
					
						
							|  |  |  | function_def: | 
					
						
							| 
									
										
										
										
											2000-06-04 19:30:55 +00:00
										 |  |  |    FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name ); | 
					
						
							|  |  |  |      $2 = cf_define_symbol($2, SYM_FUNCTION, NULL); | 
					
						
							|  |  |  |      cf_push_scope($2); | 
					
						
							|  |  |  |    } function_params function_body { | 
					
						
							|  |  |  |      $2->def = $5; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $2->aux2 = $4; | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG("Hmm, we've got one function here - %s\n", $2->name);  | 
					
						
							| 
									
										
										
										
											1999-11-04 14:03:45 +00:00
										 |  |  |      cf_pop_scope(); | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Programs */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cmds: /* EMPTY */ { $$ = NULL; } | 
					
						
							|  |  |  |  | cmd cmds { | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  |      if ($1) { | 
					
						
							| 
									
										
										
										
											1999-09-29 14:24:58 +00:00
										 |  |  |        if ($1->next) | 
					
						
							| 
									
										
										
										
											2000-05-25 15:20:40 +00:00
										 |  |  | 	 bug("Command has next already set"); | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |        $1->next = $2; | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  |        $$ = $1; | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |      } else $$ = $2; | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-09 14:45:27 +00:00
										 |  |  | block: | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |    cmd { | 
					
						
							| 
									
										
										
										
											1999-03-09 14:45:27 +00:00
										 |  |  |      $$=$1; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  | '{' cmds '}' { | 
					
						
							|  |  |  |      $$=$2; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Simple types, their bison value is int | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | pair: | 
					
						
							|  |  |  |    '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  |  * Complex types, their bison value is struct f_val | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2000-05-15 11:48:23 +00:00
										 |  |  | fipa: | 
					
						
							| 
									
										
										
										
											2000-05-16 14:24:33 +00:00
										 |  |  |    IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; } | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-12 19:58:18 +00:00
										 |  |  | set_atom: | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  |    NUM  { $$.type = T_INT; $$.val.i = $1; } | 
					
						
							|  |  |  |  | pair { $$.type = T_PAIR; $$.val.i = $1; } | 
					
						
							| 
									
										
										
										
											2000-05-15 11:48:23 +00:00
										 |  |  |  | fipa { $$ = $1; } | 
					
						
							| 
									
										
										
										
											2000-06-01 08:32:49 +00:00
										 |  |  |  | ENUM {  $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; } | 
					
						
							| 
									
										
										
										
											1999-04-12 19:58:18 +00:00
										 |  |  |  ;  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_item: | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |    set_atom {  | 
					
						
							|  |  |  | 	$$ = f_new_tree();  | 
					
						
							|  |  |  | 	$$->from = $1;  | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  | 	$$->to = $1; | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |    } | 
					
						
							|  |  |  |  | set_atom '.' '.' set_atom {  | 
					
						
							|  |  |  | 	$$ = f_new_tree();  | 
					
						
							|  |  |  | 	$$->from = $1;  | 
					
						
							|  |  |  | 	$$->to = $4;  | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-04-12 19:58:18 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_items: | 
					
						
							|  |  |  |    set_item { $$ = $1; } | 
					
						
							|  |  |  |  | set_items ',' set_item { $$ = $3; $$->left = $1; } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  | fprefix_s: | 
					
						
							|  |  |  |    IPA '/' NUM %prec '/' { | 
					
						
							|  |  |  |      if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3); | 
					
						
							|  |  |  |      $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fprefix: | 
					
						
							|  |  |  |    fprefix_s { $$ = $1; } | 
					
						
							|  |  |  |  | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; } | 
					
						
							|  |  |  |  | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; } | 
					
						
							|  |  |  |  | fprefix_s '{' NUM ',' NUM '}' {  | 
					
						
							|  |  |  |      if (! ((0 <= $3) && ($3 <= $5) && ($5 <= MAX_PREFIX_LENGTH))) cf_error("Invalid prefix pattern range: {%d, %d}.", $3, $5); | 
					
						
							|  |  |  |      $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fprefix_set: | 
					
						
							|  |  |  |    fprefix { $$ = f_new_trie(); trie_add_prefix($$, &($1.val.px)); } | 
					
						
							|  |  |  |  | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.val.px)); } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-28 21:03:36 +00:00
										 |  |  | switch_body: /* EMPTY */ { $$ = NULL; } | 
					
						
							|  |  |  |  | set_item ':' cmds switch_body { | 
					
						
							|  |  |  |      $$ = $1; | 
					
						
							|  |  |  |      $$->data = $3; | 
					
						
							|  |  |  |      $$->left = $4; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  | ELSE ':' cmds { | 
					
						
							|  |  |  |      $$ = f_new_tree();  | 
					
						
							|  |  |  |      $$->from.type = T_VOID;  | 
					
						
							|  |  |  |      $$->to.type = T_VOID; | 
					
						
							|  |  |  |      $$->data = $3; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-09 13:21:40 +00:00
										 |  |  | /* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  | bgp_path: | 
					
						
							| 
									
										
										
										
											2009-03-14 12:43:10 +01:00
										 |  |  |    PO  bgp_path_tail1 PC  { $$ = $2; } | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  |  | '/' bgp_path_tail2 '/' { $$ = $2; } | 
					
						
							|  |  |  |  | OR  		      	  { $$ = NULL; } /* special case because of || is a different token */ | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bgp_path_tail1: | 
					
						
							| 
									
										
										
										
											2009-04-17 01:48:36 +02:00
										 |  |  |    NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN;      $$->val = $1; } | 
					
						
							|  |  |  |  | '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val  = 0; } | 
					
						
							|  |  |  |  | '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val  = 0; } | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  |  |  		      { $$ = NULL; } | 
					
						
							|  |  |  |  ; | 
					
						
							| 
									
										
										
										
											2000-04-12 12:10:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  | bgp_path_tail2: | 
					
						
							| 
									
										
										
										
											2009-04-17 01:48:36 +02:00
										 |  |  |    NUM bgp_path_tail2 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN;      $$->val = $1; } | 
					
						
							|  |  |  |  | '?' bgp_path_tail2 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val  = 0; } | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  |  | 		      { $$ = NULL; } | 
					
						
							| 
									
										
										
										
											2000-04-12 12:10:37 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  | constant: | 
					
						
							| 
									
										
										
										
											2000-03-09 13:21:40 +00:00
										 |  |  |    NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT;  $$->a2.i = $1; } | 
					
						
							| 
									
										
										
										
											1999-11-18 14:01:36 +00:00
										 |  |  |  | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  } | 
					
						
							|  |  |  |  | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  } | 
					
						
							|  |  |  |  | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | 
					
						
							|  |  |  |  | pair   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR;  $$->a2.i = $1; } | 
					
						
							| 
									
										
										
										
											2000-05-15 11:48:23 +00:00
										 |  |  |  | fipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | 
					
						
							| 
									
										
										
										
											2000-05-13 11:17:49 +00:00
										 |  |  |  | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |  | '[' 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" ); } | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |  | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET;  $$->a2.p = $2; } | 
					
						
							| 
									
										
										
										
											1999-11-18 14:01:36 +00:00
										 |  |  |  | ENUM	  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } | 
					
						
							| 
									
										
										
										
											2009-01-27 17:35:00 +01:00
										 |  |  |  | bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-01 11:32:23 +00:00
										 |  |  | /* | 
					
						
							|  |  |  |  *  Maybe there are no dynamic attributes defined by protocols. | 
					
						
							|  |  |  |  *  For such cases, we force the dynamic_attr list to contain | 
					
						
							|  |  |  |  *  at least an invalid token, so it's syntantically correct. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; }) | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-08 12:51:26 +00:00
										 |  |  | rtadot: /* EMPTY, we are not permitted RTA. prefix */ | 
					
						
							| 
									
										
										
										
											1999-12-08 10:15:51 +00:00
										 |  |  |  ; | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  | function_call: | 
					
						
							|  |  |  |    SYM '(' var_list ')' { | 
					
						
							|  |  |  |      struct symbol *sym; | 
					
						
							|  |  |  |      struct f_inst *inst = $3; | 
					
						
							|  |  |  |      if ($1->class != SYM_FUNCTION) | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  |        cf_error("You can't call something which is not a function. Really."); | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG("You are calling function %s\n", $1->name); | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = P('c','a'); | 
					
						
							|  |  |  |      $$->a1.p = inst; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $$->a2.p = $1->def; | 
					
						
							|  |  |  |      sym = $1->aux2; | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      while (sym || inst) { | 
					
						
							|  |  |  |        if (!sym || !inst) | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  | 	 cf_error("Wrong number of arguments for function %s.", $1->name); | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |        DBG( "You should pass parameter called %s\n", sym->name); | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |        inst->a1.p = sym; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |        sym = sym->aux2; | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |        inst = inst->next; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 10:23:04 +00:00
										 |  |  | static_attr: | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |    FROM    { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = OFFSETOF(struct rta, from);   $$->a1.i = 1; } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:42:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |  | GW      { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = OFFSETOF(struct rta, gw);     $$->a1.i = 1; } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:42:39 +00:00
										 |  |  |  | NET     { $$ = f_new_inst(); $$->aux = T_PREFIX;     $$->a2.i = 0x12345678; /* This is actually ok - T_PREFIX is special-cased. */ } | 
					
						
							| 
									
										
										
										
											2008-11-14 14:50:37 +01:00
										 |  |  |  | PROTO   { $$ = f_new_inst(); $$->aux = T_STRING;     $$->a2.i = 0x12345678; /* T_STRING is also special-cased. */ } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:42:39 +00:00
										 |  |  |  | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = OFFSETOF(struct rta, source); } | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |  | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope);  $$->a1.i = 1; } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:42:39 +00:00
										 |  |  |  | CAST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTC;   $$->a2.i = OFFSETOF(struct rta, cast); } | 
					
						
							|  |  |  |  | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = OFFSETOF(struct rta, dest); } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:23:04 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  | term: | 
					
						
							| 
									
										
										
										
											1999-11-10 12:44:07 +00:00
										 |  |  |    '(' term ')'      { $$ = $2; } | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |  | term '+' term     { $$ = f_new_inst(); $$->code = '+';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							| 
									
										
										
										
											2000-05-15 12:27:45 +00:00
										 |  |  |  | term '-' term     { $$ = f_new_inst(); $$->code = '-';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term '*' term     { $$ = f_new_inst(); $$->code = '*';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term '/' term     { $$ = f_new_inst(); $$->code = '/';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							| 
									
										
										
										
											2000-06-01 08:43:29 +00:00
										 |  |  |  | term AND term     { $$ = f_new_inst(); $$->code = '&';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term OR  term     { $$ = f_new_inst(); $$->code = '|';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | term '=' term     { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |  | term NEQ term { $$ = f_new_inst(); $$->code = P('!','=');     $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term '<' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term LEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							|  |  |  |  | term '>' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $3; $$->a2.p = $1; } | 
					
						
							|  |  |  |  | term GEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $3; $$->a2.p = $1; } | 
					
						
							|  |  |  |  | term '~' term     { $$ = f_new_inst(); $$->code = '~';        $$->a1.p = $1; $$->a2.p = $3; } | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |  | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; } | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e');  $$->a1.p = $3; } | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-10 13:59:13 +00:00
										 |  |  |  | constant { $$ = $1; } | 
					
						
							| 
									
										
										
										
											1999-03-09 14:45:27 +00:00
										 |  |  |  | SYM { | 
					
						
							|  |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      switch ($1->class) { | 
					
						
							| 
									
										
										
										
											2000-05-15 12:19:26 +00:00
										 |  |  |        case SYM_NUMBER: | 
					
						
							|  |  |  | 	$$ = f_new_inst(); | 
					
						
							|  |  |  | 	$$->code = 'c';  | 
					
						
							|  |  |  | 	$$->aux = T_INT;  | 
					
						
							|  |  |  | 	$$->a2.i = $1->aux; | 
					
						
							|  |  |  | 	break; | 
					
						
							|  |  |  |        case SYM_IPA: | 
					
						
							|  |  |  | 	{ NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.px.ip = * (ip_addr *) ($1->def); } | 
					
						
							|  |  |  | 	break; | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |        case SYM_VARIABLE | T_BOOL: | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |        case SYM_VARIABLE | T_INT: | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  |        case SYM_VARIABLE | T_PAIR: | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |        case SYM_VARIABLE | T_STRING: | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  |        case SYM_VARIABLE | T_IP: | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |        case SYM_VARIABLE | T_PREFIX: | 
					
						
							|  |  |  |        case SYM_VARIABLE | T_PREFIX_SET: | 
					
						
							|  |  |  |        case SYM_VARIABLE | T_SET: | 
					
						
							| 
									
										
										
										
											2000-04-17 10:42:28 +00:00
										 |  |  |        case SYM_VARIABLE | T_PATH: | 
					
						
							| 
									
										
										
										
											2009-03-31 12:55:57 +02:00
										 |  |  |        case SYM_VARIABLE | T_PATH_MASK: | 
					
						
							| 
									
										
										
										
											2000-04-17 11:34:38 +00:00
										 |  |  |        case SYM_VARIABLE | T_CLIST: | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  | 	 $$->code = 'C'; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  | 	 $$->a1.p = $1->def; | 
					
						
							| 
									
										
										
										
											1999-03-09 14:45:27 +00:00
										 |  |  | 	 break; | 
					
						
							|  |  |  |        default: | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  | 	 cf_error("%s: variable expected.", $1->name ); | 
					
						
							| 
									
										
										
										
											1999-03-09 14:45:27 +00:00
										 |  |  |      } | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-11-11 13:55:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |  | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:23:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |  | rtadot static_attr { $$ = $2; $$->code = 'a'; } | 
					
						
							| 
									
										
										
										
											2000-05-30 10:13:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-01 11:32:23 +00:00
										 |  |  |  | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); } | 
					
						
							| 
									
										
										
										
											1999-04-19 18:41:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; } | 
					
						
							| 
									
										
										
										
											2000-04-17 11:06:39 +00:00
										 |  |  |  | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; } | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; } | 
					
						
							| 
									
										
										
										
											2000-04-10 15:07:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Communities */ | 
					
						
							| 
									
										
										
										
											2000-04-12 13:31:39 +00:00
										 |  |  | /* This causes one shift/reduce conflict | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' ADD '(' term ')' { } | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' DELETE '(' term ')' { } | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' CONTAINS '(' term ')' { } | 
					
						
							| 
									
										
										
										
											2000-04-12 14:05:37 +00:00
										 |  |  |  | rtadot dynamic_attr '.' RESET{ } | 
					
						
							| 
									
										
										
										
											2000-04-12 13:31:39 +00:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2000-04-10 15:07:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-17 10:42:28 +00:00
										 |  |  |  | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; } | 
					
						
							| 
									
										
										
										
											2000-04-17 11:34:38 +00:00
										 |  |  |  | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; } | 
					
						
							| 
									
										
										
										
											2000-04-17 10:42:28 +00:00
										 |  |  |  | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }  | 
					
						
							| 
									
										
										
										
											2000-04-17 11:42:08 +00:00
										 |  |  |  | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->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'; } | 
					
						
							| 
									
										
										
										
											2000-04-17 10:16:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-12 14:05:37 +00:00
										 |  |  | /* | term '.' LEN { $$->code = P('P','l'); } */ | 
					
						
							| 
									
										
										
										
											2000-04-10 15:07:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  | /* function_call is inlined here */ | 
					
						
							|  |  |  |  | SYM '(' var_list ')' { | 
					
						
							|  |  |  |      struct symbol *sym; | 
					
						
							|  |  |  |      struct f_inst *inst = $3; | 
					
						
							|  |  |  |      if ($1->class != SYM_FUNCTION) | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  |        cf_error("You can't call something which is not a function. Really."); | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |      DBG("You are calling function %s\n", $1->name); | 
					
						
							|  |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = P('c','a'); | 
					
						
							|  |  |  |      $$->a1.p = inst; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |      $$->a2.p = $1->def; | 
					
						
							|  |  |  |      sym = $1->aux2; | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |      while (sym || inst) { | 
					
						
							|  |  |  |        if (!sym || !inst) | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  | 	 cf_error("Wrong number of arguments for function %s.", $1->name); | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |        DBG( "You should pass parameter called %s\n", sym->name); | 
					
						
							|  |  |  |        inst->a1.p = sym; | 
					
						
							| 
									
										
										
										
											2008-12-25 11:55:27 +01:00
										 |  |  |        sym = sym->aux2; | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |        inst = inst->next; | 
					
						
							|  |  |  |      } | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | break_command: | 
					
						
							| 
									
										
										
										
											2004-05-31 17:44:39 +00:00
										 |  |  |    QUITBIRD { $$ = F_QUITBIRD; } | 
					
						
							|  |  |  |  | ACCEPT { $$ = F_ACCEPT; } | 
					
						
							|  |  |  |  | REJECT { $$ = F_REJECT; } | 
					
						
							|  |  |  |  | ERROR { $$ = F_ERROR; } | 
					
						
							|  |  |  |  | PRINT { $$ = F_NOP; } | 
					
						
							|  |  |  |  | PRINTN { $$ = F_NONL; } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  | print_one: | 
					
						
							| 
									
										
										
										
											1999-04-10 09:45:08 +00:00
										 |  |  |    term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; } | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print_list: /* EMPTY */ { $$ = NULL; } | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |  | print_one { $$ = $1; } | 
					
						
							|  |  |  |  | print_one ',' print_list { | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |      if ($1) { | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |        $1->next = $3; | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |        $$ = $1; | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |      } else $$ = $3; | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-03-09 14:47:43 +00:00
										 |  |  |   | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | var_listn: term {  | 
					
						
							| 
									
										
										
										
											1999-10-12 06:27:42 +00:00
										 |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = 's'; | 
					
						
							|  |  |  |      $$->a1.p = NULL; | 
					
						
							|  |  |  |      $$->a2.p = $1; | 
					
						
							|  |  |  |      $$->next = NULL; | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  |  | term ',' var_listn { | 
					
						
							| 
									
										
										
										
											1999-07-01 09:11:21 +00:00
										 |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = 's'; | 
					
						
							|  |  |  |      $$->a1.p = NULL; | 
					
						
							|  |  |  |      $$->a2.p = $1; | 
					
						
							|  |  |  |      $$->next = $3; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-11-03 22:23:01 +00:00
										 |  |  | var_list: /* EMPTY */ { $$ = NULL; } | 
					
						
							|  |  |  |  | var_listn { $$ = $1; } | 
					
						
							|  |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  | cmd: | 
					
						
							| 
									
										
										
										
											1999-11-10 13:05:57 +00:00
										 |  |  |    IF term THEN block { | 
					
						
							|  |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = '?'; | 
					
						
							|  |  |  |      $$->a1.p = $2; | 
					
						
							|  |  |  |      $$->a2.p = $4; | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-11-10 13:05:57 +00:00
										 |  |  |  | IF term THEN block ELSE block { | 
					
						
							|  |  |  |      struct f_inst *i = f_new_inst(); | 
					
						
							|  |  |  |      i->code = '?'; | 
					
						
							|  |  |  |      i->a1.p = $2; | 
					
						
							|  |  |  |      i->a2.p = $4; | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = '?'; | 
					
						
							| 
									
										
										
										
											1999-11-10 13:05:57 +00:00
										 |  |  |      $$->a1.p = i; | 
					
						
							|  |  |  |      $$->a2.p = $6; | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |  | SYM '=' term ';' { | 
					
						
							| 
									
										
										
										
											1999-03-02 19:49:28 +00:00
										 |  |  |      $$ = f_new_inst(); | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG( "Ook, we'll set value\n" ); | 
					
						
							| 
									
										
										
										
											1999-03-29 20:21:28 +00:00
										 |  |  |      if (($1->class & ~T_MASK) != SYM_VARIABLE) | 
					
						
							| 
									
										
										
										
											2000-06-08 10:26:19 +00:00
										 |  |  |        cf_error( "You may set only variables." ); | 
					
						
							| 
									
										
										
										
											1999-04-07 12:11:08 +00:00
										 |  |  |      $$->code = 's'; | 
					
						
							| 
									
										
										
										
											1999-04-10 09:45:08 +00:00
										 |  |  |      $$->a1.p = $1; | 
					
						
							|  |  |  |      $$->a2.p = $3; | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | RETURN term ';' { | 
					
						
							|  |  |  |      $$ = f_new_inst(); | 
					
						
							| 
									
										
										
										
											2000-03-02 22:23:18 +00:00
										 |  |  |      DBG( "Ook, we'll return the value\n" ); | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      $$->code = 'r'; | 
					
						
							|  |  |  |      $$->a1.p = $2; | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-03-01 11:32:23 +00:00
										 |  |  |  | rtadot dynamic_attr '=' term ';' { | 
					
						
							| 
									
										
										
										
											1999-12-08 10:15:51 +00:00
										 |  |  |      $$ = $2; | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |      $$->code = P('e','S'); | 
					
						
							| 
									
										
										
										
											1999-12-08 10:15:51 +00:00
										 |  |  |      $$->a1.p = $4; | 
					
						
							| 
									
										
										
										
											1999-11-18 14:29:10 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-05-30 11:07:22 +00:00
										 |  |  |  | rtadot static_attr '=' term ';' { | 
					
						
							|  |  |  |      $$ = $2; | 
					
						
							|  |  |  |      if (!$$->a1.i) | 
					
						
							|  |  |  |        cf_error( "This static attribute is read-only."); | 
					
						
							|  |  |  |      $$->code = P('a','S'); | 
					
						
							|  |  |  |      $$->a1.p = $4; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |  | PREFERENCE '=' term ';' { | 
					
						
							|  |  |  |      $$ = f_new_inst(); | 
					
						
							|  |  |  |      $$->code = P('P','S'); | 
					
						
							|  |  |  |      $$->a1.p = $3; | 
					
						
							|  |  |  |    }  | 
					
						
							| 
									
										
										
										
											2000-03-01 11:32:23 +00:00
										 |  |  |  | UNSET '(' rtadot dynamic_attr ')' ';' { | 
					
						
							| 
									
										
										
										
											1999-12-08 10:15:51 +00:00
										 |  |  |      $$ = $4; | 
					
						
							| 
									
										
										
										
											2000-03-04 22:30:44 +00:00
										 |  |  |      $$->aux = EAF_TYPE_UNDEF | EAF_TEMP; | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |      $$->code = P('e','S'); | 
					
						
							| 
									
										
										
										
											1999-11-24 12:04:32 +00:00
										 |  |  |      $$->a1.p = NULL; | 
					
						
							| 
									
										
										
										
											1999-11-18 14:01:36 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |  | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; } | 
					
						
							|  |  |  |  | function_call ';' { $$ = $1; } | 
					
						
							| 
									
										
										
										
											1999-09-29 14:24:58 +00:00
										 |  |  |  | CASE term '{' switch_body '}' { | 
					
						
							|  |  |  |       $$ = f_new_inst(); | 
					
						
							| 
									
										
										
										
											2000-02-25 11:15:26 +00:00
										 |  |  |       $$->code = P('S','W'); | 
					
						
							| 
									
										
										
										
											1999-09-29 14:24:58 +00:00
										 |  |  |       $$->a1.p = $2; | 
					
						
							| 
									
										
										
										
											1999-10-28 21:03:36 +00:00
										 |  |  |       $$->a2.p = build_tree( $4 ); | 
					
						
							| 
									
										
										
										
											1999-09-29 14:24:58 +00:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2000-04-20 10:25:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' EMPTY ';'  | 
					
						
							|  |  |  |   { struct f_inst *i = f_new_inst(); i->code = 'E'; i->aux = T_CLIST; $$ = $2; $$->code = P('e','S'); $$->a1.p = i; } | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' PREPEND '(' term ')' ';'   { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); } | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' ADD '(' term ')' ';'       { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); }  | 
					
						
							|  |  |  |  | rtadot dynamic_attr '.' DELETE '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); }  | 
					
						
							| 
									
										
										
										
											1999-01-15 16:49:17 +00:00
										 |  |  |  ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CF_END |