203819a1083c08086e8ffe89a99d4e4c36a1a3af
[obnox/wireshark/wip.git] / plugins / mate / mate_grammar.lemon
1 %include {
2
3 /* mate_grammar.lemon
4 * MATE's configuration language grammar 
5 *
6 * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7 *
8 * $Id $
9 *
10 * Ethereal - Network traffic analyzer
11 * By Gerald Combs <gerald@ethereal.com>
12 * Copyright 1998 Gerald Combs
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 #include "mate.h"
30 #include "mate_grammar.h"
31
32 #define DUMMY void*
33
34 typedef struct _extraction {
35         gchar* as;
36         header_field_info* hfi;
37         struct _extraction* next;
38         struct _extraction* last;
39 } extraction_t;
40
41 typedef struct _pdu_flags {
42         gboolean drop_unassigned;
43         gboolean discard;
44         gboolean last_extracted;
45 } pdu_flags_t;
46
47 typedef struct _pdu_criteria_t {
48         AVPL* criterium_avpl;
49         avpl_match_mode criterium_match_mode;
50         accept_mode_t criterium_accept_mode;
51 } pdu_criteria_t;
52
53 typedef struct _pdu_statement {
54         GPtrArray* payload;
55         pdu_flags_t* flags;
56         extraction_t* extraction;
57         pdu_criteria_t* criteria;
58         GPtrArray* transforms;
59 } pdu_statement_t;
60
61 typedef struct _gop_tree_statement {
62         gop_tree_mode_t pdu_tree_mode;
63         gboolean drop_unassigned;
64         gboolean show_times;
65 } gop_tree_statement;
66
67 typedef struct _gop_timer_statement {
68         float expiration;
69         float idle_timeout;
70         float lifetime;
71 } gop_timer_statement;
72
73 typedef struct _gop_option_statement {
74         gop_timer_statement* timer_sts;
75         gop_tree_statement* tree_sts;
76 } gop_option_statement;
77
78 typedef struct _gop_control_statement {
79         AVPL* start;
80         AVPL* stop;
81         AVPL* extras;
82 } gop_control_statement;
83
84 typedef struct _gop_statement {
85         gop_control_statement* control;
86         gop_option_statement* options;
87         GPtrArray* transforms;
88 } gop_statement;
89
90 typedef struct _gog_statements {
91         float expiration;
92         gop_tree_mode_t gop_tree_mode;
93         GPtrArray* transform_list;
94         AVPL* extras;
95         LoAL* current_gogkeys;
96 } gog_statement_t;
97
98 static void configuration_error(mate_config* mc, const gchar* fmt, ...) {
99         static gchar error_buffer[256];
100         const gchar* incl;
101         gint i;
102         mate_config_frame* current_frame;
103         va_list list;
104         
105         va_start( list, fmt );
106         g_vsnprintf(error_buffer,sizeof(error_buffer),fmt,list);
107         va_end( list );
108
109         i = (gint) mc->config_stack->len;
110         
111         while (i--) {
112
113                 if (i>0) {
114                         incl = "\n   included from: ";
115                 } else {
116                         incl = " ";
117                 }
118                 
119                 current_frame = g_ptr_array_index(mc->config_stack,(guint)i);
120                 
121                 g_string_sprintfa(mc->config_error,"%s%s at line %u",incl, current_frame->filename, current_frame->linenum);
122         }
123         
124         g_string_sprintfa(mc->config_error,": %s\n",error_buffer);
125         
126         THROW(MateConfigError);
127
128 }
129
130 static AVPL_Transf* new_transform_elem(AVPL* match, AVPL* replace, avpl_match_mode match_mode, avpl_replace_mode replace_mode) {
131          AVPL_Transf* t = g_malloc(sizeof(AVPL_Transf));
132          
133          t->name = NULL;
134          t->match = match;
135          t->replace = replace;
136          t->match_mode = match_mode;
137          t->replace_mode = replace_mode;
138          
139          t->map = NULL;
140          t->next = NULL;
141          
142          return t;
143 }
144
145 static pdu_statement_t* do_pdu_statements(GPtrArray* payload, pdu_flags_t* flags, extraction_t* extraction, pdu_criteria_t* criteria, GPtrArray* transforms) {
146         pdu_statement_t* s = g_malloc(sizeof(pdu_statement_t));
147         
148         s->payload = payload;
149         s->flags = flags;
150         s->extraction = extraction;
151         s->criteria = criteria;
152         s->transforms = transforms;
153         
154         return s;
155 }
156
157 static gchar* recolonize(mate_config* mc, gchar* s) {
158         GString* str = g_string_new("");
159         gchar** vec;
160         gchar* r;
161         guint i,v;
162         gchar c;
163         
164         vec = g_strsplit(s,":",0);
165         
166         for (i = 0; vec[i]; i++) {
167                 g_strdown(vec[i]);
168                 
169                 v = 0;
170                 switch ( strlen(vec[i]) ) {
171                  case 2:
172                     c = vec[i][1];
173                         vec[i][1] = vec[i][0];
174                         vec[i][0] = c;
175                         if (vec[i][0] >= '0' && vec[i][0] <= '9') {
176                                 v += (vec[i][1] - '0' )*16;
177                         } else {
178                                 v += (vec[i][1] - 'a' + 10)*16;
179                         }
180                  case 1:
181                         if (vec[i][0] >= '0' && vec[i][0] <= '9') {
182                                 v += (vec[i][0] - '0' );
183                         } else {
184                                 v += (vec[i][0] - 'a' + 10);
185                         }
186                  case 0:
187                         break;
188                   default:
189                         configuration_error(mc,"bad token %s",s);
190                 }
191                 
192                 g_string_sprintfa(str,":%.2X",v);                                       
193         }
194         
195         g_strfreev(vec);
196         
197         g_string_erase(str,0,1);
198         
199         r = str->str;
200         
201         g_string_free(str,FALSE);
202
203         return r;
204 }
205
206 }
207
208 %name MateParser
209
210 %token_prefix TOKEN_
211
212 %token_type { gchar* }
213 %token_destructor { if ($$) g_free($$); }
214
215 %extra_argument { mate_config* mc }
216
217 %syntax_error {
218         configuration_error(mc,"Syntax Error before %s",yyminor);
219 }
220
221 %parse_failure {
222         configuration_error(mc,"Parse Error");
223 }
224
225 %type   transform_decl  { AVPL_Transf* }
226 %type   transform_body { AVPL_Transf* }
227 %type   transform_statements { AVPL_Transf* }
228 %type   transform_statement { AVPL_Transf* }
229 %type   transform_blks { AVPL_Transf* }
230 %type   transform_blk { AVPL_Transf* }
231 %type   match_mode { avpl_match_mode }
232 %type   action_mode { avpl_replace_mode }
233
234 %type gop_name { gchar* }
235 %type time_value { float }
236 %type pdu_name { gchar* }
237 %type gop_tree_mode { gop_tree_mode_t }
238 %type true_false { gboolean }
239
240 %type pdu_setup { pdu_statement_t* }
241 %type pdu_statements { pdu_statement_t* }
242
243 %type pdu_criteria_statement { pdu_criteria_t* }
244 %type pdu_flag_statements { pdu_flags_t* }
245 %type accept_mode { accept_mode_t }
246 %type drop_unassigned_statement { gboolean } 
247 %type discard_pdu_data_statement { gboolean } 
248 %type last_extracted_statement { gboolean } 
249
250 %type extraction_statement {extraction_t*}
251 %type extraction_statements {extraction_t*}
252
253 %type gop_setup { gop_statement* }
254 %type gop_statements { gop_statement* }
255 %type gop_control_statements { gop_control_statement* }
256 %type gop_option_statements { gop_option_statement* }
257 %type gop_timer_statements { gop_timer_statement* }
258 %type gop_tree_statements { gop_tree_statement* }
259
260 %type gop_start_statement { AVPL* }
261 %type gop_stop_statement { AVPL* }
262 %type extra_statement { AVPL* }
263 %type show_goptree_statement { gop_tree_mode_t }
264 %type show_times_statement { gboolean }
265 %type expiration_statement { float }
266 %type idle_timeout_statement { float }
267 %type lifetime_statement { float }
268
269 %type gog_statements { gog_statement_t* }
270 %type gog_goptree_statement { gop_tree_mode_t }
271 %type gog_key_statements { LoAL* }
272 %type gog_key_statement { AVPL* }
273 %type transform_list_statement { GPtrArray* }
274 %type transform { AVPL_Transf* }
275 %type gop_tree_type { gop_tree_mode_t }
276
277 %type payload_statement { GPtrArray* }
278 %type proto_stack { GPtrArray*  }
279 %type field { header_field_info* }
280 %type transform_list { GPtrArray* }
281 %type avpl { AVPL* }
282 %type avps { AVPL* }
283 %type avp { AVP* }
284 %type value { gchar* }
285 %type avp_oneoff { gchar* }
286
287
288 mate_config ::= decls DONE_KW SEMICOLON.
289
290 decls ::= decls decl.
291 decls ::= decl.
292
293 decl ::= pdu_decl.
294 decl ::= gop_decl.
295 decl ::= gog_decl.
296 decl ::= transform_decl.
297
298 /******************************************* TRANSFORM
299 */
300
301 transform_decl(A) ::= TRANSFORM_KW NAME(B) transform_body(C) SEMICOLON. {
302         AVPL_Transf* c;
303
304         if ( g_hash_table_lookup(mc->transfs,B) ) {
305                 configuration_error(mc,"A transformation called '%s' exists already",B);
306         }
307
308         for ( c = C; c; c = c->next )
309                 c->name = g_strdup(B);
310         
311         g_hash_table_insert(mc->transfs,C->name,C);
312         
313         A = NULL;
314 }
315
316 transform_body(A) ::= OPEN_BRACE transform_blks(B) CLOSE_BRACE. { A = B; }
317
318 transform_blks(A) ::= transform_blks(C) transform_blk(B). {
319         AVPL_Transf* c;
320         
321         for ( c = C; c->next; c = c->next ) ;
322         c->next = B;
323         A = C;
324 }
325
326 transform_blks(A) ::= transform_blk(B). { A = B; }
327
328 transform_blk(A) ::= MATCH_KW match_mode(B) avpl(C) action_mode(D) avpl(E) SEMICOLON. {
329         A = new_transform_elem(C,E,B,D);
330 }
331
332 transform_blk(A) ::= MATCH_KW match_mode(B) avpl(C) SEMICOLON. {
333         A = new_transform_elem(C,new_avpl(""),B,AVPL_INSERT);
334 }
335
336 transform_blk(A) ::= MATCH_KW avpl(B) action_mode(C) avpl(D) SEMICOLON. {
337         A = new_transform_elem(B,D,AVPL_STRICT,C);
338 }
339
340 transform_blk(A) ::= action_mode(B) avpl(C) SEMICOLON. {
341         A = new_transform_elem(new_avpl(""),C,AVPL_NO_MATCH,B);
342 }
343
344 transform_blk(A) ::= MATCH_KW avpl(B) SEMICOLON. {
345         A = new_transform_elem(B,new_avpl(""),AVPL_STRICT,AVPL_INSERT);
346 }
347
348 match_mode(A) ::=  STRICT_KW. { A = AVPL_STRICT; }
349 match_mode(A) ::=  EVERY_KW. { A = AVPL_EVERY; }
350 match_mode(A) ::=  LOOSE_KW. { A = AVPL_LOOSE; }
351
352 action_mode(A) ::= REPLACE_KW. { A = AVPL_REPLACE; }
353 action_mode(A) ::= INSERT_KW. { A = AVPL_INSERT; }
354
355 /******************************************* PDU
356 */
357
358 pdu_decl ::= PDU_KW NAME(NAME) PROTO_KW field(FIELD) TRANSPORT_KW proto_stack(STACK) pdu_setup(SETUP) SEMICOLON. {
359         mate_cfg_pdu* cfg  = new_pducfg(NAME);
360         extraction_t *extraction, *next_extraction;
361         GPtrArray* transport_stack = g_ptr_array_new();
362         int i;
363         
364         if (! cfg ) configuration_error(mc,"could not create Pdu %s.",NAME);
365
366         cfg->hfid_proto = FIELD->id;
367
368         cfg->last_extracted = (SETUP->flags) ? SETUP->flags->last_extracted : mc->defaults.pdu.last_extracted;
369         cfg->discard = (SETUP->flags) ? SETUP->flags->discard : mc->defaults.pdu.discard;
370         cfg->drop_unassigned = (SETUP->flags) ? SETUP->flags->drop_unassigned : mc->defaults.pdu.drop_unassigned;
371         
372         g_string_sprintfa(mc->protos_filter,"||%s",FIELD->abbrev);
373
374         /* flip the transport_stack */
375         for (i = STACK->len - 1; STACK->len; i--) {
376                 g_ptr_array_add(transport_stack,g_ptr_array_remove_index(STACK,i));
377         }
378         
379         g_ptr_array_free(STACK,FALSE);
380         
381         cfg->transport_ranges = transport_stack;
382         cfg->payload_ranges = SETUP->payload;
383         
384         if (SETUP->criteria) {
385                 cfg->criterium = SETUP->criteria->criterium_avpl;
386                 cfg->criterium_match_mode = SETUP->criteria->criterium_match_mode;
387                 cfg->criterium_accept_mode = SETUP->criteria->criterium_accept_mode;
388         }
389         
390         cfg->transforms = SETUP->transforms ? SETUP->transforms : g_ptr_array_new();
391         
392         for (extraction = SETUP->extraction; extraction; extraction = next_extraction) {
393                 next_extraction = extraction->next;
394                 
395                 if ( ! add_hfid(extraction->hfi, extraction->as, cfg->hfids_attr) ) {
396                         configuration_error(mc,"MATE: failed to create extraction rule '%s'",extraction->as);
397                 }
398                 
399                 g_free(extraction);
400         }
401 }
402
403 pdu_setup(A) ::= OPEN_BRACE pdu_statements(B) CLOSE_BRACE. { A = B; }
404
405
406 pdu_statements(A) ::=  payload_statement(B) pdu_flag_statements(C) extraction_statements(D) pdu_criteria_statement(E) transform_list_statement(F). { A = do_pdu_statements(B,C,D,E,F); }
407 pdu_statements(A) ::=  payload_statement(B) pdu_flag_statements(C) extraction_statements(D) pdu_criteria_statement(E). { A = do_pdu_statements(B,C,D,E,NULL); }
408 pdu_statements(A) ::=  payload_statement(B) pdu_flag_statements(C) extraction_statements(D) transform_list_statement(F). { A = do_pdu_statements(B,C,D,NULL,F); }
409 pdu_statements(A) ::=  payload_statement(B) pdu_flag_statements(C) extraction_statements(D). { A = do_pdu_statements(B,C,D,NULL,NULL); }
410 pdu_statements(A) ::=  payload_statement(B) extraction_statements(D) pdu_criteria_statement(E) transform_list_statement(F). { A = do_pdu_statements(B,NULL,D,E,F); }
411 pdu_statements(A) ::=  payload_statement(B) extraction_statements(D) pdu_criteria_statement(E). { A = do_pdu_statements(B,NULL,D,E,NULL); }
412 pdu_statements(A) ::=  payload_statement(B) extraction_statements(D) transform_list_statement(F). { A = do_pdu_statements(B,NULL,D,NULL,F); }
413 pdu_statements(A) ::=  payload_statement(B) extraction_statements(D). { A = do_pdu_statements(B,NULL,D,NULL,NULL); }
414 pdu_statements(A) ::=  pdu_flag_statements(C) extraction_statements(D) pdu_criteria_statement(E) transform_list_statement(F).  { A = do_pdu_statements(NULL,C,D,E,F); }
415 pdu_statements(A) ::=  pdu_flag_statements(C) extraction_statements(D) pdu_criteria_statement(E).  { A = do_pdu_statements(NULL,C,D,E,NULL); }
416 pdu_statements(A) ::=  pdu_flag_statements(C) extraction_statements(D) transform_list_statement(F).  { A = do_pdu_statements(NULL,C,D,NULL,F); }
417 pdu_statements(A) ::=  pdu_flag_statements(C) extraction_statements(D).  { A = do_pdu_statements(NULL,C,D,NULL,NULL); }
418 pdu_statements(A) ::=  extraction_statements(D) pdu_criteria_statement(E) transform_list_statement(F).  { A = do_pdu_statements(NULL,NULL,D,E,F); }
419 pdu_statements(A) ::=  extraction_statements(D) pdu_criteria_statement(E).  { A = do_pdu_statements(NULL,NULL,D,E,NULL); }
420 pdu_statements(A) ::=  extraction_statements(D) transform_list_statement(F).  { A = do_pdu_statements(NULL,NULL,D,NULL,F); }
421 pdu_statements(A) ::=  extraction_statements(D). { A = do_pdu_statements(NULL,NULL,D,NULL,NULL); }
422
423 pdu_flag_statements(A) ::= drop_unassigned_statement(B) discard_pdu_data_statement(C) last_extracted_statement(D). {
424         A = g_malloc(sizeof(pdu_flags_t));
425         
426         A->drop_unassigned = B;
427         A->discard = C;
428         A->last_extracted = D;
429 }
430
431 pdu_flag_statements(A) ::= drop_unassigned_statement(B) discard_pdu_data_statement(C). {
432         A = g_malloc(sizeof(pdu_flags_t));
433         
434         A->drop_unassigned = B;
435         A->discard = C;
436         A->last_extracted = mc->defaults.pdu.last_extracted;
437 }
438
439 pdu_flag_statements(A) ::= drop_unassigned_statement(B) last_extracted_statement(D). {
440         A = g_malloc(sizeof(pdu_flags_t));
441         
442         A->drop_unassigned = B;
443         A->discard = mc->defaults.pdu.discard;
444         A->last_extracted = D;
445 }
446
447 pdu_flag_statements(A) ::= discard_pdu_data_statement(C) last_extracted_statement(D). {
448         A = g_malloc(sizeof(pdu_flags_t));
449         
450         A->drop_unassigned = mc->defaults.pdu.drop_unassigned;
451         A->discard = C;
452         A->last_extracted = D;
453 }
454
455 pdu_flag_statements(A) ::= last_extracted_statement(D). {
456         A = g_malloc(sizeof(pdu_flags_t));
457         
458         A->drop_unassigned = mc->defaults.pdu.drop_unassigned;
459         A->discard = mc->defaults.pdu.discard;
460         A->last_extracted = D;
461 }
462
463 pdu_flag_statements(A) ::= discard_pdu_data_statement(C). {
464         A = g_malloc(sizeof(pdu_flags_t));
465         
466         A->drop_unassigned = mc->defaults.pdu.drop_unassigned;
467         A->discard = C;
468         A->last_extracted = mc->defaults.pdu.last_extracted;
469 }
470
471 pdu_flag_statements(A) ::= drop_unassigned_statement(B). {
472         A = g_malloc(sizeof(pdu_flags_t));
473         
474         A->drop_unassigned = B;
475         A->discard = mc->defaults.pdu.discard;
476         A->last_extracted = mc->defaults.pdu.last_extracted;
477 }
478
479
480 payload_statement(A) ::= PAYLOAD_KW proto_stack(B) SEMICOLON. { A = B; }
481
482 pdu_criteria_statement(A) ::= CRITERIA_KW accept_mode(B) match_mode(C) avpl(D) SEMICOLON. {
483         A = g_malloc(sizeof(pdu_criteria_t));
484         A->criterium_avpl = D;
485         A->criterium_match_mode = C;
486         A->criterium_accept_mode = B;
487 }
488
489 accept_mode(A) ::= ACCEPT_KW. { A = ACCEPT_MODE; }
490 accept_mode(A) ::= REJECT_KW. { A = REJECT_MODE; }
491
492 extraction_statements(A) ::= extraction_statements(B) extraction_statement(C). {
493         A = B;
494         A->last->next = C;
495         A->last = C;
496 }
497
498 extraction_statements(A) ::= extraction_statement(B). {
499         A = B;
500         A->last = A;
501 }
502
503 extraction_statement(A) ::= EXTRACT_KW NAME(NAME) FROM_KW field(FIELD) SEMICOLON. {
504         A = g_malloc(sizeof(extraction_t));
505         A->as = NAME;
506         A->hfi = FIELD;
507         A->next = A->last = NULL;
508 }
509
510
511 drop_unassigned_statement(A) ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { A = B; } 
512
513 discard_pdu_data_statement(A) ::=  DISCARD_PDU_DATA_KW true_false(B) SEMICOLON. { A = B; }  
514
515 last_extracted_statement(A) ::= LAST_PDU_KW true_false(B) SEMICOLON. { A = B; }  
516
517 proto_stack(A) ::= proto_stack(B) SLASH field(C). {
518         int* hfidp = g_malloc(sizeof(int));
519
520         g_string_sprintfa(mc->fields_filter,"||%s",C->abbrev);
521         
522         *hfidp = C->id;
523         g_ptr_array_add(B,hfidp);
524         A = B;
525 }
526
527 proto_stack(A) ::= field(B). {
528         int* hfidp = g_malloc(sizeof(int));
529         *hfidp = B->id;
530         
531         g_string_sprintfa(mc->fields_filter,"||%s",B->abbrev);
532
533         A = g_ptr_array_new();
534         g_ptr_array_add(A,hfidp);
535 }
536
537 field(A) ::= NAME(B). {
538         A = proto_registrar_get_byname(B);
539 }
540
541
542
543 /******************************************* GOP
544 */
545
546 gop_decl(A) ::= GOP_KW NAME(B) ON_KW pdu_name(C) MATCH_KW avpl(D) gop_setup(E) SEMICOLON. {
547         mate_cfg_gop* cfg;
548         
549         if (g_hash_table_lookup(mc->gopcfgs,B)) configuration_error(mc,"A Gop Named '%s' exists already.",B);
550         if (g_hash_table_lookup(mc->gops_by_pduname,C) ) configuration_error(mc,"Gop for Pdu '%s' exists already",C);
551
552         cfg = new_gopcfg(B);
553         g_hash_table_insert(mc->gops_by_pduname,C,cfg);
554         g_hash_table_insert(mc->gopcfgs,cfg->name,cfg);
555         cfg->on_pdu = C;
556
557         cfg->drop_unassigned = (E->options && E->options->tree_sts) ? E->options->tree_sts->drop_unassigned : mc->defaults.gop.drop_unassigned;
558         cfg->show_times = (E->options && E->options->tree_sts) ? E->options->tree_sts->show_times : mc->defaults.gop.show_times;
559         cfg->pdu_tree_mode = (E->options && E->options->tree_sts) ? E->options->tree_sts->pdu_tree_mode : mc->defaults.gop.pdu_tree_mode;
560         
561         cfg->expiration = (E->options && E->options->timer_sts) ? E->options->timer_sts->expiration : mc->defaults.gop.expiration;
562         cfg->idle_timeout = (E->options && E->options->timer_sts) ? E->options->timer_sts->idle_timeout : mc->defaults.gop.idle_timeout;
563         cfg->lifetime = (E->options && E->options->timer_sts) ? E->options->timer_sts->lifetime : mc->defaults.gop.lifetime;
564         
565         cfg->start = E->control ? E->control->start : NULL;
566         cfg->stop = E->control ? E->control->stop : NULL;
567         cfg->key = D;
568         
569         cfg->transforms = (E->transforms) ? E->transforms : g_ptr_array_new();
570         
571         if (E->control && E->control->extras) {
572                 merge_avpl(cfg->extra,E->control->extras,TRUE);
573                 delete_avpl(E->control->extras,TRUE);
574         }
575         
576         if (E->control) g_free(E->control);
577         
578         if (E->options) {
579                 if (E->options->tree_sts) g_free(E->options->tree_sts);
580                 if (E->options->timer_sts) g_free(E->options->timer_sts);
581                 if (E->options) g_free(E->options);
582         }
583         
584         g_free(E);
585 }
586
587
588 gop_decl(A) ::= GOP_KW NAME(B) ON_KW pdu_name(C) MATCH_KW avpl(D) SEMICOLON. {
589         mate_cfg_gop* cfg;
590         
591         if (g_hash_table_lookup(mc->gopcfgs,B)) configuration_error(mc,"A Gop Named '%s' exists already.",B);
592         if (g_hash_table_lookup(mc->gops_by_pduname,C) ) configuration_error(mc,"Gop for Pdu '%s' exists already",C);
593         
594         cfg = new_gopcfg(B);
595         g_hash_table_insert(mc->gops_by_pduname,C,cfg);
596         g_hash_table_insert(mc->gopcfgs,cfg->name,cfg);
597         
598         cfg->drop_unassigned =  mc->defaults.gop.drop_unassigned;
599         cfg->show_times = mc->defaults.gop.show_times;
600         cfg->pdu_tree_mode = mc->defaults.gop.pdu_tree_mode;
601         
602         cfg->expiration = mc->defaults.gop.expiration;
603         cfg->idle_timeout = mc->defaults.gop.idle_timeout;
604         cfg->lifetime = mc->defaults.gop.lifetime;
605         
606         cfg->start = NULL;
607         cfg->stop = NULL;
608         cfg->key = D;
609         
610         cfg->transforms = g_ptr_array_new();
611 }
612
613 gop_setup(A) ::= OPEN_BRACE gop_statements(B) CLOSE_BRACE. {
614         A = B;
615 }
616
617 gop_statements(A) ::= gop_control_statements(B) gop_option_statements(C) transform_list_statement(E). {
618   A = g_malloc(sizeof(gop_statement));
619   
620   A->control = B;
621   A->options = C;
622   A->transforms = E;
623 }
624
625 gop_statements(A) ::= gop_option_statements(C) transform_list_statement(E). {
626   A = g_malloc(sizeof(gop_statement));
627   
628   A->control = NULL;
629   A->options = C;
630   A->transforms = E;
631 }
632
633 gop_statements(A) ::= gop_control_statements(B) transform_list_statement(E). {
634   A = g_malloc(sizeof(gop_statement));
635   
636   A->control = B;
637   A->options = NULL;
638   A->transforms = E;
639 }
640
641 gop_statements(A) ::= gop_control_statements(B) gop_option_statements(C). {
642   A = g_malloc(sizeof(gop_statement));
643   
644   A->control = B;
645   A->options = C;
646   A->transforms = NULL;
647 }
648
649
650 gop_statements(A) ::= gop_option_statements(C). {
651   A = g_malloc(sizeof(gop_statement));
652   
653   A->control = NULL;
654   A->options = C;
655   A->transforms = NULL;
656 }
657
658 gop_statements(A) ::= gop_control_statements(B). {
659   A = g_malloc(sizeof(gop_statement));
660   
661   A->control = B;
662   A->options = NULL;
663   A->transforms = NULL;
664 }
665
666 gop_statements(A) ::= transform_list_statement(E). {
667   A = g_malloc(sizeof(gop_statement));
668   
669   A->control = NULL;
670   A->options = NULL;
671   A->transforms = E;
672 }
673
674
675
676
677 gop_control_statements(A) ::= gop_start_statement(B) gop_stop_statement(C) extra_statement(D).{
678         A = g_malloc(sizeof(gop_control_statement));
679         
680         A->start = B;
681         A->stop = C;
682     A->extras = D;
683 }
684
685
686 gop_control_statements(A) ::= gop_stop_statement(C) extra_statement(D).{
687         A = g_malloc(sizeof(gop_control_statement));
688         
689         A->start = NULL;
690         A->stop = C;
691     A->extras = D;
692 }
693
694 gop_control_statements(A) ::= gop_start_statement(B) extra_statement(D).{
695         A = g_malloc(sizeof(gop_control_statement));
696         
697         A->start = B;
698         A->stop = NULL;
699     A->extras = D;
700 }
701
702 gop_control_statements(A) ::= gop_start_statement(B) gop_stop_statement(C).{
703         A = g_malloc(sizeof(gop_control_statement));
704         
705         A->start = B;
706         A->stop = C;
707     A->extras = NULL;
708 }
709
710
711 gop_control_statements(A) ::= gop_start_statement(B).{
712         A = g_malloc(sizeof(gop_control_statement));
713         
714         A->start = B;
715         A->stop = NULL;
716     A->extras = NULL;
717 }
718
719 gop_control_statements(A) ::= gop_stop_statement(C).{
720         A = g_malloc(sizeof(gop_control_statement));
721         
722         A->start = NULL;
723         A->stop = C;
724     A->extras = NULL;
725 }
726
727 gop_control_statements(A) ::= extra_statement(D). {
728         A = g_malloc(sizeof(gop_control_statement));
729         
730         A->start = NULL;
731         A->stop = NULL;
732     A->extras = D;
733 }
734
735
736
737
738 gop_option_statements(A) ::= gop_timer_statements(B) gop_tree_statements(C). {
739         A = g_malloc(sizeof(gop_control_statement));
740         
741         A->timer_sts = B;
742         A->tree_sts = C;
743 }
744
745 gop_option_statements(A) ::= gop_timer_statements(B). {
746         A = g_malloc(sizeof(gop_timer_statement));
747         
748         A->timer_sts = B;
749         A->tree_sts = NULL;
750
751 }
752
753 gop_option_statements(A) ::= gop_tree_statements(C). {
754         A = g_malloc(sizeof(gop_timer_statement));
755         
756         A->tree_sts = C;
757         A->timer_sts =  NULL;
758
759 }
760
761
762
763 gop_timer_statements(A) ::= expiration_statement(B) idle_timeout_statement(C) lifetime_statement(D).  {
764         A = g_malloc(sizeof(gop_timer_statement));
765         
766         A->expiration = B;
767         A->idle_timeout = C;
768         A->lifetime = D;
769 }
770
771
772 gop_timer_statements(A) ::= expiration_statement(B) idle_timeout_statement(C). {
773         A = g_malloc(sizeof(gop_timer_statement));
774         
775         A->expiration = B;
776         A->idle_timeout = C;
777         A->lifetime = mc->defaults.gop.lifetime;
778 }
779
780 gop_timer_statements(A) ::= expiration_statement(B) lifetime_statement(D). {
781         A = g_malloc(sizeof(gop_timer_statement));
782         
783         A->expiration = B;
784         A->idle_timeout = mc->defaults.gop.lifetime;
785         A->lifetime = D;
786 }
787
788 gop_timer_statements(A) ::= idle_timeout_statement(C) lifetime_statement(D). {
789         A = g_malloc(sizeof(gop_timer_statement));
790         
791         A->expiration = mc->defaults.gop.lifetime;
792         A->idle_timeout = C;
793         A->lifetime = D;
794 }
795
796 gop_timer_statements(A) ::= expiration_statement(B). {
797         A = g_malloc(sizeof(gop_timer_statement));
798         
799         A->expiration = B;
800         A->idle_timeout = mc->defaults.gop.lifetime;
801         A->lifetime = mc->defaults.gop.lifetime;
802 }
803
804 gop_timer_statements(A) ::= idle_timeout_statement(C). {
805         A = g_malloc(sizeof(gop_timer_statement));
806         
807         A->expiration = mc->defaults.gop.lifetime;
808         A->idle_timeout = C;
809         A->lifetime = mc->defaults.gop.lifetime;
810 }
811
812 gop_timer_statements(A) ::= lifetime_statement(D). {
813         A = g_malloc(sizeof(gop_timer_statement));
814         
815         A->expiration = mc->defaults.gop.lifetime;
816         A->idle_timeout = mc->defaults.gop.lifetime;
817         A->lifetime = D;
818 }
819
820
821
822
823 gop_tree_statements(A) ::= drop_unassigned_statement(B) show_goptree_statement(C) show_times_statement(D). {
824         A = g_malloc(sizeof(gop_tree_statement));
825         
826         A->drop_unassigned = B;
827         A->pdu_tree_mode = C;
828         A->show_times = D;
829 }
830
831 gop_tree_statements(A) ::= drop_unassigned_statement(B) show_goptree_statement(C). {
832         A = g_malloc(sizeof(gop_tree_statement));
833         
834         A->drop_unassigned = B;
835         A->pdu_tree_mode = C;
836         A->show_times = mc->defaults.gop.show_times;
837 }
838
839 gop_tree_statements(A) ::= drop_unassigned_statement(B) show_times_statement(D). {
840         A = g_malloc(sizeof(gop_tree_statement));
841         
842         A->drop_unassigned = B;
843         A->pdu_tree_mode = mc->defaults.gop.pdu_tree_mode;
844         A->show_times = D;
845 }
846
847 gop_tree_statements(A) ::= show_goptree_statement(C) show_times_statement(D). {
848         A = g_malloc(sizeof(gop_tree_statement));
849         
850         A->drop_unassigned = mc->defaults.gop.drop_unassigned;
851         A->pdu_tree_mode = C;
852         A->show_times = D;
853 }
854
855 gop_tree_statements(A) ::= drop_unassigned_statement(B). {
856         A = g_malloc(sizeof(gop_tree_statement));
857         
858         A->drop_unassigned = B;
859         A->pdu_tree_mode = mc->defaults.gop.pdu_tree_mode;
860         A->show_times = mc->defaults.gop.show_times;
861 }
862
863 gop_tree_statements(A) ::= show_goptree_statement(C).  {
864         A = g_malloc(sizeof(gop_tree_statement));
865         
866         A->drop_unassigned = mc->defaults.gop.drop_unassigned;
867         A->pdu_tree_mode = C;
868         A->show_times = mc->defaults.gop.show_times;
869 }
870
871 gop_tree_statements(A) ::= show_times_statement(D). {
872         A = g_malloc(sizeof(gop_tree_statement));
873         
874         A->drop_unassigned = mc->defaults.gop.drop_unassigned;
875         A->pdu_tree_mode = mc->defaults.gop.pdu_tree_mode;
876         A->show_times = D;
877 }
878
879
880 gop_start_statement(A) ::= START_KW avpl(B) SEMICOLON. { A = B; }
881
882 gop_stop_statement(A) ::= STOP_KW avpl(B) SEMICOLON. { A = B; }
883
884 show_goptree_statement(A) ::= SHOW_TREE_KW gop_tree_mode(B) SEMICOLON. { A = B; }
885
886 show_times_statement(A) ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { A = B; }
887
888 expiration_statement(A) ::= EXPIRATION_KW time_value(B) SEMICOLON. { A = B; }
889
890 idle_timeout_statement(A) ::= IDLE_TIMEOUT_KW time_value(B) SEMICOLON. { A = B; }
891
892 lifetime_statement(A) ::= LIFETIME_KW time_value(B) SEMICOLON. { A = B; }
893
894 gop_tree_mode(A) ::= NO_TREE_KW.    { A = GOP_NO_TREE; }
895 gop_tree_mode(A) ::= PDU_TREE_KW.   { A = GOP_PDU_TREE; }
896 gop_tree_mode(A) ::= FRAME_TREE_KW. { A = GOP_FRAME_TREE; }
897 gop_tree_mode(A) ::= BASIC_TREE_KW. { A = GOP_BASIC_PDU_TREE; }
898
899 true_false(A) ::= TRUE_KW. { A = TRUE; }
900 true_false(A) ::= FALSE_KW. { A = FALSE; }
901
902 pdu_name(A) ::= NAME(B). {
903         mate_cfg_pdu* c;
904         if (( c =  g_hash_table_lookup(mc->pducfgs,B) )) {
905                 A = c->name;
906         } else {
907                 configuration_error(mc,"No such Pdu: '%s'",B);
908         }
909 }
910
911
912 time_value(A) ::= FLOATING(B). {
913         A = (float) strtod(B,NULL);
914 }
915
916 time_value(A) ::= INTEGER(B). {
917         A = (float) strtod(B,NULL);
918 }
919
920 /************* GOG
921 */
922
923 gog_decl ::= GOG_KW NAME(A) OPEN_BRACE gog_statements(B) CLOSE_BRACE SEMICOLON. {
924         mate_cfg_gog* cfg = NULL;
925         
926         if ( g_hash_table_lookup(mc->gogcfgs,A) ) {
927                 configuration_error(mc,"Gog '%s' exists already ",A);
928         }
929         
930         cfg = new_gogcfg(A);
931
932         cfg->expiration = B->expiration;
933         cfg->gop_tree_mode = B->gop_tree_mode;
934         cfg->transforms = B->transform_list ? B->transform_list : g_ptr_array_new();
935         cfg->keys = B->current_gogkeys;
936         
937         if (B->extras) {
938                 merge_avpl(cfg->extra,B->extras,TRUE);
939                 delete_avpl(B->extras,TRUE);
940         }
941         
942         g_free(B);
943 }
944
945 gog_statements(A) ::= expiration_statement(B) gog_goptree_statement(C) gog_key_statements(D) extra_statement(E) transform_list_statement(F). {
946         A = g_malloc(sizeof(gog_statement_t));
947         
948         A->expiration = B;
949         A->gop_tree_mode = C;
950         A->current_gogkeys = D;
951         A->extras = E;
952         A->transform_list = F;
953 }
954
955 gog_statements(A) ::= expiration_statement(B) gog_goptree_statement(C) gog_key_statements(D) transform_list_statement(F). {
956         A = g_malloc(sizeof(gog_statement_t));
957         
958         A->expiration = B;
959         A->gop_tree_mode = C;
960         A->current_gogkeys = D;
961         A->extras = new_avpl("");
962         A->transform_list = F;
963 }
964
965 gog_statements(A) ::= expiration_statement(B) gog_key_statements(D) extra_statement(E) transform_list_statement(F). {
966         A = g_malloc(sizeof(gog_statement_t));
967         
968         A->expiration = B;
969         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
970         A->current_gogkeys = D;
971         A->extras = E;
972         A->transform_list = F;
973 }
974
975 gog_statements(A) ::= expiration_statement(B) gog_key_statements(D) transform_list_statement(F). {
976         A = g_malloc(sizeof(gog_statement_t));
977         
978         A->expiration = B;
979         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
980         A->current_gogkeys = D;
981         A->extras = new_avpl("");
982         A->transform_list = F;
983 }
984
985 gog_statements(A) ::= gog_goptree_statement(C) gog_key_statements(D) extra_statement(E) transform_list_statement(F).  {
986         A = g_malloc(sizeof(gog_statement_t));
987         
988         A->expiration = mc->defaults.gog.expiration;
989         A->gop_tree_mode = C;
990         A->current_gogkeys = D;
991         A->extras = E;
992         A->transform_list = F;
993 }
994
995 gog_statements(A) ::= gog_goptree_statement(C) gog_key_statements(D) transform_list_statement(F).  {
996         A = g_malloc(sizeof(gog_statement_t));
997         
998         A->expiration = mc->defaults.gog.expiration;
999         A->gop_tree_mode = C;
1000         A->current_gogkeys = D;
1001         A->extras = new_avpl("");
1002         A->transform_list = F;
1003 }
1004
1005 gog_statements(A) ::= gog_key_statements(D) extra_statement(E) transform_list_statement(F). {
1006         A = g_malloc(sizeof(gog_statement_t));
1007         
1008         A->expiration = mc->defaults.gog.expiration;
1009         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1010         A->current_gogkeys = D;
1011         A->extras = E;
1012         A->transform_list = F;
1013 }
1014
1015 gog_statements(A) ::= gog_key_statements(D) transform_list_statement(F). {
1016         A = g_malloc(sizeof(gog_statement_t));
1017         
1018         A->expiration = mc->defaults.gog.expiration;
1019         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1020         A->current_gogkeys = D;
1021         A->extras = new_avpl("");
1022         A->transform_list = F;
1023 }
1024
1025
1026 gog_statements(A) ::= expiration_statement(B) gog_goptree_statement(C) gog_key_statements(D) extra_statement(E). {
1027         A = g_malloc(sizeof(gog_statement_t));
1028         
1029         A->expiration = B;
1030         A->gop_tree_mode = C;
1031         A->current_gogkeys = D;
1032         A->extras = E;
1033         A->transform_list = NULL;
1034 }
1035
1036 gog_statements(A) ::= expiration_statement(B) gog_goptree_statement(C) gog_key_statements(D). {
1037         A = g_malloc(sizeof(gog_statement_t));
1038         
1039         A->expiration = B;
1040         A->gop_tree_mode = C;
1041         A->current_gogkeys = D;
1042         A->extras = new_avpl("");
1043         A->transform_list = NULL;
1044 }
1045
1046 gog_statements(A) ::= expiration_statement(B) gog_key_statements(D) extra_statement(E).  {
1047         A = g_malloc(sizeof(gog_statement_t));
1048         
1049         A->expiration = B;
1050         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1051         A->current_gogkeys = D;
1052         A->extras = E;
1053         A->transform_list = NULL;
1054 }
1055
1056 gog_statements(A) ::= expiration_statement(B) gog_key_statements(D). {
1057         A = g_malloc(sizeof(gog_statement_t));
1058         
1059         A->expiration = B;
1060         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1061         A->current_gogkeys = D;
1062         A->extras = new_avpl("");
1063         A->transform_list = NULL;
1064 }
1065
1066
1067 gog_statements(A) ::= gog_goptree_statement(C) gog_key_statements(D) extra_statement(E).  {
1068         A = g_malloc(sizeof(gog_statement_t));
1069         
1070         A->expiration = mc->defaults.gog.expiration;
1071         A->gop_tree_mode = C;
1072         A->current_gogkeys = D;
1073         A->extras = E;
1074         A->transform_list = NULL;
1075 }
1076
1077 gog_statements(A) ::= gog_goptree_statement(C) gog_key_statements(D). {
1078         A = g_malloc(sizeof(gog_statement_t));
1079         
1080         A->expiration = mc->defaults.gog.expiration;
1081         A->gop_tree_mode = C;
1082         A->current_gogkeys = D;
1083         A->extras = new_avpl("");
1084         A->transform_list = NULL;
1085 }
1086
1087 gog_statements(A) ::= gog_key_statements(D) extra_statement(E).  {
1088         A = g_malloc(sizeof(gog_statement_t));
1089         
1090         A->expiration = mc->defaults.gog.expiration;
1091         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1092         A->current_gogkeys = D;
1093         A->extras = E;
1094         A->transform_list = NULL;
1095 }
1096
1097 gog_statements(A) ::= gog_key_statements(D). {
1098         A = g_malloc(sizeof(gog_statement_t));
1099         
1100         A->expiration = mc->defaults.gog.expiration;
1101         A->gop_tree_mode = mc->defaults.gog.gop_tree_mode;
1102         A->current_gogkeys = D;
1103         A->extras = new_avpl("");
1104         A->transform_list = NULL;
1105 }
1106
1107 gog_goptree_statement(A) ::= GOP_TREE_KW gop_tree_type(B) SEMICOLON. { A = B; }
1108
1109 gop_tree_type(A) ::= NULL_TREE. { A = GOP_NULL_TREE; }
1110 gop_tree_type(A) ::= FULL_TREE. { A = GOP_FULL_TREE; }
1111 gop_tree_type(A) ::= BASIC_TREE. { A = GOP_BASIC_TREE; }
1112
1113
1114 gog_key_statements(A) ::= gog_key_statements(B) gog_key_statement(C). {
1115         loal_append(B,C);
1116         A = B;
1117 }
1118
1119 gog_key_statements(A) ::= gog_key_statement(B). {
1120         A = new_loal("");
1121         loal_append(A,B);
1122 }
1123
1124
1125 gog_key_statement(A) ::= MEMBER_KW gop_name(B) avpl(C) SEMICOLON. {
1126         rename_avpl(C,B);
1127         A = C;
1128 }
1129
1130 gop_name(A) ::= NAME(B). {
1131         mate_cfg_gop* c;
1132         if (( c = g_hash_table_lookup(mc->gopcfgs,B) )) {
1133                 A = c->name;
1134         } else {
1135                 configuration_error(mc,"No Gop called '%s' has been already declared",B);
1136         }
1137 }
1138 /******************************************** GENERAL
1139 */
1140
1141
1142 extra_statement(A) ::= EXTRA_KW avpl(B) SEMICOLON. { A = B; }
1143
1144 transform_list_statement(A) ::= TRANSFORM_KW transform_list(B) SEMICOLON. { A = B; }
1145
1146 transform_list(A) ::= transform_list(B) COMMA transform(C). { 
1147         A = B;
1148         g_ptr_array_add(B,C);
1149 }
1150
1151 transform_list(A) ::= transform(B). {
1152         A = g_ptr_array_new();
1153         g_ptr_array_add(A,B);
1154 }
1155
1156 transform(A) ::= NAME(B). {
1157         AVPL_Transf* t;
1158         
1159         if (( t = g_hash_table_lookup(mc->transfs,B) )) {
1160                 A = t;
1161         } else {
1162                 configuration_error(mc,"There's no such Transformation: %s",B);
1163         }       
1164 }
1165
1166 avpl(A) ::= OPEN_PARENS avps(B) CLOSE_PARENS. { A = B; }
1167 avpl(A) ::= OPEN_PARENS CLOSE_PARENS. { A = new_avpl(""); }
1168
1169 avps(A) ::= avps(B) COMMA avp(C). { A = B; if ( ! insert_avp(B,C) ) delete_avp(C); }
1170 avps(A) ::= avp(B). { A = new_avpl(""); if ( ! insert_avp(A,B) ) delete_avp(B); }
1171
1172 avp(A) ::= NAME(B) AVP_OPERATOR(C) value(D). { A = new_avp(B,D,*C); }
1173 avp(A) ::= NAME(B). { A = new_avp(B,"",'?'); }
1174 avp(A) ::= NAME(B) OPEN_BRACE avp_oneoff(C) CLOSE_BRACE. { A = new_avp(B,C,'|'); }
1175
1176 avp_oneoff(A) ::= avp_oneoff(B) PIPE value(C). { A = g_strdup_printf("%s|%s",B,C); } 
1177 avp_oneoff(A) ::= value(B). { A = g_strdup(B); }
1178
1179 value(A) ::= QUOTED(B). { A = g_strdup(B); }
1180 value(A) ::= NAME(B). { A = g_strdup(B); }
1181 value(A) ::= FLOATING(B). { A = g_strdup(B); }
1182 value(A) ::= INTEGER(B). { A = g_strdup(B); }
1183 value(A) ::= DOTED_IP(B). { A = g_strdup(B); }
1184 value(A) ::= COLONIZED(B). { A = recolonize(mc,B); }
1185