Statistics
| Branch: | Revision:

iof-bird-daemon / filter / config.Y @ 11cb6202

History | View | Annotate | Download (15.6 KB)

1 b9d70dc8 Pavel Machek
/*
2
 *	BIRD - filters
3
 *
4 1c20608e Martin Mares
 *	Copyright 1998--2000 Pavel Machek
5 b9d70dc8 Pavel Machek
 *
6
 *	Can be freely distributed and used under the terms of the GNU GPL.
7 c9f8c1a8 Pavel Machek
 *
8 1877dab2 Pavel Machek
	FIXME: priority of ! should be lower
9 b9d70dc8 Pavel Machek
 */
10
11
CF_HDR
12
13 2edb31b0 Martin Mares
CF_DEFINES
14
15 2d496d20 Pavel Machek
#define P(a,b) ((a<<8) | b)
16
17 b9d70dc8 Pavel Machek
CF_DECLS
18
19 e4a73dbf Pavel Machek
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
20 ba921648 Pavel Machek
	ACCEPT, REJECT, ERROR, QUITBIRD,
21 10a53608 Pavel Machek
	INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST,
22 7db7b7db Pavel Machek
	IF, THEN, ELSE, CASE,
23 23b1539b Pavel Machek
	TRUE, FALSE,
24 0dc4431c Pavel Machek
	FROM, GW, NET, MASK, SOURCE, SCOPE, CAST, DEST, PREFERENCE,
25 36bbfc70 Pavel Machek
	LEN,
26 f4536657 Pavel Machek
	DEFINED,
27 7f77e250 Pavel Machek
	ADD, DELETE, CONTAINS, RESET,
28 e399b6f6 Pavel Machek
	PREPEND, MATCH,
29 afc54517 Pavel Machek
	EMPTY,
30 1c20608e Martin Mares
	FILTER, WHERE, EVAL)
31 b9d70dc8 Pavel Machek
32 f4536657 Pavel Machek
%nonassoc THEN
33 4ed8718a Pavel Machek
%nonassoc ELSE
34 f4536657 Pavel Machek
35 2bdb5e00 Pavel Machek
%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr static_attr function_call
36 430da60f Martin Mares
%type <f> filter filter_body where_filter
37 4515bdba Pavel Machek
%type <i> type break_command pair
38 41be4444 Pavel Machek
%type <e> set_item set_items switch_body
39 e3f2d5fc Martin Mares
%type <v> set_atom fprefix fprefix_s fipa
40 6dc7a0cb Pavel Machek
%type <s> decls declsn one_decl function_params 
41 77de6882 Pavel Machek
%type <h> bgp_path
42 b9d70dc8 Pavel Machek
43
CF_GRAMMAR
44
45 e0f2e42f Martin Mares
CF_ADDTO(conf, filter_def)
46
filter_def:
47 cb8034f4 Pavel Machek
   FILTER SYM { cf_push_scope( $2 ); } filter_body {
48 bf3eb98e Martin Mares
     $2 = cf_define_symbol($2, SYM_FILTER, $4);
49 ae3e1af2 Pavel Machek
     $4->name = $2->name;
50 d4d75628 Pavel Machek
     DBG( "We have new filter defined (%s)\n", $2->name );
51 ae3e1af2 Pavel Machek
     cf_pop_scope();
52 b9d70dc8 Pavel Machek
   }
53
 ;
54
55 1c20608e Martin Mares
CF_ADDTO(conf, filter_eval)
56
filter_eval:
57
   EVAL term { f_eval_int($2); }
58
 ;
59
60 ba921648 Pavel Machek
type:
61
   INT { $$ = T_INT; }
62
 | BOOL { $$ = T_BOOL; }
63
 | IP { $$ = T_IP; }
64
 | PREFIX { $$ = T_PREFIX; }
65
 | PAIR { $$ = T_PAIR; }
66
 | STRING { $$ = T_STRING; }
67 10a53608 Pavel Machek
 | BGPMASK { $$ = T_PATH_MASK; }
68
 | BGPPATH { $$ = T_PATH; }
69
 | CLIST { $$ = T_CLIST; }
