]> git.ipfire.org Git - thirdparty/bird.git/blame - filter/config.Y
Test new syntax of add() and delete().
[thirdparty/bird.git] / filter / config.Y
CommitLineData
b9d70dc8
PM
1/*
2 * BIRD - filters
3 *
6542ece9 4 * Copyright 1998,1999 Pavel Machek
b9d70dc8
PM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
c9f8c1a8 7 *
f4536657 8 FIXME (nonurgent): define keyword
2d496d20 9 FIXME (for BGP): whole system of paths, path ~ string, path.prepend(), path.originate
c9f8c1a8 10 FIXME: create community lists
60d7d10e 11 FIXME: IP addresses in ipv6
0a06a9b8
PM
12
13
7f77e250
PM
14 FIXME: check messages for \n at the end
15
0a06a9b8
PM
16(1) Cesty
17
18 AS paths budtez interne reprezentovany stejne jako v BGP (viz RFC 1771),
19to znamena jako posloupnost segmentu, z nichz kazdy je budto posloupnost nebo
20mnozina cisel ASu. Na cestach nadefinuji nasledujici operace:
21
22 - zformatovani do stringu
23 - append dalsiho AS k ceste
24
25Filtry by mely podporovat:
26
77de6882 27 - operator pridani AS k ceste [bgppath_prepend]
0a06a9b8
PM
28 - matchovani na pritomnost podposloupnosti v ceste (pricemz vyskytne-li
29 se tam mnozina, tak si ji lze predstavit prerovnanou v libovolnem
30 poradi)
7f77e250 31
0a06a9b8
PM
32 - operator zjisteni delky cesty (pro vypocet metrik)
33
34Byl bych rad, kdyby se samotne matchovaci funkce objevily v proto/bgp/attrs.c.
35
7f77e250
PM
36Jsou v sitove endianite. [lib/unaligned.h]
37
0a06a9b8
PM
38
39(2) Community-listy
40
7f77e250
PM
41posloupnost 32bitovych cisel s delkou.
42
0a06a9b8
PM
43Community list budiz interne reprezentovan jako posloupnost 32-bitovych cisel.
44
45Filtry by se mely na communities divat jako na usporadane dvojice 16-bitovych
46cisel (prvni je cislo AS, ktery community definoval, druhe pak community ID
47v ramci AS) a melo by byt mozne definovat si konstanty typu community.
48K dispozici by mely byt nasledujici operace:
49
7f77e250
PM
50 - zjisteni pritomnosti community v listu [linearni pruchod]
51 - pridani community do listu [s kopii]
52 - odebrani community z listu [s kopii]
0a06a9b8
PM
53 - zresetovani listu
54
55Pro operace na cestach i na community listech by se mela pouzivat `teckova'
56notace pouzita v mem puvodnim navrhu syntaxe.
57
b9d70dc8
PM
58 */
59
60CF_HDR
61
2d496d20
PM
62#define P(a,b) ((a<<8) | b)
63
b9d70dc8
PM
64CF_DECLS
65
e4a73dbf 66CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ba921648 67 ACCEPT, REJECT, ERROR, QUITBIRD,
10a53608 68 INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST,
7db7b7db 69 IF, THEN, ELSE, CASE,
23b1539b 70 TRUE, FALSE,
db1326aa 71 FROM, GW, NET, MASK, SOURCE,
36bbfc70 72 LEN,
f4536657 73 DEFINED,
7f77e250 74 ADD, DELETE, CONTAINS, RESET,
e399b6f6 75 PREPEND, MATCH,
afc54517 76 EMPTY,
430da60f 77 FILTER, WHERE)
b9d70dc8 78
f4536657 79%nonassoc THEN
4ed8718a 80%nonassoc ELSE
f4536657 81
db1326aa 82%type <x> term block cmds cmd function_body constant print_one print_list var_list var_listn dynamic_attr function_call
430da60f 83%type <f> filter filter_body where_filter
4515bdba 84%type <i> type break_command pair
41be4444 85%type <e> set_item set_items switch_body
d3dd620b 86%type <v> set_atom prefix prefix_s ipa
6dc7a0cb 87%type <s> decls declsn one_decl function_params
77de6882
PM
88%type <h> bgp_path
89%type <i> bgp_one
b9d70dc8
PM
90
91CF_GRAMMAR
92
e0f2e42f
MM
93CF_ADDTO(conf, filter_def)
94filter_def:
cb8034f4 95 FILTER SYM { cf_push_scope( $2 ); } filter_body {
ae3e1af2
PM
96 cf_define_symbol($2, SYM_FILTER, $4);
97 $4->name = $2->name;
d4d75628 98 DBG( "We have new filter defined (%s)\n", $2->name );
ae3e1af2 99 cf_pop_scope();
b9d70dc8
PM
100 }
101 ;
102
ba921648
PM
103type:
104 INT { $$ = T_INT; }
105 | BOOL { $$ = T_BOOL; }
106 | IP { $$ = T_IP; }
107 | PREFIX { $$ = T_PREFIX; }
108 | PAIR { $$ = T_PAIR; }
109 | STRING { $$ = T_STRING; }
10a53608
PM
110 | BGPMASK { $$ = T_PATH_MASK; }
111 | BGPPATH { $$ = T_PATH; }
112 | CLIST { $$ = T_CLIST; }
ba921648
PM
113 | type SET {
114 switch ($1) {
115 default:
116 cf_error( "You can not create sets of this type\n" );
117 case T_INT: case T_IP: case T_PREFIX: case T_PAIR:
118 }
119 $$ = $1 | T_SET;
120 }
121 ;
122
6dc7a0cb
PM
123one_decl:
124 type SYM {
4107df1d 125 cf_define_symbol($2, SYM_VARIABLE | $1, NULL);
d4d75628 126 DBG( "New variable %s type %x\n", $2->name, $1 );
cb8034f4 127 $2->aux = 0;
d3dd620b
PM
128 {
129 struct f_val * val;
130 val = cfg_alloc(sizeof(struct f_val));
131 val->type = $1;
132 $2->aux2 = val;
133 }
6542ece9 134 $$=$2;
ba921648
PM
135 }
136 ;
137
6dc7a0cb
PM
138/* Decls with ';' at the end */
139decls: /* EMPTY */ { $$ = NULL; }
140 | one_decl ';' decls {
141 $$ = $1;
cb8034f4 142 $$->aux = (int) $3;
6dc7a0cb
PM
143 }
144 ;
145
3c989eb4 146/* Declarations that have no ';' at the end. */
6dc7a0cb
PM
147declsn: one_decl { $$ = $1; }
148 | declsn ';' one_decl {
4515bdba
PM
149 $$ = $1;
150 $$->aux = (int) $3;
6dc7a0cb
PM
151 }
152 ;
153
e0f2e42f 154filter_body:
ba921648 155 function_body {
e0f2e42f
MM
156 struct filter *f = cfg_alloc(sizeof(struct filter));
157 f->name = NULL;
ba921648 158 f->root = $1;
e0f2e42f
MM
159 $$ = f;
160 }
161 ;
162
163filter:
164 SYM {
165 if ($1->class != SYM_FILTER) cf_error("No such filter");
166 $$ = $1->def;
167 }
168 | filter_body
169 ;
170
430da60f
MM
171where_filter:
172 WHERE term {
173 /* Construct 'IF term THEN ACCEPT; REJECT;' */
174 struct filter *f = cfg_alloc(sizeof(struct filter));
175 struct f_inst *i, *acc, *rej;
176 acc = f_new_inst(); /* ACCEPT */
2d496d20 177 acc->code = P('p',',');
430da60f
MM
178 acc->a1.p = NULL;
179 acc->a2.i = F_ACCEPT;
180 rej = f_new_inst(); /* REJECT */
2d496d20 181 rej->code = P('p',',');
430da60f
MM
182 rej->a1.p = NULL;
183 rej->a2.i = F_REJECT;
184 i = f_new_inst(); /* IF */
185 i->code = '?';
186 i->a1.p = $2;
187 i->a2.p = acc;
188 i->next = rej;
189 f->name = NULL;
190 f->root = i;
191 $$ = f;
192 }
193 ;
194
ba921648 195function_params:
d4d75628 196 '(' declsn ')' { DBG( "Have function parameters\n" ); $$=$2; }
6dc7a0cb 197 | '(' ')' { $$=NULL; }
ba921648 198 ;
b9d70dc8 199
ba921648
PM
200function_body:
201 decls '{' cmds '}' {
202 $$ = $3;
84c7e194 203 }
ba921648
PM
204 ;
205
206CF_ADDTO(conf, function_def)
207function_def:
d4d75628 208 FUNCTION SYM { DBG( "Begining of function %s\n", $2->name ); cf_push_scope($2); } function_params function_body {
ba921648 209 extern struct f_inst *startup_func;
ae3e1af2 210 cf_define_symbol($2, SYM_FUNCTION, $5);
ba921648 211 if (!strcasecmp($2->name, "startup"))
ae3e1af2 212 startup_func = $5;
cb8034f4 213 $2->aux = (int) $4;
ae3e1af2 214 $2->aux2 = $5;
d4d75628 215 DBG("Hmm, we've got one function here - %s\n", $2->name);
ae3e1af2 216 cf_pop_scope();
ba921648
PM
217 }
218 ;
219
220/* Programs */
221
222cmds: /* EMPTY */ { $$ = NULL; }
223 | cmd cmds {
84c7e194 224 if ($1) {
7db7b7db
PM
225 if ($1->next)
226 bug("Command has next already set\n");
ba921648 227 $1->next = $2;
84c7e194 228 $$ = $1;
ba921648 229 } else $$ = $2;
84c7e194
PM
230 }
231 ;
232
2575593e 233block:
ba921648 234 cmd {
2575593e
PM
235 $$=$1;
236 }
237 | '{' cmds '}' {
238 $$=$2;
239 }
240 ;
241
d3dd620b
PM
242/*
243 * Simple types, their bison value is int
244 */
245pair:
246 '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; }
247 ;
248
249/*
250 * Complex types, their bison value is struct f_val
251 */
252prefix_s:
455ca441 253 IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; if (ipa_nonzero(ipa_and($$.val.px.ip, ipa_not(ipa_mkmask($$.val.px.len))))) cf_error( "%I/%d is not really prefix\n", $$.val.px.ip, $$.val.px.len ); }
d3dd620b
PM
254 ;
255
256prefix:
257 prefix_s { $$ = $1; }
258 | prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; }
259 | prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; }
6dc7a0cb 260 | prefix_s '{' NUM ',' NUM '}' { $$ = $1; $$.val.px.len |= LEN_RANGE | ($3 << 16) | ($5 << 8); }
d3dd620b
PM
261 ;
262
263ipa:
6dc7a0cb 264 IPA { $$.type = T_IP; $$.val.px.ip = $1; }
d3dd620b
PM
265 ;
266
38506f71 267set_atom:
d3dd620b
PM
268 NUM { $$.type = T_INT; $$.val.i = $1; }
269 | pair { $$.type = T_PAIR; $$.val.i = $1; }
270 | ipa { $$ = $1; }
271 | prefix { $$ = $1; }
38506f71
PM
272 ;
273
274set_item:
995e5894
PM
275 set_atom {
276 $$ = f_new_tree();
277 $$->from = $1;
278 if ($1.type != T_PREFIX)
279 $$->to = $1;
280 else {
281 $$->to = $1;
282 $$->to.val.px.ip = ipa_or( $$->to.val.px.ip, ipa_not( ipa_mkmask( $$->to.val.px.len ) ));
283 }
284 }
285 | set_atom '.' '.' set_atom {
286 $$ = f_new_tree();
287 $$->from = $1;
288 $$->to = $4;
289 if (($1.type == T_PREFIX) || ($4.type == T_PREFIX)) cf_error( "You can not use prefixes for range" );
290 }
38506f71
PM
291 ;
292
293set_items:
294 set_item { $$ = $1; }
295 | set_items ',' set_item { $$ = $3; $$->left = $1; }
296 ;
297
41be4444
PM
298switch_body: /* EMPTY */ { $$ = NULL; }
299 | set_item ':' cmds switch_body {
300 $$ = $1;
301 $$->data = $3;
302 $$->left = $4;
303 }
304 | ELSE ':' cmds {
305 $$ = f_new_tree();
306 $$->from.type = T_VOID;
307 $$->to.type = T_VOID;
308 $$->data = $3;
309 }
310 ;
d3dd620b 311
e4a73dbf
PM
312/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */
313
77de6882
PM
314bgp_one:
315 NUM { $$ = $1; }
4b641bab 316 | '*' { $$ = PM_ANY; }
77de6882
PM
317 ;
318
319bgp_path:
dcab7890
PM
320 bgp_one { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = NULL; $$->val = $1; }
321 | bgp_one bgp_path { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->val = $1; }
77de6882
PM
322 ;
323
23b1539b 324constant:
e4a73dbf 325 NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; }
c7b43f33
PM
326 | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; }
327 | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; }
328 | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
329 | pair { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PAIR; $$->a2.i = $1; }
d3dd620b 330 | ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
2f702671 331 | prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
d4d75628 332 | '[' 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" ); }
c7b43f33 333 | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
dcab7890 334 | '/' bgp_path '/' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PATH_MASK; $$->a2.p = $2; }
23b1539b
PM
335 ;
336
db1326aa
MM
337/*
338 * Maybe there are no dynamic attributes defined by protocols.
339 * For such cases, we force the dynamic_attr list to contain
340 * at least an invalid token, so it's syntantically correct.
341 */
342CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; })
f4536657 343
2e18b87d 344rtadot: /* EMPTY, we are not permitted RTA. prefix */
6c14255d 345 ;
f4536657 346
2d496d20
PM
347function_call:
348 SYM '(' var_list ')' {
349 struct symbol *sym;
350 struct f_inst *inst = $3;
351 if ($1->class != SYM_FUNCTION)
352 cf_error("You can not call something which is not function. Really.");
d4d75628 353 DBG("You are calling function %s\n", $1->name);
2d496d20
PM
354 $$ = f_new_inst();
355 $$->code = P('c','a');
356 $$->a1.p = inst;
357 $$->a2.p = $1->aux2;
358 sym = (void *) $1->aux;
359 while (sym || inst) {
360 if (!sym || !inst)
361 cf_error("wrong number of arguments for function %s.", $1->name);
d4d75628 362 DBG( "You should pass parameter called %s\n", sym->name);
2d496d20
PM
363 inst->a1.p = sym;
364 sym = (void *) sym->aux;
365 inst = inst->next;
366 }
367 }
368 ;
369
84c7e194 370term:
f4536657 371 '(' term ')' { $$ = $2; }
d4d75628 372 | term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; }
2d496d20 373 | term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; }
d4d75628
PM
374 | term NEQ term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $3; }
375 | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; }
376 | term LEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $3; }
377 | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
378 | term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; }
379 | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
995e5894 380 | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
2d496d20 381 | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
23b1539b 382
1183b6b2 383 | constant { $$ = $1; }
2575593e
PM
384 | SYM {
385 $$ = f_new_inst();
386 switch ($1->class) {
ba921648 387 case SYM_VARIABLE | T_INT:
d3dd620b
PM
388 case SYM_VARIABLE | T_PAIR:
389 case SYM_VARIABLE | T_PREFIX:
390 case SYM_VARIABLE | T_IP:
dcab7890 391 case SYM_VARIABLE | T_PATH_MASK:
e399b6f6 392 case SYM_VARIABLE | T_PATH:
9c400ec9 393 case SYM_VARIABLE | T_CLIST:
d3dd620b
PM
394 $$->code = 'C';
395 $$->a1.p = $1->aux2;
2575593e
PM
396 break;
397 default:
1183b6b2 398 cf_error("Can not use this class of symbol (%s,%x) as variable.", $1->name, $1->class );
2575593e
PM
399 }
400 }
4515bdba 401
6c14255d 402 | rtadot FROM { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); }
36bbfc70 403
6c14255d
PM
404 | rtadot GW { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); }
405 | rtadot NET { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_PREFIX; $$->a2.i = 0x12345678; }
b1573615 406 | rtadot SOURCE { $$ = f_new_inst(); $$->code = 'a'; $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
6dc7a0cb 407
db1326aa 408 | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
36bbfc70 409
2d496d20 410 | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
684c6f5a 411 | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
2d496d20 412 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
7f77e250
PM
413
414/* Communities */
10a53608
PM
415/* This causes one shift/reduce conflict
416 | rtadot dynamic_attr '.' ADD '(' term ')' { }
417 | rtadot dynamic_attr '.' DELETE '(' term ')' { }
418 | rtadot dynamic_attr '.' CONTAINS '(' term ')' { }
a2d15746 419 | rtadot dynamic_attr '.' RESET{ }
10a53608 420*/
7f77e250
PM
421
422/* Paths */
e399b6f6 423 | term '.' PREPEND '(' term ')' { }
a2d15746 424 | term '.' RESET { }
afc54517 425
e399b6f6 426 | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; }
9c400ec9 427 | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; }
e399b6f6 428 | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; }
4444ed2b
PM
429 | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; }
430 | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
9c400ec9 431
afc54517 432
a2d15746 433/* | term '.' LEN { $$->code = P('P','l'); } */
7f77e250 434
995e5894
PM
435/* function_call is inlined here */
436 | SYM '(' var_list ')' {
437 struct symbol *sym;
438 struct f_inst *inst = $3;
439 if ($1->class != SYM_FUNCTION)
440 cf_error("You can not call something which is not function. Really.");
441 DBG("You are calling function %s\n", $1->name);
442 $$ = f_new_inst();
443 $$->code = P('c','a');
444 $$->a1.p = inst;
445 $$->a2.p = $1->aux2;
446 sym = (void *) $1->aux;
447 while (sym || inst) {
448 if (!sym || !inst)
449 cf_error("wrong number of arguments for function %s.", $1->name);
450 DBG( "You should pass parameter called %s\n", sym->name);
451 inst->a1.p = sym;
452 sym = (void *) sym->aux;
453 inst = inst->next;
454 }
455 }
ba921648
PM
456 ;
457
458break_command:
459 QUITBIRD { $$ = F_QUITBIRD }
460 | ACCEPT { $$ = F_ACCEPT }
461 | REJECT { $$ = F_REJECT }
462 | ERROR { $$ = F_ERROR }
23b1539b 463 | PRINT { $$ = F_NOP }
d3dd620b 464 | PRINTN { $$ = F_NONL }
ba921648
PM
465 ;
466
23b1539b 467print_one:
2db3b288 468 term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; }
23b1539b
PM
469 ;
470
471print_list: /* EMPTY */ { $$ = NULL; }
995e5894
PM
472 | print_one { $$ = $1; }
473 | print_one ',' print_list {
23b1539b 474 if ($1) {
995e5894 475 $1->next = $3;
23b1539b 476 $$ = $1;
995e5894 477 } else $$ = $3;
23b1539b 478 }
995e5894 479
23b1539b
PM
480 ;
481
6dc7a0cb 482var_listn: term {
d3dd620b
PM
483 $$ = f_new_inst();
484 $$->code = 's';
485 $$->a1.p = NULL;
486 $$->a2.p = $1;
487 $$->next = NULL;
488 }
6dc7a0cb 489 | term ',' var_listn {
6542ece9
PM
490 $$ = f_new_inst();
491 $$->code = 's';
492 $$->a1.p = NULL;
493 $$->a2.p = $1;
494 $$->next = $3;
495 }
496 ;
497
6dc7a0cb
PM
498var_list: /* EMPTY */ { $$ = NULL; }
499 | var_listn { $$ = $1; }
500 ;
501
23b1539b 502cmd:
49955645
MM
503 IF term THEN block {
504 $$ = f_new_inst();
505 $$->code = '?';
506 $$->a1.p = $2;
507 $$->a2.p = $4;
23b1539b 508 }
49955645
MM
509 | IF term THEN block ELSE block {
510 struct f_inst *i = f_new_inst();
511 i->code = '?';
512 i->a1.p = $2;
513 i->a2.p = $4;
23b1539b
PM
514 $$ = f_new_inst();
515 $$->code = '?';
49955645
MM
516 $$->a1.p = i;
517 $$->a2.p = $6;
23b1539b 518 }
ba921648 519 | SYM '=' term ';' {
84c7e194 520 $$ = f_new_inst();
d4d75628 521 DBG( "Ook, we'll set value\n" );
ba921648
PM
522 if (($1->class & ~T_MASK) != SYM_VARIABLE)
523 cf_error( "You may only set variables, and this is %x.\n", $1->class );
23b1539b 524 $$->code = 's';
2db3b288
PM
525 $$->a1.p = $1;
526 $$->a2.p = $3;
b9d70dc8 527 }
2d496d20
PM
528 | RETURN term ';' {
529 $$ = f_new_inst();
d4d75628 530 DBG( "Ook, we'll return the value\n" );
2d496d20
PM
531 $$->code = 'r';
532 $$->a1.p = $2;
533 }
db1326aa 534 | rtadot dynamic_attr '=' term ';' {
6c14255d 535 $$ = $2;
2d496d20 536 $$->code = P('e','S');
6c14255d 537 $$->a1.p = $4;
f31156ca 538 }
db1326aa 539 | UNSET '(' rtadot dynamic_attr ')' ';' {
6c14255d 540 $$ = $4;
9f4929e7 541 $$->aux = EAF_TYPE_UNDEF | EAF_TEMP;
2d496d20 542 $$->code = P('e','S');
48f9e019 543 $$->a1.p = NULL;
c7b43f33 544 }
2d496d20
PM
545 | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; }
546 | function_call ';' { $$ = $1; }
7db7b7db
PM
547 | CASE term '{' switch_body '}' {
548 $$ = f_new_inst();
2d496d20 549 $$->code = P('S','W');
7db7b7db 550 $$->a1.p = $2;
41be4444 551 $$->a2.p = build_tree( $4 );
7db7b7db 552 }
b9d70dc8
PM
553 ;
554
555CF_END