modules/up/src/rpsl/rpsl/rpsl.y
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- yyparse
- enable_yy_parser_debugging
- handleArgumentTypeError
- searchMethod
1 %{
2 // $Id: rpsl.y,v 1.8 2001/06/07 08:23:05 engin Exp $
3 //
4 // Copyright (c) 1994 by the University of Southern California
5 // All rights reserved.
6 //
7 // Permission to use, copy, modify, and distribute this software and its
8 // documentation in source and binary forms for lawful non-commercial
9 // purposes and without fee is hereby granted, provided that the above
10 // copyright notice appear in all copies and that both the copyright
11 // notice and this permission notice appear in supporting documentation,
12 // and that any documentation, advertising materials, and other materials
13 // related to such distribution and use acknowledge that the software was
14 // developed by the University of Southern California, Information
15 // Sciences Institute. The name of the USC may not be used to endorse or
16 // promote products derived from this software without specific prior
17 // written permission.
18 //
19 // THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
20 // REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
21 // PURPOSE. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
22 // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
23 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
24 // TITLE, AND NON-INFRINGEMENT.
25 //
26 // IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
27 // SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
28 // OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
29 // OR PERFORMANCE OF THIS SOFTWARE.
30 //
31 // Questions concerning this software should be directed to
32 // ratoolset@isi.edu.
33 //
34 // Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
35
36 #include "config.h"
37 #include "time.h"
38 #include "schema.hh"
39 #include "object.hh"
40 #include "regexp.hh"
41 #include "rptype.hh"
42
43 #ifdef DEBUG
44 #define YYDEBUG 1
45 #endif // DEBUG
46 #if YYDEBUG != 0
47 // stdio is needed for yydebug
48 #include <cstdio>
49 #endif
50
51 extern void handle_error(char *, ...);
52 extern void handle_object_error(char *, ...);
53 extern void handle_warning(char *, ...);
54 extern int yylex();
55 char *token_name(int token_id);
56 void rpslerror(char *s, ...);
57 Attr *changeCurrentAttr(Attr *b);
58 void handleArgumentTypeError(char *attr, char *method, int position,
59 const RPType *correctType,
60 bool isOperator = false);
61 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, char *method, ItemList *args);
62
63 /* argument to yyparse result of parsing should be stored here */
64 #define YYPARSE_PARAM object
65 #define yyschema schema
66 #define enable_yy_parser_debugging enable_rpsl_parser_debugging
67
68 extern Object *current_object;
69
70 %}
71
72 %expect 1
73
74 %union {
75 long long int i;
76 double real;
77 char *string;
78 void *ptr;
79 time_t time;
80 Item *item;
81 ItemList *list;
82 regexp *re;
83 SymID sid;
84 IPAddr *ip;
85 Prefix *prfx;
86 PrefixRange *prfxrng;
87 RPType *typenode;
88
89 Filter *filter;
90 FilterMS *moreSpecOp;
91 PolicyPeering *peering;
92 PolicyActionList *actionList;
93 PolicyAction *actionNode;
94 PolicyFactor *policyFactor;
95 PolicyTerm *policyTerm;
96 PolicyExpr *policyExpr;
97 List<PolicyPeeringAction> *peeringActionList;
98
99 Attr *attr;
100 AttrAttr *rpslattr;
101 AttrMethod *method;
102 const AttrRPAttr *rp_attr;
103 const AttrProtocol *protocol;
104 AttrProtocolOption *protocol_option;
105 List<AttrProtocolOption> *protocol_option_list;
106
107 AttrPeerOption *peer_option;
108 List<AttrPeerOption> *peer_option_list;
109
110 List<RPTypeNode> *typelist;
111 List<AttrMethod> *methodlist;
112 List<WordNode> *wordlist;
113
114 List<AttrMntRoutes::MntPrfxPair> *listMntPrfxPair;
115 AttrMntRoutes::MntPrfxPair *mntPrfxPair;
116 }
117
118 %token KEYW_TRUE
119 %token KEYW_FALSE
120 %token KEYW_ACTION
121 %token KEYW_ACCEPT
122 %token KEYW_ANNOUNCE
123 %token KEYW_FROM
124 %token KEYW_TO
125 %token KEYW_AT
126 %token KEYW_ANY
127 %token KEYW_REFINE
128 %token KEYW_EXCEPT
129 %token KEYW_STATIC
130 %token KEYW_NETWORKS
131 %token KEYW_MASKLEN
132 %token KEYW_UNION
133 %token KEYW_RANGE
134 %token KEYW_LIST
135 %token KEYW_OF
136 %token KEYW_OPERATOR
137 %token KEYW_SYNTAX
138 %token KEYW_SPECIAL
139 %token KEYW_OPTIONAL
140 %token KEYW_MANDATORY
141 %token KEYW_INTERNAL
142 %token KEYW_SINGLEVALUED
143 %token KEYW_MULTIVALUED
144 %token KEYW_LOOKUP
145 %token KEYW_KEY
146 %token KEYW_DELETED
147 %token KEYW_GENERATED
148 %token KEYW_OBSOLETE
149 %token KEYW_PEERAS
150 %token KEYW_PROTOCOL
151 %token KEYW_INTO
152 %token KEYW_ATOMIC
153 %token KEYW_INBOUND
154 %token KEYW_OUTBOUND
155 %token KEYW_UPON
156 %token KEYW_HAVE_COMPONENTS
157 %token KEYW_EXCLUDE
158
159 %token KEYW_NONE
160 %token KEYW_MAILFROM
161 %token KEYW_CRYPTPW
162 %token KEYW_ASSIGNED
163 %token KEYW_ALLOCATED
164 %token KEYW_PI
165 %token KEYW_PA
166 %token KEYW_UNSPECIFIED
167 %token KEYW_EXT
168 %token KEYW_SIMPLE
169 %token KEYW_RIPE
170 %token KEYW_INTERNIC
171 %token KEYW_CLIENTADDRESS
172
173
174 %token TKN_ERROR
175 %token TKN_UNKNOWN_CLASS
176 %token TKN_EOA /* end of attribute */
177 %token TKN_EOO /* end of object */
178 %token TKN_FREETEXT
179 %token <i> TKN_INT
180 %token <real> TKN_REAL
181 %token <string> TKN_STRING
182 %token <time> TKN_TIMESTAMP
183 %token <string> TKN_BLOB
184 %token <ip> TKN_IPV4
185 %token <string> TKN_PRFXV6
186 %token <prfx> TKN_PRFXV4
187 %token <prfxrng> TKN_PRFXV4RNG
188 %token <i> TKN_ASNO
189 %token <sid> TKN_ASNAME
190 %token <sid> TKN_RSNAME
191 %token <sid> TKN_RTRSNAME
192 %token <sid> TKN_PRNGNAME
193 %token <sid> TKN_FLTRNAME
194 %token <i> TKN_BOOLEAN
195 %token <string> TKN_WORD
196 %token <rp_attr> TKN_RP_ATTR
197 %token <sid> TKN_DNS
198 %token <string> TKN_EMAIL
199 %token TKN_3DOTS
200
201 %token <string> TKN_NICHDL
202 %token <string> TKN_KEYCRTNAME
203 %token <string> TKN_CRYPTEDPW
204
205 %token <attr> ATTR_GENERIC
206 %token <attr> ATTR_BLOBS
207 %token <attr> ATTR_IMPORT
208 %token <attr> ATTR_EXPORT
209 %token <attr> ATTR_DEFAULT
210 %token <attr> ATTR_FREETEXT
211 %token <attr> ATTR_CHANGED
212 %token <attr> ATTR_IFADDR
213 %token <attr> ATTR_PEER
214 %token <attr> ATTR_INJECT
215 %token <attr> ATTR_COMPONENTS
216 %token <attr> ATTR_AGGR_MTD
217 %token <attr> ATTR_AGGR_BNDRY
218 %token <attr> ATTR_RS_MEMBERS
219 %token <attr> ATTR_RP_ATTR
220 %token <attr> ATTR_TYPEDEF
221 %token <attr> ATTR_PROTOCOL
222 %token <attr> ATTR_FILTER
223 %token <attr> ATTR_PEERING
224 %token <attr> ATTR_ATTR
225 %token <attr> ATTR_MNT_ROUTES
226
227 %token <attr> ATTR_NICHDL
228 %token <attr> ATTR_AUTH
229 %token <attr> ATTR_STATUS_INET
230 %token <attr> ATTR_PHONE
231 %token <attr> ATTR_SOURCE
232 %token <attr> ATTR_REFER
233 %token <attr> ATTR_COUNTRY
234 %token <attr> ATTR_PERSON
235
236 %left OP_OR
237 %left OP_AND
238 %right OP_NOT
239 %nonassoc<moreSpecOp> OP_MS
240 %nonassoc<string> TKN_OPERATOR
241
242 %type<list> generic_list
243 %type<list> rs_members_list
244 %type<list> opt_rs_members_list
245 %type<list> blobs_list
246 %type<list> generic_non_empty_list
247 %type<item> list_item
248 %type<item> list_item_0
249 %type<item> rs_member
250
251 %type<string> tkn_word
252 %type<string> tkn_word_from_keyw
253
254 %type<string> tkn_word_from_keyw_none
255 %type<string> tkn_word_from_keyw_mailfrom
256 %type<string> tkn_word_from_keyw_cryptpw
257 %type<string> tkn_word_from_keyw_assigned
258 %type<string> tkn_word_from_keyw_allocated
259 %type<string> tkn_word_from_keyw_pi
260 %type<string> tkn_word_from_keyw_pa
261 %type<string> tkn_word_from_keyw_unspecified
262 %type<string> tkn_word_from_keyw_ext
263 %type<string> tkn_word_from_keyw_simple
264 %type<string> tkn_word_from_keyw_ripe
265 %type<string> tkn_word_from_keyw_internic
266 %type<string> tkn_word_from_keyw_clientaddress
267
268 %type<attr> attribute
269 %type<attr> generic_attribute
270 %type<attr> blobs_attribute
271 %type<attr> changed_attribute
272 %type<attr> ifaddr_attribute
273 %type<attr> peer_attribute
274 %type<attr> components_attribute
275 %type<attr> inject_attribute
276 %type<attr> aggr_mtd_attribute
277 %type<attr> aggr_bndry_attribute
278
279 %type<attr> import_attribute
280 %type<attr> export_attribute
281 %type<attr> default_attribute
282 %type<attr> typedef_attribute
283 %type<attr> rpattr_attribute
284 %type<attr> rs_members_attribute
285 %type<attr> protocol_attribute
286 %type<attr> filter_attribute
287 %type<attr> peering_attribute
288 %type<attr> attr_attribute
289 %type<attr> freetext_attribute
290 %type<attr> mnt_routes_attribute
291
292 %type<attr> nichdl_attribute
293 %type<attr> auth_attribute
294 %type<attr> status_inet_attribute
295 %type<attr> phone_attribute
296 %type<attr> source_attribute
297 %type<attr> refer_attribute
298 %type<attr> country_attribute
299 %type<attr> person_attribute
300
301 %type<filter> filter
302 %type<filter> opt_default_filter
303 %type<filter> filter_term
304 %type<filter> filter_factor
305 %type<filter> filter_operand
306 %type<filter> filter_prefix
307 %type<filter> filter_prefix_operand
308 %type<filter> opt_filter_prefix_list
309 %type<filter> filter_prefix_list
310 %type<prfxrng> filter_prefix_list_prefix
311 %type<filter> filter_rp_attribute
312
313 %type<filter> opt_as_expr
314 %type<filter> as_expr
315 %type<filter> as_expr_term
316 %type<filter> as_expr_factor
317 %type<filter> as_expr_operand
318
319 %type<filter> opt_router_expr
320 %type<filter> opt_router_expr_with_at
321 %type<filter> router_expr
322 %type<filter> router_expr_term
323 %type<filter> router_expr_factor
324 %type<filter> router_expr_operand
325
326 %type<filter> opt_inject_expr
327 %type<filter> inject_expr
328 %type<filter> inject_expr_term
329 %type<filter> inject_expr_factor
330 %type<filter> inject_expr_operand
331
332 %type<re> filter_aspath
333 %type<re> filter_aspath_term
334 %type<re> filter_aspath_closure
335 %type<re> filter_aspath_factor
336 %type<re> filter_aspath_no
337 %type<re> filter_aspath_range
338
339 %type<actionList> action
340 %type<actionList> opt_action
341 %type<actionNode> single_action
342
343 %type<peering> peering
344
345 %type<peeringActionList> import_peering_action_list
346 %type<peeringActionList> export_peering_action_list
347 %type<policyFactor> import_factor
348 %type<policyTerm> import_factor_list
349 %type<policyTerm> import_term
350 %type<policyExpr> import_expr
351 %type<policyFactor> export_factor
352 %type<policyTerm> export_factor_list
353 %type<policyTerm> export_term
354 %type<policyExpr> export_expr
355 %type<protocol> opt_protocol_from
356 %type<protocol> opt_protocol_into
357
358 %type<wordlist> enum_list
359 %type<typenode> typedef_type
360 %type<typelist> typedef_type_list
361
362 %type<method> method
363 %type<methodlist> methods
364
365 %type<protocol_option> protocol_option
366 %type<protocol_option_list> protocol_options
367
368 %type<peer_option> peer_option
369 %type<peer_option_list> peer_options
370 %type<peer_option_list> opt_peer_options
371 %type<ip> peer_id
372
373 %type<rpslattr> opt_attr_options
374 %type<rpslattr> attr_options
375 %type<rpslattr> attr_option
376
377 %type<listMntPrfxPair> mnt_routes_list
378 %type<mntPrfxPair> mnt_routes_list_item
379
380 %type<string> int_list
381 %type<string> name_list
382
383 %%
/* [<][>][^][v][top][bottom][index][help] */
384 object: attribute_list TKN_EOO {
385 YYACCEPT;
386 }
387 | TKN_UNKNOWN_CLASS TKN_EOO {
388 YYACCEPT;
389 }
390 | error TKN_EOO {
391 handle_object_error("Error: syntax error\n");
392 YYABORT;
393 }
394 | attribute_list { // end of file
395 YYACCEPT;
396 }
397 | TKN_UNKNOWN_CLASS { // end of file
398 YYACCEPT;
399 }
400 | error { // end of file
401 handle_object_error("Error: syntax error\n");
402 YYABORT;
403 }
404 | { // end of file
405 YYABORT;
406 }
407 ;
408
409 attribute_list: attribute {
410 (*current_object) += $1;
411 }
412 | attribute_list attribute {
413 (*current_object) += $2;
414 }
415 ;
416
417 attribute: generic_attribute
418 | blobs_attribute
419 | changed_attribute
420 | import_attribute
421 | export_attribute
422 | default_attribute
423 | peer_attribute
424 | ifaddr_attribute
425 | components_attribute
426 | inject_attribute
427 | aggr_mtd_attribute
428 | aggr_bndry_attribute
429 | typedef_attribute
430 | protocol_attribute
431 | rpattr_attribute
432 | rs_members_attribute
433 | filter_attribute
434 | peering_attribute
435 | attr_attribute
436 | freetext_attribute
437 | mnt_routes_attribute
438 | nichdl_attribute
439 | auth_attribute
440 | status_inet_attribute
441 | phone_attribute
442 | source_attribute
443 | refer_attribute
444 | country_attribute
445 | person_attribute
446 | TKN_ERROR TKN_EOA { // the current line started w/ non-attribute
447 $$ = changeCurrentAttr(new Attr);
448 handle_error("Error: syntax error\n");
449 }
450 | error TKN_EOA {
451 $$ = changeCurrentAttr(new Attr);
452 handle_error("Error: syntax error\n");
453 yyerrok;
454 }
455 ;
456
457 //**** Generic Attributes ************************************************
458
459 changed_attribute: ATTR_CHANGED TKN_EMAIL TKN_INT TKN_EOA {
460 free($2);
461 $$ = $1;
462 }
463 | ATTR_CHANGED TKN_EMAIL TKN_EOA {
464 free($2);
465 $$ = $1;
466 }
467 | ATTR_CHANGED error TKN_EOA {
468 handle_error("Error: \"changed: <email> <YYYYMMDD>\" expected\n");
469 yyerrok;
470 }
471 ;
472
473
474 nichdl_attribute: ATTR_NICHDL TKN_NICHDL TKN_EOA {
475 if(yyschema.validNICHandle($2)){
476 free($2);
477 $$ = $1;
478 }else{
479 free($2);
480 handle_error("Error: Invalid NIC handle\n");
481 yyerrok;
482 }
483 }
484 | ATTR_NICHDL error TKN_EOA {
485 handle_error("Error: \"%s: <nic-handle>\" expected\n",$1->type->name());
486 yyerrok;
487 }
488
489 auth_attribute: ATTR_AUTH tkn_word_from_keyw_none TKN_EOA {
490 $$ = $1;
491 }
492 | ATTR_AUTH tkn_word_from_keyw_mailfrom TKN_EMAIL TKN_EOA {
493 free($3);
494 $$ = $1;
495 }
496 | ATTR_AUTH tkn_word_from_keyw_cryptpw TKN_CRYPTEDPW TKN_EOA {
497 free($3);
498 $$ = $1;
499 }
500 | ATTR_AUTH TKN_KEYCRTNAME TKN_EOA {
501 free($2);
502 $$ = $1;
503 }
504 | ATTR_AUTH error TKN_EOA {
505 handle_error("Error: \"auth: MAIL-FROM <regexp>\""
506 ", \"auth: NONE\", \"auth: CRYPT-PW <cryptedpaswd>\""
507 " or \"auth: PGPKEY-<pgpid>\" expected\n");
508 yyerrok;
509
510 }
511 ;
512
513
514
515 status_inet_attribute: ATTR_STATUS_INET tkn_word_from_keyw_assigned tkn_word_from_keyw_pi TKN_EOA {
516 $$ = $1;
517 }
518 | ATTR_STATUS_INET tkn_word_from_keyw_assigned tkn_word_from_keyw_pa TKN_EOA {
519 $$ = $1;
520 }
521 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_pi TKN_EOA {
522 $$ = $1;
523 }
524 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_pa TKN_EOA {
525 $$ = $1;
526 }
527 | ATTR_STATUS_INET tkn_word_from_keyw_allocated tkn_word_from_keyw_unspecified TKN_EOA {
528 $$ = $1;
529 }
530 | ATTR_STATUS_INET error TKN_EOA {
531 handle_error("Error: \"status\" attribute contains invalid keywords\n");
532 yyerrok;
533 }
534 ;
535
536 phone_attribute: ATTR_PHONE '+' int_list TKN_EOA {
537 $$ = $1;
538 }
539 | ATTR_PHONE '+' int_list '(' int_list ')' int_list TKN_EOA {
540 $$ = $1;
541 }
542 | ATTR_PHONE '+' int_list tkn_word_from_keyw_ext '.' int_list TKN_EOA {
543 $$ = $1;
544 }
545 | ATTR_PHONE '+' int_list '(' int_list ')' int_list tkn_word_from_keyw_ext '.' int_list TKN_EOA {
546 $$ = $1;
547 }
548 | ATTR_PHONE error TKN_EOA {
549 handle_error("Error: intn'l phone number expected (with a preceding '+')\n");
550 yyerrok;
551 }
552
553
554 int_list: TKN_INT {
555 //sprintf($$, "%i", $1);
556 $$ = strdup("phone"); // well, sprintf($$, "%i", $1) didn't work
557 }
558 | int_list TKN_INT{
559 $$ = $1;
560 }
561 | int_list '-' TKN_INT{
562 $$ = $1;
563 }
564 | int_list '.' TKN_INT{
565 $$ = $1;
566 }
567
568
569 source_attribute: ATTR_SOURCE tkn_word TKN_EOA {
570 if(yyschema.searchSource($2)){
571 free($2);
572 $$ = $1;
573 }else{
574 free($2);
575 handle_error("Error: No such source\n");
576 }
577 }
578 | ATTR_SOURCE error TKN_EOA {
579 handle_error("Error: invalid source attribute\n");
580 yyerrok;
581 }
582
583 refer_attribute: ATTR_REFER tkn_word_from_keyw_simple TKN_DNS TKN_EOA {
584 $$ = $1;
585 }
586 | ATTR_REFER tkn_word_from_keyw_simple TKN_DNS TKN_INT TKN_EOA {
587 $$ = $1;
588 }
589 | ATTR_REFER tkn_word_from_keyw_ripe TKN_DNS TKN_EOA {
590 $$ = $1;
591 }
592 | ATTR_REFER tkn_word_from_keyw_ripe TKN_DNS TKN_INT TKN_EOA {
593 $$ = $1;
594 }
595 | ATTR_REFER tkn_word_from_keyw_internic TKN_DNS TKN_EOA {
596 $$ = $1;
597 }
598 | ATTR_REFER tkn_word_from_keyw_internic TKN_DNS TKN_INT TKN_EOA {
599 $$ = $1;
600 }
601 | ATTR_REFER tkn_word_from_keyw_clientaddress TKN_DNS TKN_EOA {
602 $$ = $1;
603 }
604 | ATTR_REFER tkn_word_from_keyw_clientaddress TKN_DNS TKN_INT TKN_EOA {
605 $$ = $1;
606 }
607 | ATTR_REFER error TKN_EOA {
608 handle_error("Error: invalid refer attribute\n");
609 yyerrok;
610 }
611
612 country_attribute: ATTR_COUNTRY tkn_word TKN_EOA {
613 if(yyschema.searchCountry($2)){
614 free($2);
615 $$ = $1;
616 }else{
617 free($2);
618 handle_error("Error: No such country\n");
619 }
620 }
621 | ATTR_COUNTRY error TKN_EOA {
622 handle_error("Error: invalid country attribute\n");
623 yyerrok;
624 }
625
626 person_attribute: ATTR_PERSON tkn_word name_list TKN_EOA {
627 $$ = $1;
628 }
629 | ATTR_PERSON error TKN_EOA {
630 handle_error("Error: invalid %s attribute\n",$1->type->name());
631 yyerrok;
632 }
633
634 name_list: tkn_word {
635 $$ = strdup($1);
636 }
637 | '.' tkn_word {
638 $$ = strdup($2);
639 }
640 | '`' tkn_word {
641 $$ = strdup($2);
642 }
643 | '\'' tkn_word {
644 $$ = strdup($2);
645 }
646 | name_list tkn_word {
647 $$ = strdup($2);
648 }
649 | name_list '.' {
650 $$ = strdup($1);
651 }
652 | name_list '`' {
653 $$ = strdup($1);
654 }
655 | name_list '\'' {
656 $$ = strdup($1);
657 }
658
659
660
661
662 freetext_attribute: ATTR_FREETEXT TKN_EOA {
663 char *start = strchr($1->object->contents + $1->offset, ':') + 1;
664 int len = $1->object->contents + $1->offset + $1->len - start;
665 ItemFREETEXT *ft = new ItemFREETEXT(start, len);
666 ItemList *il = new ItemList;
667 il->append(ft);
668
669 $$ = changeCurrentAttr(new AttrGeneric($1->type, il));
670 }
671 ;
672
673 generic_attribute: ATTR_GENERIC generic_list TKN_EOA {
674 if (!$1->type->subsyntax()->validate($2)) {
675 handle_error("Error: argument to %s should be %s.\n",
676 $1->type->name(), $1->type->subsyntax()->name());
677 delete $2;
678 $$ = changeCurrentAttr(new AttrGeneric($1->type, NULL));
679 } else
680 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
681 }
682 | ATTR_GENERIC error TKN_EOA {
683 $$ = $1;
684 handle_error("Error: argument to %s should be %s.\n",
685 $1->type->name(), $1->type->subsyntax()->name());
686 yyerrok;
687 }
688 ;
689
690 generic_list: /* empty list */ {
691 $$ = new ItemList;
692 }
693 | generic_non_empty_list
694 ;
695
696 generic_non_empty_list: list_item {
697 $$ = new ItemList;
698 $$->append($1);
699 }
700 | generic_non_empty_list ',' list_item {
701 $$ = $1;
702 $$->append($3);
703 }
704 ;
705
706 blobs_attribute: ATTR_BLOBS blobs_list TKN_EOA {
707 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
708 }
709 | ATTR_BLOBS error TKN_EOA {
710 $$ = $1;
711 handle_error("Error: argument to %s should be blob sequence.\n",
712 $1->type->name());
713 yyerrok;
714 }
715 ;
716
717 blobs_list: list_item {
718 $$ = new ItemList;
719 $$->append($1);
720 }
721 | blobs_list list_item {
722 $$ = $1;
723 $$->append($2);
724 }
725 ;
726
727 list_item: list_item_0 {
728 $$ = $1;
729 }
730 | list_item_0 '-' list_item_0 {
731 $$ = new ItemRange($1, $3);
732 }
733 ;
734
735 list_item_0: TKN_ASNO {
736 $$ = new ItemASNO($1);
737 }
738 | TKN_INT {
739 $$ = new ItemINT($1);
740 }
741 | TKN_REAL {
742 $$ = new ItemREAL($1);
743 }
744 | TKN_STRING {
745 $$ = new ItemSTRING($1);
746 }
747 | TKN_TIMESTAMP {
748 $$ = new ItemTimeStamp($1);
749 }
750 | TKN_IPV4 {
751 $$ = new ItemIPV4($1);
752 }
753 | TKN_PRFXV4 {
754 $$ = new ItemPRFXV4($1);
755 }
756 | TKN_PRFXV6 {
757 $$ = new ItemPRFXV6($1);
758 }
759 | TKN_PRFXV4RNG {
760 $$ = new ItemPRFXV4Range($1);
761 }
762 | TKN_IPV4 ':' TKN_INT {
763 $$ = new ItemConnection($1, $3);
764 }
765 | TKN_IPV4 ':' TKN_INT ':' TKN_INT {
766 $$ = new ItemConnection($1, $3, $5);
767 }
768 | TKN_DNS ':' TKN_INT {
769 $$ = new ItemConnection($1, $3);
770 }
771 | TKN_DNS ':' TKN_INT ':' TKN_INT {
772 $$ = new ItemConnection($1, $3, $5);
773 }
774 | TKN_ASNAME {
775 $$ = new ItemASNAME($1);
776 }
777 | TKN_RSNAME {
778 $$ = new ItemRSNAME($1);
779 }
780 | TKN_RTRSNAME {
781 $$ = new ItemRTRSNAME($1);
782 }
783 | TKN_PRNGNAME {
784 $$ = new ItemPRNGNAME($1);
785 }
786 | TKN_FLTRNAME {
787 $$ = new ItemFLTRNAME($1);
788 }
789 | TKN_BOOLEAN {
790 $$ = new ItemBOOLEAN($1);
791 }
792 | TKN_WORD {
793 $$ = new ItemWORD($1);
794 }
795 | tkn_word_from_keyw {
796 $$ = new ItemWORD($1);
797 }
798 | TKN_DNS {
799 $$ = new ItemDNS($1);
800 }
801 | TKN_EMAIL {
802 $$ = new ItemEMAIL($1);
803 }
804 | TKN_KEYCRTNAME {
805 $$ = new ItemKEYCRTNAME($1);
806 }
807 | TKN_BLOB {
808 $$ = new ItemBLOB($1);
809 }
810 | '{' generic_list '}' {
811 $$ = $2;
812 }
813 | '(' filter ')' {
814 $$ = new ItemFilter($2);
815 }
816 ;
817
818 tkn_word: TKN_WORD {
819 $$ = $1;
820 }
821 | TKN_ASNO {
822 char buffer[64];
823 sprintf(buffer, "AS%d", $1);
824 $$ = strdup(buffer);
825 }
826 | TKN_ASNAME {
827 $$ = strdup($1);
828 }
829 | TKN_RSNAME {
830 $$ = strdup($1);
831 }
832 | TKN_RTRSNAME {
833 $$ = strdup($1);
834 }
835 | TKN_PRNGNAME {
836 $$ = strdup($1);
837 }
838 | TKN_FLTRNAME {
839 $$ = strdup($1);
840 }
841 | TKN_NICHDL {
842 $$ = strdup($1);
843 }
844 | TKN_BOOLEAN {
845 if ($1)
846 $$ = strdup("true");
847 else
848 $$ = strdup("false");
849 }
850 | tkn_word_from_keyw
851 | tkn_word_from_keyw_ripe
852 | tkn_word_from_keyw_internic
853 | tkn_word_from_keyw_simple
854 | tkn_word_from_keyw_clientaddress
855 ;
856
857 tkn_word_from_keyw: KEYW_TRUE {
858 $$ = strdup("true");
859 }
860 | KEYW_FALSE {
861 $$ = strdup("false");
862 }
863 | KEYW_ACTION {
864 $$ = strdup("action");
865 }
866 | KEYW_ACCEPT {
867 $$ = strdup("accept");
868 }
869 | KEYW_ANNOUNCE {
870 $$ = strdup("announce");
871 }
872 | KEYW_FROM {
873 $$ = strdup("from");
874 }
875 | KEYW_TO {
876 $$ = strdup("to");
877 }
878 | KEYW_AT {
879 $$ = strdup("at");
880 }
881 | KEYW_ANY {
882 $$ = strdup("any");
883 }
884 | KEYW_REFINE {
885 $$ = strdup("refine");
886 }
887 | KEYW_EXCEPT {
888 $$ = strdup("except");
889 }
890 | KEYW_STATIC {
891 $$ = strdup("static");
892 }
893 | KEYW_NETWORKS {
894 $$ = strdup("networks");
895 }
896 | KEYW_MASKLEN {
897 $$ = strdup("masklen");
898 }
899 | KEYW_UNION {
900 $$ = strdup("union");
901 }
902 | KEYW_RANGE {
903 $$ = strdup("range");
904 }
905 | KEYW_LIST {
906 $$ = strdup("list");
907 }
908 | KEYW_OF {
909 $$ = strdup("of");
910 }
911 | KEYW_OPERATOR {
912 $$ = strdup("operator");
913 }
914 | KEYW_SYNTAX {
915 $$ = strdup("syntax");
916 }
917 | KEYW_SPECIAL {
918 $$ = strdup("special");
919 }
920 | KEYW_OPTIONAL {
921 $$ = strdup("optional");
922 }
923 | KEYW_MANDATORY {
924 $$ = strdup("mandatory");
925 }
926 | KEYW_INTERNAL {
927 $$ = strdup("internal");
928 }
929 | KEYW_DELETED {
930 $$ = strdup("deleted");
931 }
932 | KEYW_SINGLEVALUED {
933 $$ = strdup("singlevalued");
934 }
935 | KEYW_GENERATED {
936 $$ = strdup("generated");
937 }
938 | KEYW_MULTIVALUED {
939 $$ = strdup("multivalued");
940 }
941 | KEYW_LOOKUP {
942 $$ = strdup("lookup");
943 }
944 | KEYW_KEY {
945 $$ = strdup("key");
946 }
947 | KEYW_OBSOLETE {
948 $$ = strdup("obsolete");
949 }
950 | KEYW_PEERAS {
951 $$ = strdup("peeras");
952 }
953 | KEYW_PROTOCOL {
954 $$ = strdup("protocol");
955 }
956 | KEYW_INTO {
957 $$ = strdup("into");
958 }
959 | KEYW_ATOMIC {
960 $$ = strdup("atomic");
961 }
962 | KEYW_INBOUND {
963 $$ = strdup("inbound");
964 }
965 | KEYW_OUTBOUND {
966 $$ = strdup("outbound");
967 }
968 ;
969
970 tkn_word_from_keyw_none: KEYW_NONE {
971 $$ = strdup("none");
972 }
973
974 tkn_word_from_keyw_mailfrom: KEYW_MAILFROM {
975 $$ = strdup("mail-from");
976 }
977
978 tkn_word_from_keyw_cryptpw: KEYW_CRYPTPW {
979 $$ = strdup("crypt-pw");
980 }
981
982 tkn_word_from_keyw_assigned: KEYW_ASSIGNED {
983 $$ = strdup("assigned");
984 }
985
986 tkn_word_from_keyw_allocated: KEYW_ALLOCATED {
987 $$ = strdup("allocated");
988 }
989
990 tkn_word_from_keyw_pi: KEYW_PI {
991 $$ = strdup("pi");
992 }
993
994 tkn_word_from_keyw_pa: KEYW_PA {
995 $$ = strdup("pa");
996 }
997
998 tkn_word_from_keyw_unspecified: KEYW_UNSPECIFIED {
999 $$ = strdup("unspecified");
1000 }
1001
1002 tkn_word_from_keyw_ext: KEYW_EXT {
1003 $$ = strdup("ext");
1004 }
1005
1006 tkn_word_from_keyw_simple: KEYW_SIMPLE {
1007 $$ = strdup("simple");
1008 }
1009
1010 tkn_word_from_keyw_ripe: KEYW_RIPE {
1011 $$ = strdup("ripe");
1012 }
1013
1014 tkn_word_from_keyw_internic: KEYW_INTERNIC {
1015 $$ = strdup("internic");
1016 }
1017
1018 tkn_word_from_keyw_clientaddress: KEYW_CLIENTADDRESS {
1019 $$ = strdup("clientaddress");
1020 }
1021
1022
1023 //**** aut-num class ******************************************************
1024
1025 //// as_expr ////////////////////////////////////////////////////////////
1026
1027 opt_as_expr: {
1028 $$ = new FilterASNAME(symbols.symID("AS-ANY"));
1029 }
1030 | as_expr
1031 ;
1032
1033 as_expr: as_expr OP_OR as_expr_term {
1034 $$ = new FilterOR($1, $3);
1035 }
1036 | as_expr_term
1037 ;
1038
1039 as_expr_term: as_expr_term OP_AND as_expr_factor {
1040 $$ = new FilterAND($1, $3);
1041 }
1042 | as_expr_term KEYW_EXCEPT as_expr_factor {
1043 $$ = new FilterEXCEPT($1, $3);
1044 }
1045 | as_expr_factor
1046 ;
1047
1048 as_expr_factor: '(' as_expr ')' {
1049 $$ = $2;
1050 }
1051 | as_expr_operand
1052 ;
1053
1054 as_expr_operand: TKN_ASNO {
1055 $$ = new FilterASNO($1);
1056 }
1057 | TKN_ASNAME {
1058 $$ = new FilterASNAME($1);
1059 }
1060 ;
1061
1062 //// router_expr ///////////////////////////////////////////////////////////
1063
1064 opt_router_expr: {
1065 $$ = new FilterANY;
1066 }
1067 | router_expr {
1068 $$ = $1;
1069 }
1070 ;
1071
1072 opt_router_expr_with_at: {
1073 $$ = new FilterANY;
1074 }
1075 | KEYW_AT router_expr {
1076 $$ = $2;
1077 }
1078 ;
1079
1080 router_expr: router_expr OP_OR router_expr_term {
1081 $$ = new FilterOR($1, $3);
1082 }
1083 | router_expr_term
1084 ;
1085
1086 router_expr_term: router_expr_term OP_AND router_expr_factor {
1087 $$ = new FilterAND($1, $3);
1088 }
1089 | router_expr_term KEYW_EXCEPT router_expr_factor {
1090 $$ = new FilterEXCEPT($1, $3);
1091 }
1092 | router_expr_factor
1093 ;
1094
1095 router_expr_factor: '(' router_expr ')' {
1096 $$ = $2;
1097 }
1098 | router_expr_operand
1099 ;
1100
1101 router_expr_operand: TKN_IPV4 {
1102 $$ = new FilterRouter($1);
1103 }
1104 | TKN_DNS {
1105 $$ = new FilterRouterName($1);
1106 }
1107 | TKN_RTRSNAME {
1108 $$ = new FilterRTRSNAME($1);
1109 }
1110 ;
1111
1112 //// peering ////////////////////////////////////////////////////////////
1113
1114 peering: as_expr opt_router_expr opt_router_expr_with_at {
1115 $$ = new PolicyPeering($1, $2, $3);
1116 }
1117 | TKN_PRNGNAME {
1118 $$ = new PolicyPeering($1);
1119 }
1120 ;
1121
1122 //// action /////////////////////////////////////////////////////////////
1123
1124 opt_action: {
1125 $$ = new PolicyActionList;
1126 }
1127 | KEYW_ACTION action {
1128 $$ = $2;
1129 }
1130 ;
1131
1132 action: single_action {
1133 $$ = new PolicyActionList;
1134 if ($1)
1135 $$->append($1);
1136 }
1137 | action single_action {
1138 $$ = $1;
1139 if ($2)
1140 $$->append($2);
1141 }
1142 ;
1143
1144 single_action: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' ';' {
1145 const AttrMethod *mtd = searchMethod($1, $3, $5);
1146 if (mtd)
1147 $$ = new PolicyAction($1, mtd, $5);
1148 else {
1149 delete $5;
1150 $$ = NULL;
1151 }
1152 free($3);
1153 }
1154 | TKN_RP_ATTR TKN_OPERATOR list_item ';' {
1155 ItemList *plist = new ItemList;
1156 plist->append($3);
1157
1158 const AttrMethod *mtd = searchMethod($1, $2, plist);
1159 if (mtd)
1160 $$ = new PolicyAction($1, mtd, plist);
1161 else {
1162 delete plist;
1163 $$ = NULL;
1164 }
1165 // Added by wlee
1166 free($2);
1167 }
1168 | TKN_RP_ATTR '(' generic_list ')' ';' {
1169 const AttrMethod *mtd = searchMethod($1, "()", $3);
1170 if (mtd)
1171 $$ = new PolicyAction($1, mtd, $3);
1172 else {
1173 delete $3;
1174 $$ = NULL;
1175 }
1176 }
1177 | TKN_RP_ATTR '[' generic_list ']' ';' {
1178 const AttrMethod *mtd = searchMethod($1, "[]", $3);
1179 if (mtd)
1180 $$ = new PolicyAction($1, mtd, $3);
1181 else {
1182 delete $3;
1183 $$ = NULL;
1184 }
1185 }
1186 | ';' {
1187 $$ = NULL;
1188 }
1189 ;
1190
1191 //// filter /////////////////////////////////////////////////////////////
1192
1193 filter: filter OP_OR filter_term {
1194 $$ = new FilterOR($1, $3);
1195 }
1196 | filter filter_term %prec OP_OR {
1197 $$ = new FilterOR($1, $2);
1198 }
1199 | filter_term
1200 ;
1201
1202 filter_term : filter_term OP_AND filter_factor {
1203 $$ = new FilterAND($1, $3);
1204 }
1205 | filter_factor
1206 ;
1207
1208 filter_factor : OP_NOT filter_factor {
1209 $$ = new FilterNOT($2);
1210 }
1211 | '(' filter ')' {
1212 $$ = $2;
1213 }
1214 | filter_operand
1215 ;
1216
1217 filter_operand: KEYW_ANY {
1218 $$ = new FilterANY;
1219 }
1220 | '<' filter_aspath '>' {
1221 $$ = new FilterASPath($2);
1222 }
1223 | filter_rp_attribute {
1224 if ($1)
1225 $$ = $1;
1226 else
1227 $$ = new FilterNOT(new FilterANY);
1228 }
1229 | TKN_FLTRNAME {
1230 $$ = new FilterFLTRNAME($1);
1231 }
1232 | filter_prefix
1233 ;
1234
1235 filter_prefix: filter_prefix_operand OP_MS {
1236 $2->f1 = $1;
1237 $$ = $2;
1238 }
1239 | filter_prefix_operand
1240 ;
1241
1242 filter_prefix_operand: TKN_ASNO {
1243 $$ = new FilterASNO($1);
1244 }
1245 | KEYW_PEERAS {
1246 $$ = new FilterPeerAS;
1247 }
1248 | TKN_ASNAME {
1249 $$ = new FilterASNAME($1);
1250 }
1251 | TKN_RSNAME {
1252 $$ = new FilterRSNAME($1);
1253 }
1254 | '{' opt_filter_prefix_list '}' {
1255 $$ = $2;
1256 }
1257 ;
1258
1259 opt_filter_prefix_list: {
1260 $$ = new FilterPRFXList;
1261 }
1262 | filter_prefix_list
1263 ;
1264
1265 filter_prefix_list: filter_prefix_list_prefix {
1266 ((FilterPRFXList *) ($$ = new FilterPRFXList))->add_high(*$1);
1267 delete $1;
1268 }
1269 | filter_prefix_list ',' filter_prefix_list_prefix {
1270 $$ = $1;
1271 ((FilterPRFXList *) ($$))->add_high(*$3);
1272 delete $3;
1273 }
1274 ;
1275
1276 filter_prefix_list_prefix: TKN_PRFXV4 {
1277 $$ = $1;
1278 }
1279 | TKN_PRFXV4RNG {
1280 $$ = $1;
1281 }
1282 ;
1283
1284 filter_aspath: filter_aspath '|' filter_aspath_term {
1285 $$ = new regexp_or($1, $3);
1286 }
1287 | filter_aspath_term
1288 ;
1289
1290 filter_aspath_term: filter_aspath_term filter_aspath_closure {
1291 $$ = new regexp_cat($1, $2);
1292 }
1293 | filter_aspath_closure
1294 ;
1295
1296 filter_aspath_closure: filter_aspath_closure '*' {
1297 $$ = new regexp_star($1);
1298 }
1299 | filter_aspath_closure '?' {
1300 $$ = new regexp_question($1);
1301 }
1302 | filter_aspath_closure '+' {
1303 $$ = new regexp_plus($1);
1304 }
1305 | filter_aspath_factor
1306 ;
1307
1308 filter_aspath_factor: '^' {
1309 $$ = new regexp_bol;
1310 }
1311 | '$' {
1312 $$ = new regexp_eol;
1313 }
1314 | '(' filter_aspath ')' {
1315 $$ = $2;
1316 }
1317 | filter_aspath_no
1318 ;
1319
1320 filter_aspath_no: TKN_ASNO {
1321 $$ = new regexp_symbol($1);
1322 }
1323 | KEYW_PEERAS {
1324 $$ = new regexp_symbol(symbols.symID("PEERAS"));
1325 }
1326 | TKN_ASNAME {
1327 $$ = new regexp_symbol($1);
1328 }
1329 | '.' {
1330 $$ = new regexp_symbol(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1331 }
1332 | '[' filter_aspath_range ']' {
1333 $$ = $2;
1334 }
1335 | '[' '^' filter_aspath_range ']' {
1336 $$ = $3;
1337 ((regexp_symbol *) $$)->complement();
1338 }
1339 ;
1340
1341 filter_aspath_range: {
1342 $$ = new regexp_symbol;
1343 }
1344 | filter_aspath_range TKN_ASNO {
1345 ((regexp_symbol *) ($$ = $1))->add($2);
1346 }
1347 | filter_aspath_range KEYW_PEERAS {
1348 ((regexp_symbol *) ($$ = $1))->add(symbols.symID("PEERAS"));
1349 }
1350 | filter_aspath_range '.' {
1351 ((regexp_symbol *) ($$ = $1))->add(regexp_symbol::MIN_AS, regexp_symbol::MAX_AS);
1352 }
1353 | filter_aspath_range TKN_ASNO '-' TKN_ASNO {
1354 ((regexp_symbol *) ($$ = $1))->add($2, $4);
1355 }
1356 | filter_aspath_range TKN_ASNAME {
1357 ((regexp_symbol *) ($$ = $1))->add($2);
1358 }
1359 ;
1360
1361 filter_rp_attribute: TKN_RP_ATTR '.' TKN_WORD '(' generic_list ')' {
1362 const AttrMethod *mtd = searchMethod($1, $3, $5);
1363 if (mtd)
1364 $$ = new FilterRPAttribute($1, mtd, $5);
1365 else {
1366 delete $5;
1367 $$ = NULL;
1368 }
1369 free($3);
1370 }
1371 | TKN_RP_ATTR TKN_OPERATOR list_item {
1372 ItemList *plist = new ItemList;
1373 plist->append($3);
1374
1375 const AttrMethod *mtd = searchMethod($1, $2, plist);
1376 if (mtd)
1377 $$ = new FilterRPAttribute($1, mtd, plist);
1378 else {
1379 delete plist;
1380 $$ = NULL;
1381 }
1382 // Added by wlee
1383 free($2);
1384 }
1385 | TKN_RP_ATTR '(' generic_list ')' {
1386 const AttrMethod *mtd = searchMethod($1, "()", $3);
1387 if (mtd)
1388 $$ = new FilterRPAttribute($1, mtd, $3);
1389 else {
1390 delete $3;
1391 $$ = NULL;
1392 }
1393 }
1394 | TKN_RP_ATTR '[' generic_list ']' {
1395 const AttrMethod *mtd = searchMethod($1, "[]", $3);
1396 if (mtd)
1397 $$ = new FilterRPAttribute($1, mtd, $3);
1398 else {
1399 delete $3;
1400 $$ = NULL;
1401 }
1402 }
1403 ;
1404
1405 //// peering action pair ////////////////////////////////////////////////
1406
1407 import_peering_action_list: KEYW_FROM peering opt_action {
1408 $$ = new List<PolicyPeeringAction>;
1409 $$->append(new PolicyPeeringAction($2, $3));
1410 }
1411 | import_peering_action_list KEYW_FROM peering opt_action {
1412 $$ = $1;
1413 $$->append(new PolicyPeeringAction($3, $4));
1414 }
1415 ;
1416
1417 export_peering_action_list: KEYW_TO peering opt_action {
1418 $$ = new List<PolicyPeeringAction>;
1419 $$->append(new PolicyPeeringAction($2, $3));
1420 }
1421 | export_peering_action_list KEYW_TO peering opt_action {
1422 $$ = $1;
1423 $$->append(new PolicyPeeringAction($3, $4));
1424 }
1425 ;
1426
1427 //// import/export factor ///////////////////////////////////////////////
1428
1429 import_factor: import_peering_action_list KEYW_ACCEPT filter {
1430 $$ = new PolicyFactor($1, $3);
1431 }
1432 ;
1433
1434 import_factor_list: import_factor ';' {
1435 $$ = new PolicyTerm;
1436 $$->append($1);
1437 }
1438 | import_factor_list import_factor ';' {
1439 $$ = $1;
1440 $$->append($2);
1441 }
1442 ;
1443
1444 export_factor: export_peering_action_list KEYW_ANNOUNCE filter {
1445 $$ = new PolicyFactor($1, $3);
1446 }
1447 ;
1448
1449 export_factor_list: export_factor ';' {
1450 $$ = new PolicyTerm;
1451 $$->append($1);
1452 }
1453 | export_factor_list export_factor ';' {
1454 $$ = $1;
1455 $$->append($2);
1456 }
1457 ;
1458
1459 //// import/export term /////////////////////////////////////////////////
1460
1461 import_term: import_factor ';' {
1462 PolicyTerm *term = new PolicyTerm;
1463 term->append($1);
1464 $$ = term;
1465 }
1466 | '{' import_factor_list '}' {
1467 $$ = $2;
1468 }
1469 ;
1470
1471 export_term: export_factor ';' {
1472 PolicyTerm *term = new PolicyTerm;
1473 term->append($1);
1474 $$ = term;
1475 }
1476 | '{' export_factor_list '}' {
1477 $$ = $2;
1478 }
1479 ;
1480
1481 //// import/export expr /////////////////////////////////////////////////
1482
1483 import_expr: import_term {
1484 $$ = $1;
1485 }
1486 | import_term KEYW_REFINE import_expr {
1487 $$ = new PolicyRefine($1, $3);
1488 }
1489 | import_term KEYW_EXCEPT import_expr {
1490 $$ = new PolicyExcept($1, $3);
1491 }
1492 ;
1493
1494 export_expr: export_term {
1495 $$ = $1;
1496 }
1497 | export_term KEYW_REFINE export_expr {
1498 $$ = new PolicyRefine($1, $3);
1499 }
1500 | export_term KEYW_EXCEPT export_expr {
1501 $$ = new PolicyExcept($1, $3);
1502 }
1503 ;
1504
1505 //// protocol ///////////////////////////////////////////////////////////
1506
1507 opt_protocol_from: {
1508 $$ = schema.searchProtocol("BGP4");
1509 }
1510 | KEYW_PROTOCOL tkn_word {
1511 $$ = schema.searchProtocol($2);
1512 if (!$$) {
1513 handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1514 $$ = schema.searchProtocol("BGP4");
1515 }
1516 free($2);
1517 }
1518 ;
1519
1520 opt_protocol_into: {
1521 $$ = schema.searchProtocol("BGP4");
1522 }
1523 | KEYW_INTO tkn_word {
1524 $$ = schema.searchProtocol($2);
1525 if (!$$) {
1526 handle_warning("Warning: unknown protocol %s, BGP4 assumed.\n", $2);
1527 $$ = schema.searchProtocol("BGP4");
1528 }
1529 free($2);;
1530 }
1531 ;
1532
1533 //**** import/export attributes *******************************************
1534
1535 import_attribute: ATTR_IMPORT
1536 opt_protocol_from opt_protocol_into
1537 import_expr TKN_EOA {
1538 $$ = changeCurrentAttr(new AttrImport($2, $3, $4));
1539 }
1540 | ATTR_IMPORT opt_protocol_from opt_protocol_into import_factor TKN_EOA {
1541 PolicyTerm *term = new PolicyTerm;
1542 term->append($4);
1543
1544 $$ = changeCurrentAttr(new AttrImport($2, $3, term));
1545 }
1546 | ATTR_IMPORT error TKN_EOA {
1547 $$ = $1;
1548 handle_error("Error: from <peering> expected.\n");
1549 yyerrok;
1550 }
1551 ;
1552
1553 export_attribute: ATTR_EXPORT
1554 opt_protocol_from opt_protocol_into
1555 export_expr TKN_EOA {
1556 $$ = changeCurrentAttr(new AttrExport($2, $3, $4));
1557 }
1558 | ATTR_EXPORT opt_protocol_from opt_protocol_into export_factor TKN_EOA {
1559 PolicyTerm *term = new PolicyTerm;
1560 term->append($4);
1561
1562 $$ = changeCurrentAttr(new AttrExport($2, $3, term));
1563 }
1564 | ATTR_EXPORT error TKN_EOA {
1565 $$ = $1;
1566 handle_error("Error: to <peering> expected.\n");
1567 yyerrok;
1568 }
1569 ;
1570
1571 opt_default_filter: {
1572 $$ = new FilterANY;
1573 }
1574 | KEYW_NETWORKS filter {
1575 $$ = $2;
1576 }
1577 ;
1578
1579 default_attribute: ATTR_DEFAULT KEYW_TO peering
1580 opt_action
1581 opt_default_filter TKN_EOA {
1582 $$ = changeCurrentAttr(new AttrDefault($3, $4, $5));
1583 }
1584 | ATTR_DEFAULT KEYW_TO peering error TKN_EOA {
1585 if ($3)
1586 delete $3;
1587 handle_error("Error: badly formed filter/action or keyword NETWORKS/ACTION missing.\n");
1588 yyerrok;
1589 }
1590 | ATTR_DEFAULT error TKN_EOA {
1591 handle_error("Error: TO <peer> missing.\n");
1592 yyerrok;
1593 }
1594 ;
1595
1596 filter_attribute: ATTR_FILTER filter TKN_EOA {
1597 $$ = changeCurrentAttr(new AttrFilter($2));
1598 }
1599 | ATTR_FILTER error TKN_EOA {
1600 $$ = $1;
1601 handle_error("Error: badly formed filter.\n");
1602 yyerrok;
1603 }
1604 ;
1605
1606 peering_attribute: ATTR_PEERING peering TKN_EOA {
1607 $$ = changeCurrentAttr(new AttrPeering($2));
1608 }
1609 | ATTR_PEERING error TKN_EOA {
1610 $$ = $1;
1611 handle_error("Error: badly formed filter.\n");
1612 yyerrok;
1613 }
1614 ;
1615
1616 //**** inet-rtr class *****************************************************
1617
1618 ifaddr_attribute: ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT opt_action TKN_EOA {
1619 $$ = changeCurrentAttr(new AttrIfAddr($2->get_ipaddr(), $4, $5));
1620 delete $2;
1621 }
1622 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN TKN_INT error TKN_EOA {
1623 delete $2;
1624 $$ = $1;
1625 handle_error("Error: in action specification.\n");
1626 yyerrok;
1627 }
1628 | ATTR_IFADDR TKN_IPV4 KEYW_MASKLEN error TKN_EOA {
1629 delete $2;
1630 $$ = $1;
1631 handle_error("Error: integer mask length expected.\n");
1632 yyerrok;
1633 }
1634 | ATTR_IFADDR TKN_IPV4 error TKN_EOA {
1635 delete $2;
1636 $$ = $1;
1637 handle_error("Error: MASKLEN <length> expected.\n");
1638 yyerrok;
1639 }
1640 | ATTR_IFADDR error TKN_EOA {
1641 $$ = $1;
1642 handle_error("Error: <ip_address> MASKLEN <length> [<action>] expected.\n");
1643 yyerrok;
1644 }
1645 ;
1646
1647 //// peer attribute /////////////////////////////////////////////////////
1648
1649 opt_peer_options: {
1650 $$ = new List<AttrPeerOption>;
1651 }
1652 | peer_options {
1653 $$ = $1;
1654 }
1655 ;
1656
1657 peer_options: peer_option {
1658 $$ = new List<AttrPeerOption>;
1659 $$->append($1);
1660 }
1661 | peer_options ',' peer_option {
1662 $$ = $1;
1663 $$->append($3);
1664 }
1665 ;
1666
1667 peer_option: tkn_word '(' generic_list ')' {
1668 $$ = new AttrPeerOption($1, $3);
1669 }
1670 ;
1671
1672 peer_id: TKN_IPV4
1673 | TKN_DNS {
1674 $$ = new IPAddr;
1675 }
1676 | TKN_RTRSNAME {
1677 $$ = new IPAddr;
1678 }
1679 | TKN_PRNGNAME {
1680 $$ = new IPAddr;
1681 }
1682 ;
1683
1684 peer_attribute: ATTR_PEER tkn_word peer_id opt_peer_options TKN_EOA {
1685 const AttrProtocol *protocol = schema.searchProtocol($2);
1686 int position;
1687 const RPType *correctType;
1688 bool error = false;
1689
1690 if (!protocol) {
1691 handle_error("Error: unknown protocol %s.\n", $2);
1692 error = true;
1693 } else {
1694 ((AttrProtocol *) protocol)->startMandatoryCheck();
1695 for (AttrPeerOption *opt = $4->head(); opt; opt = $4->next(opt)) {
1696 const AttrProtocolOption *decl = protocol->searchOption(opt->option);
1697 if (!decl) {
1698 handle_error("Error: protocol %s does not have option %s.\n",
1699 $2, opt->option);
1700 error = true;
1701 } else {
1702 for (; decl; decl = protocol->searchNextOption(decl))
1703 if (decl->option->validateArgs(opt->args, position, correctType))
1704 break;
1705 if (! decl) {
1706 handleArgumentTypeError($2, opt->option, position, correctType);
1707 error = true;
1708 }
1709 }
1710 }
1711 }
1712
1713 if (! error) {
1714 const AttrProtocolOption *missing =
1715 ((AttrProtocol *) protocol)->missingMandatoryOption();
1716 if (missing) {
1717 handle_error("Error: mandatory option %s of protocol %s is missing.\n",
1718 missing->option->name, $2);
1719 error = true;
1720 }
1721 }
1722
1723 if (!error)
1724 $$ = changeCurrentAttr(new AttrPeer(protocol, $3, $4));
1725 else {
1726 free($2);
1727 delete $3;
1728 delete $4;
1729 }
1730 }
1731 | ATTR_PEER tkn_word TKN_IPV4 error TKN_EOA {
1732 $$ = $1;
1733 free($2);
1734 delete $3;
1735 handle_error("Error: in peer option.\n");
1736 yyerrok;
1737 }
1738 | ATTR_PEER tkn_word error TKN_EOA {
1739 $$ = $1;
1740 free($2);
1741 handle_error("Error: missing peer ip_address.\n");
1742 yyerrok;
1743 }
1744 | ATTR_PEER error TKN_EOA {
1745 $$ = $1;
1746 handle_error("Error: missing protocol name.\n");
1747 yyerrok;
1748 }
1749 ;
1750
1751 //**** route class ********************************************************
1752
1753 aggr_bndry_attribute: ATTR_AGGR_BNDRY as_expr TKN_EOA {
1754 $$ = $1;
1755 delete $2;
1756 }
1757 | ATTR_AGGR_BNDRY error TKN_EOA {
1758 $$ = $1;
1759 handle_error("Error: <as-expression> expected.\n");
1760 yyerrok;
1761 }
1762 ;
1763
1764 aggr_mtd_attribute: ATTR_AGGR_MTD KEYW_INBOUND TKN_EOA {
1765 $$ = $1;
1766 }
1767 | ATTR_AGGR_MTD KEYW_OUTBOUND opt_as_expr TKN_EOA {
1768 delete $3;
1769 }
1770 | ATTR_AGGR_MTD KEYW_OUTBOUND error TKN_EOA {
1771 $$ = $1;
1772 handle_error("Error: OUTBOUND <as-expression> expected.\n");
1773 yyerrok;
1774 }
1775 | ATTR_AGGR_MTD KEYW_INBOUND error TKN_EOA {
1776 $$ = $1;
1777 handle_error("Error: INBOUND can not be followed by anything.\n");
1778 yyerrok;
1779 }
1780 | ATTR_AGGR_MTD error TKN_EOA {
1781 $$ = $1;
1782 handle_error("Error: keyword INBOUND or OUTBOUND expected.\n");
1783 yyerrok;
1784 }
1785 ;
1786
1787 //// inject attribute ///////////////////////////////////////////////////
1788
1789 opt_inject_expr: {
1790 $$ = new FilterANY;
1791 }
1792 | KEYW_UPON inject_expr {
1793 $$ = $2;
1794 }
1795 ;
1796
1797 inject_expr: inject_expr OP_OR inject_expr_term {
1798 $$ = new FilterOR($1, $3);
1799 }
1800 | inject_expr_term
1801 ;
1802
1803 inject_expr_term: inject_expr_term OP_AND inject_expr_factor {
1804 $$ = new FilterAND($1, $3);
1805 }
1806 | inject_expr_factor
1807 ;
1808
1809 inject_expr_factor: '(' inject_expr ')' {
1810 $$ = $2;
1811 }
1812 | inject_expr_operand
1813 ;
1814
1815 inject_expr_operand: KEYW_STATIC {
1816 $$ = new FilterANY;
1817 }
1818 | KEYW_HAVE_COMPONENTS '{' opt_filter_prefix_list '}' {
1819 $$ = new FilterHAVE_COMPONENTS((FilterPRFXList *) $3);
1820 }
1821 | KEYW_EXCLUDE '{' opt_filter_prefix_list '}' {
1822 $$ = new FilterEXCLUDE((FilterPRFXList *) $3);
1823 }
1824 ;
1825
1826 inject_attribute: ATTR_INJECT opt_router_expr_with_at opt_action opt_inject_expr TKN_EOA {
1827 $$ = $1;
1828 delete $2;
1829 delete $3;
1830 delete $4;
1831 }
1832 | ATTR_INJECT error TKN_EOA {
1833 $$ = $1;
1834 handle_error("Error: [at <router-exp>] [action <action>] [upon <condition>] expected.\n");
1835 yyerrok;
1836 }
1837 ;
1838
1839 //// components attribute ///////////////////////////////////////////////
1840
1841 opt_atomic:
1842 | KEYW_ATOMIC
1843 ;
1844
1845 components_list: {
1846 }
1847 | filter {
1848 delete $1;
1849 }
1850 | components_list KEYW_PROTOCOL tkn_word filter {
1851 free($3);
1852 delete $4;
1853 }
1854 ;
1855
1856 components_attribute: ATTR_COMPONENTS opt_atomic components_list TKN_EOA {
1857 $$ = $1;
1858 }
1859 | ATTR_COMPONENTS error TKN_EOA {
1860 $$ = $1;
1861 handle_error("Error: [ATOMIC] [[<filter>] [PROTOCOL <protocol> <filter>] ...] expected.\n");
1862 yyerrok;
1863 }
1864 ;
1865
1866 //**** route-set **********************************************************
1867
1868 opt_rs_members_list: /* empty list */ {
1869 $$ = new ItemList;
1870 }
1871 | rs_members_list
1872 ;
1873
1874 rs_members_list: rs_member {
1875 $$ = new ItemList;
1876 $$->append($1);
1877 }
1878 | rs_members_list ',' rs_member {
1879 $$ = $1;
1880 $$->append($3);
1881 }
1882 ;
1883
1884 rs_member: TKN_ASNO {
1885 $$ = new ItemASNO($1);
1886 }
1887 | TKN_ASNO OP_MS {
1888 $$ = new ItemMSItem(new ItemASNO($1), $2->code, $2->n, $2->m);
1889 delete $2;
1890 }
1891 | TKN_ASNAME {
1892 $$ = new ItemASNAME($1);
1893 }
1894 | TKN_ASNAME OP_MS {
1895 $$ = new ItemMSItem(new ItemASNAME($1), $2->code, $2->n, $2->m);
1896 delete $2;
1897 }
1898 | TKN_RSNAME {
1899 $$ = new ItemRSNAME($1);
1900 }
1901 | TKN_RSNAME OP_MS {
1902 $$ = new ItemMSItem(new ItemRSNAME($1), $2->code, $2->n, $2->m);
1903 delete $2;
1904 }
1905 | TKN_PRFXV4 {
1906 $$ = new ItemPRFXV4($1);
1907 }
1908 | TKN_PRFXV4RNG {
1909 $$ = new ItemPRFXV4Range($1);
1910 }
1911 ;
1912
1913 rs_members_attribute: ATTR_RS_MEMBERS opt_rs_members_list TKN_EOA {
1914 $$ = changeCurrentAttr(new AttrGeneric($1->type, $2));
1915 }
1916 | ATTR_RS_MEMBERS error TKN_EOA {
1917 $$ = $1;
1918 handle_error("Error: invalid member\n");
1919 yyerrok;
1920 }
1921 ;
1922
1923 //**** dictionary *********************************************************
1924
1925 rpattr_attribute: ATTR_RP_ATTR TKN_WORD methods TKN_EOA {
1926 $$ = changeCurrentAttr(new AttrRPAttr($2, $3));
1927 }
1928 | ATTR_RP_ATTR TKN_RP_ATTR methods TKN_EOA {
1929 $$ = changeCurrentAttr(new AttrRPAttr($2->name, $3));
1930 }
1931 | ATTR_RP_ATTR error TKN_EOA {
1932 $$ = $1;
1933 handle_error("Error: invalid rp-attribute specification\n");
1934 yyerrok;
1935 }
1936 ;
1937
1938 methods: method {
1939 $$ = new List<AttrMethod>;
1940 if ($1)
1941 $$->append($1);
1942 }
1943 | methods method {
1944 $$ = $1;
1945 if ($2)
1946 $$->append($2);
1947 }
1948 ;
1949
1950 method: TKN_WORD '(' ')' {
1951 $$ = new AttrMethod($1, new List<RPTypeNode>, false);
1952 }
1953 | TKN_WORD '(' typedef_type_list ')' {
1954 $$ = new AttrMethod($1, $3, false);
1955 }
1956 | TKN_WORD '(' typedef_type_list ',' TKN_3DOTS ')' {
1957 $$ = new AttrMethod($1, $3, true);
1958 }
1959 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ')' {
1960 char buffer[16];
1961 strcpy(buffer, "operator");
1962 strcat(buffer, $2);
1963 $$ = new AttrMethod(strdup(buffer), $4, false, true);
1964 free($2);
1965 }
1966 | KEYW_OPERATOR TKN_OPERATOR '(' typedef_type_list ',' TKN_3DOTS ')' {
1967 char buffer[16];
1968 strcpy(buffer, "operator");
1969 strcat(buffer, $2);
1970 $$ = new AttrMethod(strdup(buffer), $4, true, true);
1971 free($2);
1972 }
1973 | TKN_WORD error ')' {
1974 free($1);
1975 $$ = NULL;
1976 handle_error("Error: invalid method specification for %s\n", $1);
1977 }
1978 | KEYW_OPERATOR TKN_OPERATOR error ')' {
1979 $$ = NULL;
1980 handle_error("Error: invalid operator specification for %s\n", $2);
1981 free($2);
1982 }
1983 | KEYW_OPERATOR error ')' {
1984 $$ = NULL;
1985 handle_error("Error: invalid operator\n");
1986 }
1987 | error ')' {
1988 $$ = NULL;
1989 handle_error("Error: method specification expected\n");
1990 }
1991 ;
1992
1993 //// typedef attribute /////////////////////////////////////////////////
1994
1995 typedef_attribute: ATTR_TYPEDEF TKN_WORD typedef_type TKN_EOA {
1996 $$ = changeCurrentAttr(new AttrTypedef($2, $3));
1997 }
1998 | ATTR_TYPEDEF error TKN_EOA {
1999 $$ = $1;
2000 handle_error("Error: invalid typedef specification\n");
2001 yyerrok;
2002 }
2003 ;
2004
2005 typedef_type_list: typedef_type {
2006 $$ = new List<RPTypeNode>;
2007 if ($1)
2008 $$->append(new RPTypeNode($1));
2009 }
2010 | typedef_type_list ',' typedef_type {
2011 $$ = $1;
2012 if ($3)
2013 $$->append(new RPTypeNode($3));
2014 }
2015 ;
2016
2017 typedef_type: KEYW_UNION typedef_type_list {
2018 $$ = RPType::newRPType("union", $2);
2019 if (!$$) {
2020 handle_error("Error: empty union specification\n");
2021 delete $2;
2022 }
2023 }
2024 | KEYW_RANGE KEYW_OF typedef_type {
2025 if ($3)
2026 $$ = new RPTypeRange($3);
2027 else {
2028 $$ = NULL;
2029 }
2030 }
2031 | TKN_WORD {
2032 $$ = RPType::newRPType($1);
2033 if (!$$) {
2034 handle_error("Error: invalid type %s\n", $1);
2035 }
2036 free($1);
2037 }
2038 | TKN_WORD '[' TKN_INT ',' TKN_INT ']' {
2039 $$ = RPType::newRPType($1, $3, $5);
2040 if (!$$) {
2041 handle_error("Error: invalid type %s[%d,%d]\n", $1, $3, $5);
2042 }
2043 free($1);
2044 }
2045 | TKN_WORD '[' TKN_REAL ',' TKN_REAL ']' {
2046 $$ = RPType::newRPType($1, $3, $5);
2047 if (!$$) {
2048 handle_error("Error: invalid type %s[%f,%f]\n", $1, $3, $5);
2049 }
2050 free($1);
2051 }
2052 | TKN_WORD '[' enum_list ']' {
2053 $$ = RPType::newRPType($1, $3);
2054 if (!$$) {
2055 handle_error("Error: invalid type %s, enum expected\n", $1);
2056 delete $3;
2057 }
2058 free($1);
2059 }
2060 | KEYW_LIST '[' TKN_INT ':' TKN_INT ']' KEYW_OF typedef_type {
2061 if ($8)
2062 if ($3 < $5)
2063 $$ = new RPTypeList($8, $3, $5);
2064 else
2065 $$ = new RPTypeList($8, $5, $3);
2066 else {
2067 $$ = NULL;
2068 delete $8;
2069 }
2070 }
2071 | KEYW_LIST KEYW_OF typedef_type {
2072 if ($3)
2073 $$ = new RPTypeList($3);
2074 else {
2075 $$ = NULL;
2076 }
2077 }
2078 | KEYW_LIST error KEYW_OF typedef_type {
2079 $$ = NULL;
2080 delete $4;
2081 handle_error("Error: invalid list size\n");
2082 }
2083 ;
2084
2085 enum_list: tkn_word {
2086 $$ = new List<WordNode>;
2087 $$->append(new WordNode($1));
2088 }
2089 | enum_list ',' tkn_word {
2090 $$ = $1;
2091 $$->append(new WordNode($3));
2092 }
2093 ;
2094
2095 //// protocol attribute /////////////////////////////////////////////////
2096
2097 protocol_attribute: ATTR_PROTOCOL tkn_word protocol_options TKN_EOA {
2098 $$ = changeCurrentAttr(new AttrProtocol($2, $3));
2099 }
2100 | ATTR_PROTOCOL tkn_word error TKN_EOA {
2101 $$ = $1;
2102 handle_error("Error: invalid protocol option\n");
2103 yyerrok;
2104 }
2105 | ATTR_PROTOCOL error TKN_EOA {
2106 $$ = $1;
2107 handle_error("Error: invalid protocol name\n");
2108 yyerrok;
2109 }
2110 ;
2111
2112 protocol_options: {
2113 $$ = new List<AttrProtocolOption>;
2114 }
2115 | protocol_options protocol_option {
2116 $$ = $1;
2117 $$->append($2);
2118 }
2119 ;
2120
2121 protocol_option: KEYW_MANDATORY method {
2122 $$ = new AttrProtocolOption(false, $2);
2123 }
2124 | KEYW_OPTIONAL method {
2125 $$ = new AttrProtocolOption(true, $2);
2126 }
2127 ;
2128
2129 //**** schema class *******************************************************
2130
2131 opt_attr_options: {
2132 $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2133 }
2134 | attr_options {
2135 $$ = new AttrAttr(ATTR_GENERIC, RPType::newRPType("free_text"));
2136 *$$ |= *$1;
2137 delete $1;
2138 }
2139 ;
2140
2141 attr_options: attr_option {
2142 $$ = $1;
2143 }
2144 | attr_options ',' attr_option {
2145 $$ = $1;
2146 *$$ |= *$3;
2147 delete $3;
2148 }
2149 | error ',' attr_option {
2150 $$ = $3;
2151 handle_error("Error: in attr option specification.\n");
2152 }
2153 ;
2154
2155 attr_option: KEYW_SYNTAX '(' typedef_type ')' {
2156 $$ = new AttrAttr(ATTR_GENERIC, $3);
2157 }
2158 | KEYW_SYNTAX '(' KEYW_SPECIAL ',' tkn_word ')' {
2159 int syntax = schema.searchAttrSyntax($5);
2160 if (syntax < 0) {
2161 handle_error("Error: no known syntax rule for %s.\n", $5);
2162 $$ = new AttrAttr;
2163 } else
2164 $$ = new AttrAttr(syntax, NULL);
2165 free($5);
2166 }
2167 | KEYW_OPTIONAL {
2168 $$ = new AttrAttr(AttrAttr::OPTIONAL);
2169 }
2170 | KEYW_MANDATORY {
2171 $$ = new AttrAttr;
2172 }
2173 | KEYW_DELETED {
2174 $$ = new AttrAttr(AttrAttr::DELETED)
2175 }
2176 | KEYW_SINGLEVALUED {
2177 $$ = new AttrAttr;
2178 }
2179 | KEYW_MULTIVALUED {
2180 $$ = new AttrAttr(AttrAttr::MULTIVALUED);
2181 }
2182 | KEYW_LOOKUP {
2183 $$ = new AttrAttr(AttrAttr::LOOKUP);
2184 }
2185 | KEYW_KEY {
2186 $$ = new AttrAttr(AttrAttr::KEY);
2187 }
2188 | KEYW_OBSOLETE {
2189 $$ = new AttrAttr(AttrAttr::OBSOLETE);
2190 }
2191 | KEYW_INTERNAL {
2192 $$ = new AttrAttr(AttrAttr::INTERNAL);
2193 }
2194 | KEYW_GENERATED {
2195 $$ = new AttrAttr(AttrAttr::GENERATED);
2196 }
2197 ;
2198
2199 attr_attribute: ATTR_ATTR tkn_word opt_attr_options TKN_EOA {
2200 $3->setName($2);
2201 $$ = changeCurrentAttr($3);
2202 }
2203 | ATTR_ATTR tkn_word error TKN_EOA {
2204 $$ = $1;
2205 free($2);
2206 handle_error("Error: in attr option specification.\n");
2207 yyerrok;
2208 }
2209 | ATTR_ATTR error TKN_EOA {
2210 $$ = $1;
2211 handle_error("Error: attr name expected.\n");
2212 yyerrok;
2213 }
2214 ;
2215
2216 //**** rps-auth stuff *****************************************************
2217
2218 mnt_routes_attribute: ATTR_MNT_ROUTES mnt_routes_list TKN_EOA {
2219 $$ = changeCurrentAttr(new AttrMntRoutes($2));
2220 }
2221 ;
2222
2223 mnt_routes_list: mnt_routes_list_item {
2224 $$ = new List<AttrMntRoutes::MntPrfxPair>;
2225 $$->append($1);
2226 }
2227 | mnt_routes_list ',' mnt_routes_list_item {
2228 $$ = $1;
2229 $$->append($3);
2230 }
2231 ;
2232
2233 mnt_routes_list_item: tkn_word {
2234 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2235 }
2236 | tkn_word KEYW_ANY {
2237 $$ = new AttrMntRoutes::MntPrfxPair($1, NULL);
2238 }
2239 | tkn_word '{' opt_filter_prefix_list '}' {
2240 $$ = new AttrMntRoutes::MntPrfxPair($1, (FilterPRFXList *) $3);
2241 }
2242 ;
2243
2244 %%
2245
2246 void enable_yy_parser_debugging() {
/* [<][>][^][v][top][bottom][index][help] */
2247 #if YYDEBUG != 0
2248 yydebug = 1;
2249 #endif
2250 }
2251
2252 void handleArgumentTypeError(char *attr, char *method, int position,
/* [<][>][^][v][top][bottom][index][help] */
2253 const RPType *correctType,
2254 bool isOperator = false) {
2255 if (isOperator)
2256 if (position)
2257 handle_error("Error: argument %d to %s.operator%s should be %s.\n",
2258 position, attr, method, ((RPType *) correctType)->name());
2259 else
2260 handle_error("Error: wrong number of arguments to %s.operator%s.\n",
2261 attr, method);
2262 else
2263 if (position)
2264 handle_error("Error: argument %d to %s.%s should be %s.\n",
2265 position, attr, method, ((RPType *) correctType)->name());
2266 else
2267 handle_error("Error: wrong number of arguments to %s.%s.\n",
2268 attr, method);
2269 }
2270
2271 const AttrMethod *searchMethod(const AttrRPAttr *rp_attr, char *method, ItemList *args) {
/* [<][>][^][v][top][bottom][index][help] */
2272 const AttrMethod *mtd = rp_attr->searchMethod(method);
2273 int position;
2274 const RPType *correctType;
2275
2276 if (!mtd) {
2277 handle_error("Error: rp-attribute %s does not have %s defined.\n",
2278 rp_attr->name, method);
2279 return NULL;
2280 }
2281
2282 for (; mtd; mtd = rp_attr->searchNextMethod(mtd))
2283 if (mtd->validateArgs(args, position, correctType))
2284 return mtd;
2285
2286 handleArgumentTypeError(rp_attr->name, method, position, correctType);
2287
2288 return NULL;
2289 }