70 ba921648 Pavel Machek
 | type SET { 
71
	switch ($1) {
72
	  default:
73 a5a947d4 Pavel Machek
		cf_error( "You can't create sets of this type." );
74 de10a974 Martin Mares
	  case T_INT: case T_IP: case T_PREFIX: case T_PAIR: ;
75 ba921648 Pavel Machek
	}
76
	$$ = $1 | T_SET;
77
	}
78
 ;
79
80 6dc7a0cb Pavel Machek
one_decl:
81
   type SYM {
82 bf3eb98e Martin Mares
     $2 = cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
83 d4d75628 Pavel Machek
     DBG( "New variable %s type %x\n", $2->name, $1 );
84 cb8034f4 Pavel Machek
     $2->aux = 0;
85 d3dd620b Pavel Machek
     {
86
       struct f_val * val; 
87
       val = cfg_alloc(sizeof(struct f_val)); 
88
       val->type = $1; 
89
       $2->aux2 = val;
90
     }
91 6542ece9 Pavel Machek
     $$=$2;
92 ba921648 Pavel Machek
   }
93
 ;
94
95 6dc7a0cb Pavel Machek
/* Decls with ';' at the end */
96
decls: /* EMPTY */ { $$ = NULL; }
97
 | one_decl ';' decls {
98
     $$ = $1;
99 cb8034f4 Pavel Machek
     $$->aux = (int) $3;
100 6dc7a0cb Pavel Machek
   }
101
 ;
102
103 3c989eb4 Pavel Machek
/* Declarations that have no ';' at the end. */
104 6dc7a0cb Pavel Machek
declsn: one_decl { $$ = $1; }
105
 | declsn ';' one_decl {
106 4515bdba Pavel Machek
     $$ = $1;
107
     $$->aux = (int) $3;
108 6dc7a0cb Pavel Machek
   }
109
 ;
110
111 e0f2e42f Martin Mares
filter_body:
112 ba921648 Pavel Machek
   function_body {
113 e0f2e42f Martin Mares
     struct filter *f = cfg_alloc(sizeof(struct filter));
114
     f->name = NULL;
115 ba921648 Pavel Machek
     f->root = $1;
116 e0f2e42f Martin Mares
     $$ = f;
117
   }
118
 ;
119
120
filter:
121
   SYM {
122 a5a947d4 Pavel Machek
     if ($1->class != SYM_FILTER) cf_error("No such filter.");
123 e0f2e42f Martin Mares
     $$ = $1->def;
124
   }
125
 | filter_body
126
 ;
127
128 430da60f Martin Mares
where_filter:
129
   WHERE term {
130
     /* Construct 'IF term THEN ACCEPT; REJECT;' */
131
     struct filter *f = cfg_alloc(sizeof(struct filter));
132
     struct f_inst *i, *acc, *rej;
133
     acc = f_new_inst();		/* ACCEPT */
134 2d496d20 Pavel Machek
     acc->code = P('p',',');
135 430da60f Martin Mares
     acc->a1.p = NULL;
136
     acc->a2.i = F_ACCEPT;
137
     rej = f_new_inst();		/* REJECT */
138 2d496d20 Pavel Machek
     rej->code = P('p',',');
139 430da60f Martin Mares
     rej->a1.p = NULL;
140
     rej->a2.i = F_REJECT;
141
     i = f_new_inst();			/* IF */
142
     i->code = '?';
143
     i->a1.p = $2;
144
     i->a2.p = acc;
145
     i->next = rej;
146
     f->name = NULL;
147
     f->root = i;
148
     $$ = f;
149
  }
150
 ;
151
152 ba921648 Pavel Machek
function_params:
153 d4d75628 Pavel Machek
   '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
154 6dc7a0cb Pavel Machek
 | '(' ')' { $$=NULL; }
155 ba921648 Pavel Machek
 ;
156 b9d70dc8 Pavel Machek
157 ba921648 Pavel Machek
function_body:
158
   decls '{' cmds '}' {
159
     $$ = $3;
160 84c7e194 Pavel Machek
   }
161 ba921648 Pavel Machek
 ;
162
163
CF_ADDTO(conf, function_def)
164
function_def:
165 bf3eb98e Martin Mares
   FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name );
