| %include { |
| |
| /* mate_grammar.lemon |
| * MATE's configuration language grammar |
| * |
| * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com> |
| * |
| * $Id: mate_grammar.lemon 23221 2007-10-17 21:25:16Z morriss $ |
| * |
| * Wireshark - Network traffic analyzer |
| * By Gerald Combs <gerald@wireshark.org> |
| * Copyright 1998 Gerald Combs |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| */ |
| |
| #include "mate.h" |
| #include "mate_grammar.h" |
| #include <epan/ws_strsplit.h> |
| #include <wiretap/file_util.h> |
| |
| #define DUMMY void* |
| |
| typedef struct _extraction { |
| gchar* as; |
| header_field_info* hfi; |
| struct _extraction* next; |
| struct _extraction* last; |
| } extraction_t; |
| |
| typedef struct _pdu_criteria_t { |
| AVPL* criterium_avpl; |
| avpl_match_mode criterium_match_mode; |
| accept_mode_t criterium_accept_mode; |
| } pdu_criteria_t; |
| |
| typedef struct _gop_options { |
| gop_tree_mode_t pdu_tree_mode; |
| gboolean drop_unassigned; |
| gboolean show_times; |
| float expiration; |
| float idle_timeout; |
| float lifetime; |
| AVPL* start; |
| AVPL* stop; |
| AVPL* extras; |
| } gop_options_t; |
| |
| typedef struct _gog_statements { |
| float expiration; |
| gop_tree_mode_t gop_tree_mode; |
| GPtrArray* transform_list; |
| AVPL* extras; |
| LoAL* current_gogkeys; |
| } gog_statement_t; |
| |
| typedef struct _transf_match_t { |
| avpl_match_mode match_mode; |
| AVPL* avpl; |
| } transf_match_t; |
| |
| typedef struct _transf_action_t { |
| avpl_replace_mode replace_mode; |
| AVPL* avpl; |
| } transf_action_t; |
| |
| static void configuration_error(mate_config* mc, const gchar* fmt, ...) { |
| static gchar error_buffer[256]; |
| const gchar* incl; |
| gint i; |
| mate_config_frame* current_frame; |
| va_list list; |
| |
| va_start( list, fmt ); |
| g_vsnprintf(error_buffer,sizeof(error_buffer),fmt,list); |
| va_end( list ); |
| |
| i = (gint) mc->config_stack->len; |
| |
| while (i--) { |
| |
| if (i>0) { |
| incl = "\n included from: "; |
| } else { |
| incl = " "; |
| } |
| |
| current_frame = g_ptr_array_index(mc->config_stack,(guint)i); |
| |
| g_string_sprintfa(mc->config_error,"%s%s at line %u",incl, current_frame->filename, current_frame->linenum); |
| } |
| |
| g_string_sprintfa(mc->config_error,": %s\n",error_buffer); |
| |
| THROW(MateConfigError); |
| |
| } |
| |
| static AVPL_Transf* new_transform_elem(AVPL* match, AVPL* replace, avpl_match_mode match_mode, avpl_replace_mode replace_mode) { |
| AVPL_Transf* t = g_malloc(sizeof(AVPL_Transf)); |
| |
| t->name = NULL; |
| t->match = match; |
| t->replace = replace; |
| t->match_mode = match_mode; |
| t->replace_mode = replace_mode; |
| |
| t->map = NULL; |
| t->next = NULL; |
| |
| return t; |
| } |
| |
| static gchar* recolonize(mate_config* mc, gchar* s) { |
| GString* str = g_string_new(""); |
| gchar** vec; |
| gchar* r; |
| guint i,v; |
| gchar c; |
| |
| vec = g_strsplit(s,":",0); |
| |
| for (i = 0; vec[i]; i++) { |
| g_strdown(vec[i]); |
| |
| v = 0; |
| switch ( strlen(vec[i]) ) { |
| case 2: |
| c = vec[i][1]; |
| vec[i][1] = vec[i][0]; |
| vec[i][0] = c; |
| if (vec[i][0] >= '0' && vec[i][0] <= '9') { |
| v += (vec[i][1] - '0' )*16; |
| } else { |
| v += (vec[i][1] - 'a' + 10)*16; |
| } |
| case 1: |
| if (vec[i][0] >= '0' && vec[i][0] <= '9') { |
| v += (vec[i][0] - '0' ); |
| } else { |
| v += (vec[i][0] - 'a' + 10); |
| } |
| case 0: |
| break; |
| default: |
| configuration_error(mc,"bad token %s",s); |
| } |
| |
| g_string_sprintfa(str,":%.2X",v); |
| } |
| |
| g_strfreev(vec); |
| |
| g_string_erase(str,0,1); |
| |
| r = str->str; |
| |
| g_string_free(str,FALSE); |
| |
| return r; |
| } |
| |
| } |
| |
| %name MateParser |
| |
| %token_prefix TOKEN_ |
| |
| %token_type { gchar* } |
| %token_destructor { if ($$) g_free($$); } |
| |
| %extra_argument { mate_config* mc } |
| |
| %syntax_error { |
| configuration_error(mc,"Syntax Error before %s",yyminor); |
| } |
| |
| %parse_failure { |
| configuration_error(mc,"Parse Error"); |
| } |
| |
| %type transform_decl { AVPL_Transf* } |
| %type transform_body { AVPL_Transf* } |
| %type transform_statements { AVPL_Transf* } |
| %type transform_statement { AVPL_Transf* } |
| %type transform_match { transf_match_t* } |
| %type transform_action { transf_action_t* } |
| %type match_mode { avpl_match_mode } |
| %type action_mode { avpl_replace_mode } |
| |
| %type gop_name { gchar* } |
| %type time_value { float } |
| %type pdu_name { gchar* } |
| %type gop_tree_mode { gop_tree_mode_t } |
| %type true_false { gboolean } |
| |
| %type criteria_statement { pdu_criteria_t* } |
| %type accept_mode { accept_mode_t } |
| %type pdu_drop_unassigned_statement { gboolean } |
| %type discard_pdu_data_statement { gboolean } |
| %type last_extracted_statement { gboolean } |
| |
| %type extraction_statement {extraction_t*} |
| %type extraction_statements {extraction_t*} |
| |
| %type gop_options { gop_options_t* } |
| |
| %type gop_start_statement { AVPL* } |
| %type gop_stop_statement { AVPL* } |
| %type extra_statement { AVPL* } |
| %type gop_drop_unassigned_statement { gboolean } |
| %type show_goptree_statement { gop_tree_mode_t } |
| %type show_times_statement { gboolean } |
| %type gop_expiration_statement { float } |
| %type idle_timeout_statement { float } |
| %type lifetime_statement { float } |
| |
| %type gog_statements { gog_statement_t* } |
| %type gog_expiration_statement { float } |
| %type gog_goptree_statement { gop_tree_mode_t } |
| %type gog_key_statements { LoAL* } |
| %type gog_key_statement { AVPL* } |
| %type transform_list_statement { GPtrArray* } |
| %type transform { AVPL_Transf* } |
| %type gop_tree_type { gop_tree_mode_t } |
| |
| %type payload_statement { GPtrArray* } |
| %type proto_stack { GPtrArray* } |
| %type field { header_field_info* } |
| %type transform_list { GPtrArray* } |
| %type avpl { AVPL* } |
| %type avps { AVPL* } |
| %type avp { AVP* } |
| %type value { gchar* } |
| %type avp_oneoff { gchar* } |
| |
| |
| mate_config ::= decls. |
| |
| decls ::= decls decl. |
| decls ::= . |
| |
| decl ::= pdu_decl. |
| decl ::= gop_decl. |
| decl ::= gog_decl. |
| decl ::= transform_decl. |
| decl ::= defaults_decl. |
| decl ::= debug_decl. |
| decl ::= DONE_KW SEMICOLON. |
| |
| /************* DEBUG |
| */ |
| |
| debug_decl ::= DEBUG_KW OPEN_BRACE dbgfile_default dbglevel_default pdu_dbglevel_default gop_dbglevel_default gog_dbglevel_default CLOSE_BRACE SEMICOLON. |
| |
| dbgfile_default ::= FILENAME_KW QUOTED(Filename) SEMICOLON. { mc->dbg_facility = eth_fopen(Filename,"w"); if (mc->dbg_facility == NULL) report_open_failure(Filename,errno,TRUE); } |
| dbgfile_default ::= FILENAME_KW NAME(Filename) SEMICOLON. { mc->dbg_facility = eth_fopen(Filename,"w"); if (mc->dbg_facility == NULL) report_open_failure(Filename,errno,TRUE); } |
| dbgfile_default ::= . |
| |
| dbglevel_default ::= LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_lvl = (int) strtol(LevelString,NULL,10); } |
| dbglevel_default ::= . |
| |
| pdu_dbglevel_default ::= PDU_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_pdu_lvl = (int) strtol(LevelString,NULL,10); } |
| pdu_dbglevel_default ::= . |
| |
| gop_dbglevel_default ::= GOP_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_gop_lvl = (int) strtol(LevelString,NULL,10); } |
| gop_dbglevel_default ::= . |
| |
| gog_dbglevel_default ::= GOG_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_gog_lvl = (int) strtol(LevelString,NULL,10); } |
| gog_dbglevel_default ::= . |
| |
| |
| /************* DEFAULTS |
| */ |
| |
| defaults_decl ::= DEFAULT_KW OPEN_BRACE pdu_defaults gop_defaults gog_defaults CLOSE_BRACE SEMICOLON. |
| |
| pdu_defaults ::= PDU_KW OPEN_BRACE pdu_last_extracted_default pdu_drop_unassigned_default pdu_discard_default CLOSE_BRACE SEMICOLON. |
| pdu_defaults ::= . |
| |
| pdu_last_extracted_default ::= LAST_EXTRACTED_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.last_extracted = Flag; } |
| pdu_last_extracted_default ::= . |
| |
| pdu_drop_unassigned_default ::= DROP_UNASSIGNED_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.drop_unassigned = Flag; } |
| pdu_drop_unassigned_default ::= . |
| |
| pdu_discard_default ::= DISCARD_PDU_DATA_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.discard = Flag; } |
| pdu_discard_default ::= . |
| |
| gop_defaults ::= GOP_KW OPEN_BRACE gop_expiration_default gop_idle_timeout_default gop_lifetime_default gop_drop_unassigned_default gop_tree_mode_default gop_show_times_default CLOSE_BRACE SEMICOLON. |
| gop_defaults ::= . |
| |
| gop_expiration_default ::= EXPIRATION_KW time_value(B) SEMICOLON. { mc->defaults.gop.expiration = B; } |
| gop_expiration_default ::= . |
| |
| gop_idle_timeout_default ::= IDLE_TIMEOUT_KW time_value(B) SEMICOLON. { mc->defaults.gop.idle_timeout = B; } |
| gop_idle_timeout_default ::= . |
| |
| gop_lifetime_default ::= LIFETIME_KW time_value(B) SEMICOLON. { mc->defaults.gop.lifetime = B; } |
| gop_lifetime_default ::= . |
| |
| gop_drop_unassigned_default ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { mc->defaults.gop.drop_unassigned = B; } |
| gop_drop_unassigned_default ::= . |
| |
| gop_tree_mode_default ::= SHOW_TREE_KW gop_tree_mode(B) SEMICOLON. { mc->defaults.gop.pdu_tree_mode = B; } |
| gop_tree_mode_default ::= . |
| |
| gop_show_times_default ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { mc->defaults.gop.show_times = B; } |
| gop_show_times_default ::= . |
| |
| gog_defaults ::= GOG_KW OPEN_BRACE gog_expiration_default gop_tree_mode_default gog_goptree_default CLOSE_BRACE SEMICOLON. |
| gog_defaults ::= . |
| |
| gog_expiration_default ::= EXPIRATION_KW time_value(B) SEMICOLON. { mc->defaults.gop.expiration = B; } |
| gog_expiration_default ::= . |
| |
| gog_goptree_default ::= GOP_TREE_KW gop_tree_type(B) SEMICOLON. { mc->defaults.gog.gop_tree_mode = B; } |
| gog_goptree_default ::= . |
| |
| |
| /******************************************* TRANSFORM |
| */ |
| |
| transform_decl(A) ::= TRANSFORM_KW NAME(B) transform_body(C) SEMICOLON. { |
| AVPL_Transf* c; |
| |
| if ( g_hash_table_lookup(mc->transfs,B) ) { |
| configuration_error(mc,"A transformation called '%s' exists already",B); |
| } |
| |
| for ( c = C; c; c = c->next ) |
| c->name = g_strdup(B); |
| |
| g_hash_table_insert(mc->transfs,C->name,C); |
| |
| A = NULL; |
| } |
| |
| transform_body(A) ::= OPEN_BRACE transform_statements(B) CLOSE_BRACE. { A = B; } |
| |
| transform_statements(A) ::= transform_statements(C) transform_statement(B). { |
| AVPL_Transf* c; |
| |
| for ( c = C; c->next; c = c->next ) ; |
| c->next = B; |
| A = C; |
| } |
| |
| transform_statements(A) ::= transform_statement(B). { A = B; } |
| |
| transform_statement(A) ::= transform_match(Match) transform_action(Action) SEMICOLON. { |
| A = new_transform_elem(Match->avpl,Action->avpl,Match->match_mode,Action->replace_mode); |
| } |
| |
| transform_match(A) ::= MATCH_KW match_mode(Mode) avpl(Avpl). { |
| A = g_malloc(sizeof(transf_match_t)); |
| A->match_mode = Mode; |
| A->avpl = Avpl; |
| } |
| |
| transform_match(A) ::= . { |
| A = g_malloc(sizeof(transf_match_t)); |
| A->match_mode = AVPL_STRICT; |
| A->avpl = new_avpl(""); |
| |
| } |
| |
| transform_action(A) ::= . { |
| A = g_malloc(sizeof(transf_action_t)); |
| A->replace_mode = AVPL_INSERT; |
| A->avpl = new_avpl(""); |
| } |
| transform_action(A) ::= action_mode(Mode) avpl(Avpl). { |
| A = g_malloc(sizeof(transf_action_t)); |
| A->replace_mode = Mode; |
| A->avpl = Avpl; |
| } |
| |
| match_mode(A) ::= . { A = AVPL_STRICT; } |
| match_mode(A) ::= STRICT_KW. { A = AVPL_STRICT; } |
| match_mode(A) ::= EVERY_KW. { A = AVPL_EVERY; } |
| match_mode(A) ::= LOOSE_KW. { A = AVPL_LOOSE; } |
| |
| action_mode(A) ::= REPLACE_KW. { A = AVPL_REPLACE; } |
| action_mode(A) ::= INSERT_KW. { A = AVPL_INSERT; } |
| action_mode(A) ::= . { A = AVPL_INSERT; } |
| |
| /******************************************* PDU |
| */ |
| |
| pdu_decl ::= |
| PDU_KW NAME(Name) PROTO_KW field(Field) TRANSPORT_KW proto_stack(Stack) |
| OPEN_BRACE |
| payload_statement(Payload) |
| extraction_statements(Extraction) |
| transform_list_statement(Transform) |
| criteria_statement(Criteria) |
| pdu_drop_unassigned_statement(DropUnassigned) |
| discard_pdu_data_statement(DistcardPduData) |
| last_extracted_statement(LastExtracted) |
| CLOSE_BRACE SEMICOLON. |
| { |
| |
| mate_cfg_pdu* cfg = new_pducfg(Name); |
| extraction_t *extraction, *next_extraction; |
| GPtrArray* transport_stack = g_ptr_array_new(); |
| int i; |
| |
| if (! cfg ) configuration_error(mc,"could not create Pdu %s.",Name); |
| |
| cfg->hfid_proto = Field->id; |
| |
| cfg->last_extracted = LastExtracted; |
| cfg->discard = DistcardPduData; |
| cfg->drop_unassigned = DropUnassigned; |
| |
| g_string_sprintfa(mc->protos_filter,"||%s",Field->abbrev); |
| |
| /* flip the transport_stack */ |
| for (i = Stack->len - 1; Stack->len; i--) { |
| g_ptr_array_add(transport_stack,g_ptr_array_remove_index(Stack,i)); |
| } |
| |
| g_ptr_array_free(Stack,FALSE); |
| |
| cfg->transport_ranges = transport_stack; |
| cfg->payload_ranges = Payload; |
| |
| if (Criteria) { |
| cfg->criterium = Criteria->criterium_avpl; |
| cfg->criterium_match_mode = Criteria->criterium_match_mode; |
| cfg->criterium_accept_mode = Criteria->criterium_accept_mode; |
| } |
| |
| cfg->transforms = Transform; |
| |
| for (extraction = Extraction; extraction; extraction = next_extraction) { |
| next_extraction = extraction->next; |
| |
| if ( ! add_hfid(extraction->hfi, extraction->as, cfg->hfids_attr) ) { |
| configuration_error(mc,"MATE: failed to create extraction rule '%s'",extraction->as); |
| } |
| |
| g_free(extraction); |
| } |
| } |
| |
| payload_statement(A) ::= . { A = NULL; } |
| payload_statement(A) ::= PAYLOAD_KW proto_stack(B) SEMICOLON. { A = B; } |
| |
| criteria_statement(A) ::= . { A = NULL; } |
| criteria_statement(A) ::= CRITERIA_KW accept_mode(B) match_mode(C) avpl(D) SEMICOLON. { |
| A = g_malloc(sizeof(pdu_criteria_t)); |
| A->criterium_avpl = D; |
| A->criterium_match_mode = C; |
| A->criterium_accept_mode = B; |
| } |
| |
| accept_mode(A) ::= . { A = ACCEPT_MODE; } |
| accept_mode(A) ::= ACCEPT_KW. { A = ACCEPT_MODE; } |
| accept_mode(A) ::= REJECT_KW. { A = REJECT_MODE; } |
| |
| extraction_statements(A) ::= extraction_statements(B) extraction_statement(C). { A = B; A->last = A->last->next = C; } |
| extraction_statements(A) ::= extraction_statement(B). { A = B; A->last = A; } |
| |
| extraction_statement(A) ::= EXTRACT_KW NAME(NAME) FROM_KW field(FIELD) SEMICOLON. { |
| A = g_malloc(sizeof(extraction_t)); |
| A->as = NAME; |
| A->hfi = FIELD; |
| A->next = A->last = NULL; |
| } |
| |
| |
| pdu_drop_unassigned_statement(A) ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { A = B; } |
| pdu_drop_unassigned_statement(A) ::= . { A = mc->defaults.pdu.drop_unassigned; } |
| |
| discard_pdu_data_statement(A) ::= DISCARD_PDU_DATA_KW true_false(B) SEMICOLON. { A = B; } |
| discard_pdu_data_statement(A) ::= . { A = mc->defaults.pdu.discard; } |
| |
| last_extracted_statement(A) ::= LAST_PDU_KW true_false(B) SEMICOLON. { A = B; } |
| last_extracted_statement(A) ::= . { A = mc->defaults.pdu.last_extracted; } |
| |
| proto_stack(A) ::= proto_stack(B) SLASH field(C). { |
| int* hfidp = g_malloc(sizeof(int)); |
| |
| g_string_sprintfa(mc->fields_filter,"||%s",C->abbrev); |
| |
| *hfidp = C->id; |
| g_ptr_array_add(B,hfidp); |
| A = B; |
| } |
| |
| proto_stack(A) ::= field(B). { |
| int* hfidp = g_malloc(sizeof(int)); |
| *hfidp = B->id; |
| |
| g_string_sprintfa(mc->fields_filter,"||%s",B->abbrev); |
| |
| A = g_ptr_array_new(); |
| g_ptr_array_add(A,hfidp); |
| } |
| |
| field(A) ::= NAME(B). { |
| A = proto_registrar_get_byname(B); |
| } |
| |
| /******************************************* GOP |
| */ |
| |
| gop_decl(A) ::= GOP_KW NAME(Name) ON_KW pdu_name(PduName) MATCH_KW avpl(Key) OPEN_BRACE |
| gop_start_statement(Start) |
| gop_stop_statement(Stop) |
| extra_statement(Extra) |
| transform_list_statement(Transform) |
| gop_expiration_statement(Expiration) |
| idle_timeout_statement(IdleTimeout) |
| lifetime_statement(Lifetime) |
| gop_drop_unassigned_statement(DropUnassigned) |
| show_goptree_statement(TreeMode) |
| show_times_statement(ShowTimes) |
| CLOSE_BRACE SEMICOLON. { |
| mate_cfg_gop* cfg; |
| |
| if (g_hash_table_lookup(mc->gopcfgs,Name)) configuration_error(mc,"A Gop Named '%s' exists already.",Name); |
| if (g_hash_table_lookup(mc->gops_by_pduname,PduName) ) configuration_error(mc,"Gop for Pdu '%s' exists already",PduName); |
| |
| cfg = new_gopcfg(Name); |
| g_hash_table_insert(mc->gops_by_pduname,PduName,cfg); |
| g_hash_table_insert(mc->gopcfgs,cfg->name,cfg); |
| |
| cfg->on_pdu = PduName; |
| cfg->key = Key; |
| cfg->drop_unassigned = DropUnassigned; |
| cfg->show_times = ShowTimes; |
| cfg->pdu_tree_mode = TreeMode; |
| cfg->expiration = Expiration; |
| cfg->idle_timeout = IdleTimeout; |
| cfg->lifetime = Lifetime; |
| cfg->start = Start; |
| cfg->stop = Stop; |
| cfg->transforms = Transform; |
| |
| merge_avpl(cfg->extra,Extra,TRUE); |
| delete_avpl(Extra,TRUE); |
| } |
| |
| gop_drop_unassigned_statement(A) ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { A = B; } |
| gop_drop_unassigned_statement(A) ::= . { A = mc->defaults.gop.drop_unassigned; } |
| |
| gop_start_statement(A) ::= START_KW avpl(B) SEMICOLON. { A = B; } |
| gop_start_statement(A) ::= . { A = NULL; } |
| |
| gop_stop_statement(A) ::= STOP_KW avpl(B) SEMICOLON. { A = B; } |
| gop_stop_statement(A) ::= . { A = NULL; } |
| |
| show_goptree_statement(A) ::= SHOW_TREE_KW gop_tree_mode(B) SEMICOLON. { A = B; } |
| show_goptree_statement(A) ::= . { A = mc->defaults.gop.pdu_tree_mode; } |
| |
| show_times_statement(A) ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { A = B; } |
| show_times_statement(A) ::= . { A = mc->defaults.gop.show_times; } |
| |
| gop_expiration_statement(A) ::= EXPIRATION_KW time_value(B) SEMICOLON. { A = B; } |
| gop_expiration_statement(A) ::= . { A = mc->defaults.gop.lifetime; } |
| |
| idle_timeout_statement(A) ::= IDLE_TIMEOUT_KW time_value(B) SEMICOLON. { A = B; } |
| idle_timeout_statement(A) ::= . { A = mc->defaults.gop.lifetime; } |
| |
| lifetime_statement(A) ::= LIFETIME_KW time_value(B) SEMICOLON. { A = B; } |
| lifetime_statement(A) ::= . { A = mc->defaults.gop.lifetime; } |
| |
| gop_tree_mode(A) ::= NO_TREE_KW. { A = GOP_NO_TREE; } |
| gop_tree_mode(A) ::= PDU_TREE_KW. { A = GOP_PDU_TREE; } |
| gop_tree_mode(A) ::= FRAME_TREE_KW. { A = GOP_FRAME_TREE; } |
| gop_tree_mode(A) ::= BASIC_TREE_KW. { A = GOP_BASIC_PDU_TREE; } |
| |
| true_false(A) ::= TRUE_KW. { A = TRUE; } |
| true_false(A) ::= FALSE_KW. { A = FALSE; } |
| |
| pdu_name(A) ::= NAME(B). { |
| mate_cfg_pdu* c; |
| if (( c = g_hash_table_lookup(mc->pducfgs,B) )) { |
| A = c->name; |
| } else { |
| configuration_error(mc,"No such Pdu: '%s'",B); |
| } |
| } |
| |
| |
| time_value(A) ::= FLOATING(B). { |
| A = (float) strtod(B,NULL); |
| } |
| |
| time_value(A) ::= INTEGER(B). { |
| A = (float) strtod(B,NULL); |
| } |
| |
| /************* GOG |
| */ |
| |
| gog_decl ::= GOG_KW NAME(Name) OPEN_BRACE |
| gog_key_statements(Keys) |
| extra_statement(Extra) |
| transform_list_statement(Transforms) |
| gog_expiration_statement(Expiration) |
| gog_goptree_statement(Tree) |
| CLOSE_BRACE SEMICOLON. { |
| mate_cfg_gog* cfg = NULL; |
| |
| if ( g_hash_table_lookup(mc->gogcfgs,Name) ) { |
| configuration_error(mc,"Gog '%s' exists already ",Name); |
| } |
| |
| cfg = new_gogcfg(Name); |
| |
| cfg->expiration = Expiration; |
| cfg->gop_tree_mode = Tree; |
| cfg->transforms = Transforms; |
| cfg->keys = Keys; |
| |
| merge_avpl(cfg->extra,Extra,TRUE); |
| delete_avpl(Extra,TRUE); |
| } |
| |
| gog_goptree_statement(A) ::= GOP_TREE_KW gop_tree_type(B) SEMICOLON. { A = B; } |
| gog_goptree_statement(A) ::= . { A = mc->defaults.gog.gop_tree_mode; } |
| |
| gog_expiration_statement(A) ::= EXPIRATION_KW time_value(B) SEMICOLON. { A = B; } |
| gog_expiration_statement(A) ::= . { A = mc->defaults.gog.expiration; } |
| |
| gop_tree_type(A) ::= NULL_TREE_KW. { A = GOP_NULL_TREE; } |
| gop_tree_type(A) ::= FULL_TREE_KW. { A = GOP_FULL_TREE; } |
| gop_tree_type(A) ::= BASIC_TREE_KW. { A = GOP_BASIC_TREE; } |
| |
| gog_key_statements(A) ::= gog_key_statements(B) gog_key_statement(C). { |
| loal_append(B,C); |
| A = B; |
| } |
| |
| gog_key_statements(A) ::= gog_key_statement(B). { |
| A = new_loal(""); |
| loal_append(A,B); |
| } |
| |
| |
| gog_key_statement(A) ::= MEMBER_KW gop_name(B) avpl(C) SEMICOLON. { |
| rename_avpl(C,B); |
| A = C; |
| } |
| |
| gop_name(A) ::= NAME(B). { |
| mate_cfg_gop* c; |
| if (( c = g_hash_table_lookup(mc->gopcfgs,B) )) { |
| A = c->name; |
| } else { |
| configuration_error(mc,"No Gop called '%s' has been already declared",B); |
| } |
| } |
| /******************************************** GENERAL |
| */ |
| |
| |
| extra_statement(A) ::= EXTRA_KW avpl(B) SEMICOLON. { A = B; } |
| extra_statement(A) ::= . { A = new_avpl(""); } |
| |
| transform_list_statement(A) ::= TRANSFORM_KW transform_list(B) SEMICOLON. { A = B; } |
| transform_list_statement(A) ::= . { A = g_ptr_array_new(); } |
| |
| transform_list(A) ::= transform_list(B) COMMA transform(C). { |
| A = B; |
| g_ptr_array_add(B,C); |
| } |
| |
| transform_list(A) ::= transform(B). { |
| A = g_ptr_array_new(); |
| g_ptr_array_add(A,B); |
| } |
| |
| transform(A) ::= NAME(B). { |
| AVPL_Transf* t; |
| |
| if (( t = g_hash_table_lookup(mc->transfs,B) )) { |
| A = t; |
| } else { |
| configuration_error(mc,"There's no such Transformation: %s",B); |
| } |
| } |
| |
| avpl(A) ::= OPEN_PARENS avps(B) CLOSE_PARENS. { A = B; } |
| avpl(A) ::= OPEN_PARENS CLOSE_PARENS. { A = new_avpl(""); } |
| |
| avps(A) ::= avps(B) COMMA avp(C). { A = B; if ( ! insert_avp(B,C) ) delete_avp(C); } |
| avps(A) ::= avp(B). { A = new_avpl(""); if ( ! insert_avp(A,B) ) delete_avp(B); } |
| |
| avp(A) ::= NAME(B) AVP_OPERATOR(C) value(D). { A = new_avp(B,D,*C); } |
| avp(A) ::= NAME(B). { A = new_avp(B,"",'?'); } |
| avp(A) ::= NAME(B) OPEN_BRACE avp_oneoff(C) CLOSE_BRACE. { A = new_avp(B,C,'|'); } |
| |
| avp_oneoff(A) ::= avp_oneoff(B) PIPE value(C). { A = g_strdup_printf("%s|%s",B,C); } |
| avp_oneoff(A) ::= value(B). { A = g_strdup(B); } |
| |
| value(A) ::= QUOTED(B). { A = g_strdup(B); } |
| value(A) ::= NAME(B). { A = g_strdup(B); } |
| value(A) ::= FLOATING(B). { A = g_strdup(B); } |
| value(A) ::= INTEGER(B). { A = g_strdup(B); } |
| value(A) ::= DOTED_IP(B). { A = g_strdup(B); } |
| value(A) ::= COLONIZED(B). { A = recolonize(mc,B); } |
| |