166
     $2 = cf_define_symbol($2, SYM_FUNCTION, NULL);
167
     cf_push_scope($2);
168
   } function_params function_body {
169
     $2->def = $5;
170 cb8034f4 Pavel Machek
     $2->aux = (int) $4;
171 ae3e1af2 Pavel Machek
     $2->aux2 = $5;
172 d4d75628 Pavel Machek
     DBG("Hmm, we've got one function here - %s\n", $2->name); 
173 ae3e1af2 Pavel Machek
     cf_pop_scope();
174 ba921648 Pavel Machek
   }
175
 ;
176
177
/* Programs */
178
179
cmds: /* EMPTY */ { $$ = NULL; }
180
 | cmd cmds {
181 84c7e194 Pavel Machek
     if ($1) {
182 7db7b7db Pavel Machek
       if ($1->next)
183 ad9074e9 Pavel Machek
	 bug("Command has next already set");
184 ba921648 Pavel Machek
       $1->next = $2;
185 84c7e194 Pavel Machek
       $$ = $1;
186 ba921648 Pavel Machek
     } else $$ = $2;
187 84c7e194 Pavel Machek
   }
188
 ;
189
190 2575593e Pavel Machek
block:
191 ba921648 Pavel Machek
   cmd {
192 2575593e Pavel Machek
     $$=$1;
193
   }
194
 | '{' cmds '}' {
195
     $$=$2;
196
   }
197
 ;
198
199 d3dd620b Pavel Machek
/*
200
 * Simple types, their bison value is int
201
 */
202
pair:
203
   '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
204
 ;
205
206
/*
207
 * Complex types, their bison value is struct f_val
208
 */
209 758458be Martin Mares
fprefix_s:
210 60de3356 Pavel Machek
   IPA '/' NUM %prec '/' {
211 a5a947d4 Pavel Machek
     if (!ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
212 758458be Martin Mares
     $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
213
   }
214 d3dd620b Pavel Machek
 ;
215
216 758458be Martin Mares
fprefix:
217
   fprefix_s { $$ = $1; }
218
 | fprefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
219
 | fprefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
220
 | fprefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
221 d3dd620b Pavel Machek
 ;
222
223 e3f2d5fc Martin Mares
fipa:
224 60de3356 Pavel Machek
   IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
225 d3dd620b Pavel Machek
 ;
226
227 38506f71 Pavel Machek
set_atom:
228 d3dd620b Pavel Machek
   NUM  { $$.type = T_INT; $$.val.i = $1; }
229
 | pair { $$.type = T_PAIR; $$.val.i = $1; }
230 e3f2d5fc Martin Mares
 | fipa { $$ = $1; }
231 758458be Martin Mares
 | fprefix { $$ = $1; }
232 1895e81e Pavel Machek
 | ENUM {  $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
233 38506f71 Pavel Machek
 ; 
234
235
set_item:
236 995e5894 Pavel Machek
   set_atom { 
237
	$$ = f_new_tree(); 
238
	$$->from = $1; 
239
	if ($1.type != T_PREFIX)
240
		$$->to = $1;
241
	else {
242
		$$->to = $1;
243
		$$->to.val.px.ip = ipa_or( $$->to.val.px.ip, ipa_not( ipa_mkmask( $$->to.val.px.len ) ));
244
	}
245
   }
246
 | set_atom '.' '.' set_atom { 
247
	$$ = f_new_tree(); 
248
	$$->from = $1; 
249
	$$->to = $4; 
250 a5a947d4 Pavel Machek
	if (($1.type == T_PREFIX) || ($4.type == T_PREFIX)) cf_error( "You can't use prefixes for range." ); 
251 995e5894 Pavel Machek
   }
252 38506f71 Pavel Machek
 ;
253
254
set_items:
255
   set_item { $$ = $1; }
256
 | set_items ',' set_item { $$ = $3; $$->left = $1; }
257
 ;
258
259 41be4444 Pavel Machek
switch_body: /* EMPTY */ { $$ = NULL; }
260
 | set_item ':' cmds switch_body {
261
     $$ = $1;
262
     $$->data = $3;
263
     $$->left = $4;
264
   }
265
 | ELSE ':' cmds {
266
     $$ = f_new_tree(); 
267
     $$->from.type = T_VOID; 
268
     $$->to.type = T_VOID;
269
     $$->data = $3;
270
   }
271
 ;
272 d3dd620b Pavel Machek
273 e4a73dbf Pavel Machek
/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
274
275 77de6882 Pavel Machek
276
bgp_path: 
277 11cb6202 Ondrej Zajicek
   NUM          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = $1; $$->any = 0; }
278
 | '?'          { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val  = 0;  $$->any = 1; }
279
 | NUM bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = $1; $$->any = 0; }
280
 | '?' bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2;   $$->val  = 0;  $$->any = 1; }
281 77de6882 Pavel Machek
 ;
282
283 23b1539b Pavel Machek
constant:
284 e4a73dbf Pavel Machek
   NUM    { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT;  $$->a2.i = $1; }
285 c7b43f33 Pavel Machek
 | TRUE   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1;  }
286
 | FALSE  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0;  }
287
 | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
288
 | pair   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR;  $$->a2.i = $1; }
289 e3f2d5fc Martin Mares
 | fipa	   { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
290 758458be Martin Mares
 | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
291 d4d75628 Pavel Machek
 | '[' 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" ); }
292 c7b43f33 Pavel Machek
 | ENUM	  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
293 f71bded6 Pavel Machek
 | '/' bgp_path '/' { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $2; $$->a1.p = val; }
294 23b1539b Pavel Machek
 ;
295
296 db1326aa Martin Mares
/*
297
 *  Maybe there are no dynamic attributes defined by protocols.
298
 *  For such cases, we force the dynamic_attr list to contain
299
 *  at least an invalid token, so it's syntantically correct.
300
 */
301
CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
302 f4536657 Pavel Machek
303 2e18b87d Pavel Machek
rtadot: /* EMPTY, we are not permitted RTA. prefix */
304 6c14255d Pavel Machek
 ;
305 f4536657 Pavel Machek
306 2d496d20 Pavel Machek
function_call:
307
   SYM '(' var_list ')' {
308
     struct symbol *sym;
309
     struct f_inst *inst = $3;
310
     if ($1->class != SYM_FUNCTION)
311 a5a947d4 Pavel Machek
       cf_error("You can't call something which is not a function. Really.");
312 d4d75628 Pavel Machek
     DBG("You are calling function %s\n", $1->name);
313 2d496d20 Pavel Machek
     $$ = f_new_inst();
314
     $$->code = P('c','a');
315
     $$->a1.p = inst;
316
     $$->a2.p = $1->aux2;
317
     sym = (void *) $1->aux;
318
     while (sym || inst) {
319
       if (!sym || !inst)
320 a5a947d4 Pavel Machek
	 cf_error("Wrong number of arguments for function %s.", $1->name);
321 d4d75628 Pavel Machek
       DBG( "You should pass parameter called %s\n", sym->name);
322 2d496d20 Pavel Machek
       inst->a1.p = sym;
323
       sym = (void *) sym->aux;
324
       inst = inst->next;
325
     }
326
   }
327
 ;
328
329 2bdb5e00 Pavel Machek
static_attr:
330 0dc4431c Pavel Machek
   FROM    { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = OFFSETOF(struct rta, from);   $$->a1.i = 1; }
331 26c09e1d Pavel Machek
332 0dc4431c Pavel Machek
 | GW      { $$ = f_new_inst(); $$->aux = T_IP;         $$->a2.i = OFFSETOF(struct rta, gw);     $$->a1.i = 1; }
333 26c09e1d Pavel Machek
 | NET     { $$ = f_new_inst(); $$->aux = T_PREFIX;     $$->a2.i = 0x12345678; /* This is actually ok - T_PREFIX is special-cased. */ }
334
 | SOURCE  { $$ = f_new_inst(); $$->aux = T_ENUM_RTS;   $$->a2.i = OFFSETOF(struct rta, source); }
335 0dc4431c Pavel Machek
 | SCOPE   { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope);  $$->a1.i = 1; }
336 26c09e1d Pavel Machek
 | CAST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTC;   $$->a2.i = OFFSETOF(struct rta, cast); }
337
 | DEST    { $$ = f_new_inst(); $$->aux = T_ENUM_RTD;   $$->a2.i = OFFSETOF(struct rta, dest); }
338 2bdb5e00 Pavel Machek
 ;
339
340 84c7e194 Pavel Machek
term:
341 f4536657 Pavel Machek
   '(' term ')'      { $$ = $2; }
342 d4d75628 Pavel Machek
 | term '+' term     { $$ = f_new_inst(); $$->code = '+';        $$->a1.p = $1; $$->a2.p = $3; }
343 c5a06f65 Pavel Machek
 | term '-' term     { $$ = f_new_inst(); $$->code = '-';        $$->a1.p = $1; $$->a2.p = $3; }
344
 | term '*' term     { $$ = f_new_inst(); $$->code = '*';        $$->a1.p = $1; $$->a2.p = $3; }
345
 | term '/' term     { $$ = f_new_inst(); $$->code = '/';        $$->a1.p = $1; $$->a2.p = $3; }
346 5f4aee76 Pavel Machek
 | term AND term     { $$ = f_new_inst(); $$->code = '&';        $$->a1.p = $1; $$->a2.p = $3; }
347
 | term OR  term     { $$ = f_new_inst(); $$->code = '|';        $$->a1.p = $1; $$->a2.p = $3; }
348 2d496d20 Pavel Machek
 | term '=' term     { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
349 d4d75628 Pavel Machek
 | term NEQ term { $$ = f_new_inst(); $$->code = P('!','=');     $$->a1.p = $1; $$->a2.p = $3; }
350
 | term '<' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $1; $$->a2.p = $3; }
351
 | term LEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $1; $$->a2.p = $3; }
352
 | term '>' term     { $$ = f_new_inst(); $$->code = '<';        $$->a1.p = $3; $$->a2.p = $1; }
353
 | term GEQ term { $$ = f_new_inst(); $$->code = P('<','=');     $$->a1.p = $3; $$->a2.p = $1; }
354
 | term '~' term     { $$ = f_new_inst(); $$->code = '~';        $$->a1.p = $1; $$->a2.p = $3; }
355 995e5894 Pavel Machek
 | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
356 2d496d20 Pavel Machek
 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e');  $$->a1.p = $3; }
357 23b1539b Pavel Machek
358 1183b6b2 Pavel Machek
 | constant { $$ = $1; }
359 2575593e Pavel Machek
 | SYM {
360
     $$ = f_new_inst();
361
     switch ($1->class) {
362 cbfd671f Pavel Machek
       case SYM_NUMBER:
363
	$$ = f_new_inst();
364
	$$->code = 'c'; 
365
	$$->aux = T_INT; 
366
	$$->a2.i = $1->aux;
367
	break;
368
       case SYM_IPA:
369
	{ NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.px.ip = * (ip_addr *) ($1->def); }
370
	break;
371 ba921648 Pavel Machek
       case SYM_VARIABLE | T_INT:
372 d3dd620b Pavel Machek
       case SYM_VARIABLE | T_PAIR:
373
       case SYM_VARIABLE | T_PREFIX:
374
       case SYM_VARIABLE | T_IP:
375 dcab7890 Pavel Machek
       case SYM_VARIABLE | T_PATH_MASK:
376 e399b6f6 Pavel Machek
       case SYM_VARIABLE | T_PATH:
377 9c400ec9 Pavel Machek
       case SYM_VARIABLE | T_CLIST:
378 d3dd620b Pavel Machek
	 $$->code = 'C';
379
	 $$->a1.p = $1->aux2;
380 2575593e Pavel Machek
	 break;
381
       default:
382 a5a947d4 Pavel Machek
	 cf_error("%s: variable expected.", $1->name );
383 2575593e Pavel Machek
     }
384
   }
385 4515bdba Pavel Machek
386 0dc4431c Pavel Machek
 | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; }
387 2bdb5e00 Pavel Machek
388
 | rtadot static_attr { $$ = $2; $$->code = 'a'; }
389 fe613ecd Pavel Machek
390 db1326aa Martin Mares
 | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
391 36bbfc70 Pavel Machek
392 2d496d20 Pavel Machek
 | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
393 684c6f5a Pavel Machek
 | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
394 2d496d20 Pavel Machek
 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
395 7f77e250 Pavel Machek
396
/* Communities */
397 10a53608 Pavel Machek
/* This causes one shift/reduce conflict
398
 | rtadot dynamic_attr '.' ADD '(' term ')' { }
399
 | rtadot dynamic_attr '.' DELETE '(' term ')' { }
400
 | rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
401 a2d15746 Pavel Machek
 | rtadot dynamic_attr '.' RESET{ }
402 10a53608 Pavel Machek
*/
403 7f77e250 Pavel Machek
404 e399b6f6 Pavel Machek
 | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
405 9c400ec9 Pavel Machek
 | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
406 e399b6f6 Pavel Machek
 | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } 
407 4444ed2b Pavel Machek
 | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } 
408
 | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
409 afc54517 Pavel Machek
410 a2d15746 Pavel Machek
/* | term '.' LEN { $$->code = P('P','l'); } */
411 7f77e250 Pavel Machek
412 995e5894 Pavel Machek
/* function_call is inlined here */
413
 | SYM '(' var_list ')' {
414
     struct symbol *sym;
415
     struct f_inst *inst = $3;
416
     if ($1->class != SYM_FUNCTION)
417 a5a947d4 Pavel Machek
       cf_error("You can't call something which is not a function. Really.");
418 995e5894 Pavel Machek
     DBG("You are calling function %s\n", $1->name);
419
     $$ = f_new_inst();
420
     $$->code = P('c','a');
421
     $$->a1.p = inst;
422
     $$->a2.p = $1->aux2;
423
     sym = (void *) $1->aux;
424
     while (sym || inst) {
425
       if (!sym || !inst)
426 a5a947d4 Pavel Machek
	 cf_error("Wrong number of arguments for function %s.", $1->name);
427 995e5894 Pavel Machek
       DBG( "You should pass parameter called %s\n", sym->name);
428
       inst->a1.p = sym;
429
       sym = (void *) sym->aux;
430
       inst = inst->next;
431
     }
432
   }
433 ba921648 Pavel Machek
 ;
434
435
break_command:
436 03e3d184 Martin Mares
   QUITBIRD { $$ = F_QUITBIRD; }
437
 | ACCEPT { $$ = F_ACCEPT; }
438
 | REJECT { $$ = F_REJECT; }
439
 | ERROR { $$ = F_ERROR; }
440
 | PRINT { $$ = F_NOP; }
441
 | PRINTN { $$ = F_NONL; }
442 ba921648 Pavel Machek
 ;
443
444 23b1539b Pavel Machek
print_one:
445 2db3b288 Pavel Machek
   term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
446 23b1539b Pavel Machek
 ;
447
448
print_list: /* EMPTY */ { $$ = NULL; }
449 995e5894 Pavel Machek
 | print_one { $$ = $1; }
450
 | print_one ',' print_list {
451 23b1539b Pavel Machek
     if ($1) {
452 995e5894 Pavel Machek
       $1->next = $3;
453 23b1539b Pavel Machek
       $$ = $1;
454 995e5894 Pavel Machek
     } else $$ = $3;
455 23b1539b Pavel Machek
   }
456 995e5894 Pavel Machek
 
457 23b1539b Pavel Machek
 ;
458
459 6dc7a0cb Pavel Machek
var_listn: term { 
460 d3dd620b Pavel Machek
     $$ = f_new_inst();
461
     $$->code = 's';
462
     $$->a1.p = NULL;
463
     $$->a2.p = $1;
464
     $$->next = NULL;
465
   }
466 6dc7a0cb Pavel Machek
 | term ',' var_listn {
467 6542ece9 Pavel Machek
     $$ = f_new_inst();
468
     $$->code = 's';
469
     $$->a1.p = NULL;
470
     $$->a2.p = $1;
471
     $$->next = $3;
472
   }
473
 ;
474
475 6dc7a0cb Pavel Machek
var_list: /* EMPTY */ { $$ = NULL; }
476
 | var_listn { $$ = $1; }
477
 ;
478
479 23b1539b Pavel Machek
cmd:
480 49955645 Martin Mares
   IF term THEN block {
481
     $$ = f_new_inst();
482
     $$->code = '?';
483
     $$->a1.p = $2;
484
     $$->a2.p = $4;
485 23b1539b Pavel Machek
   }
486 49955645 Martin Mares
 | IF term THEN block ELSE block {
487
     struct f_inst *i = f_new_inst();
488
     i->code = '?';
489
     i->a1.p = $2;
490
     i->a2.p = $4;
491 23b1539b Pavel Machek
     $$ = f_new_inst();
492
     $$->code = '?';
493 49955645 Martin Mares
     $$->a1.p = i;
494
     $$->a2.p = $6;
495 23b1539b Pavel Machek
   }
496 ba921648 Pavel Machek
 | SYM '=' term ';' {
497 84c7e194 Pavel Machek
     $$ = f_new_inst();
498 d4d75628 Pavel Machek
     DBG( "Ook, we'll set value\n" );
499 ba921648 Pavel Machek
     if (($1->class & ~T_MASK) != SYM_VARIABLE)
500 a5a947d4 Pavel Machek
       cf_error( "You may set only variables." );
501 23b1539b Pavel Machek
     $$->code = 's';
502 2db3b288 Pavel Machek
     $$->a1.p = $1;
503
     $$->a2.p = $3;
504 b9d70dc8 Pavel Machek
   }
505 2d496d20 Pavel Machek
 | RETURN term ';' {
506
     $$ = f_new_inst();
507 d4d75628 Pavel Machek
     DBG( "Ook, we'll return the value\n" );
508 2d496d20 Pavel Machek
     $$->code = 'r';
509
     $$->a1.p = $2;
510
   }
511 db1326aa Martin Mares
 | rtadot dynamic_attr '=' term ';' {
512 6c14255d Pavel Machek
     $$ = $2;
513 0dc4431c Pavel Machek
     $$->code = P('e','S');
514 6c14255d Pavel Machek
     $$->a1.p = $4;
515 f31156ca Pavel Machek
   }
516 0dc4431c Pavel Machek
 | rtadot static_attr '=' term ';' {
517
     $$ = $2;
518
     if (!$$->a1.i)
519
       cf_error( "This static attribute is read-only.");
520
     $$->code = P('a','S');
521
     $$->a1.p = $4;
522
   }
523
 | PREFERENCE '=' term ';' {
524
     $$ = f_new_inst();
525
     $$->code = P('P','S');
526
     $$->a1.p = $3;
527
   } 
528 db1326aa Martin Mares
 | UNSET '(' rtadot dynamic_attr ')' ';' {
529 6c14255d Pavel Machek
     $$ = $4;
530 9f4929e7 Martin Mares
     $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
531 2d496d20 Pavel Machek
     $$->code = P('e','S');
532 48f9e019 Pavel Machek
     $$->a1.p = NULL;
533 c7b43f33 Pavel Machek
   }
534 2d496d20 Pavel Machek
 | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
535
 | function_call ';' { $$ = $1; }
536 7db7b7db Pavel Machek
 | CASE term '{' switch_body '}' {
537
      $$ = f_new_inst();
538 2d496d20 Pavel Machek
      $$->code = P('S','W');
539 7db7b7db Pavel Machek
      $$->a1.p = $2;
540 41be4444 Pavel Machek
      $$->a2.p = build_tree( $4 );
541 7db7b7db Pavel Machek
   }
542 7d6eebae Pavel Machek
543
544
 | rtadot dynamic_attr '.' EMPTY ';' 
545
  { struct f_inst *i = f_new_inst(); i->code = 'E'; i->aux = T_CLIST; $$ = $2; $$->code = P('e','S'); $$->a1.p = i; }
546
 | rtadot dynamic_attr '.' PREPEND '(' term ')' ';'   { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); }
547
 | rtadot dynamic_attr '.' ADD '(' term ')' ';'       { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } 
548
 | rtadot dynamic_attr '.' DELETE '(' term ')' ';'    { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } 
549 b9d70dc8 Pavel Machek
 ;
550
551
CF_END