diff options
Diffstat (limited to 'plugins/epan/mate/mate_grammar.lemon')
-rw-r--r-- | plugins/epan/mate/mate_grammar.lemon | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/plugins/epan/mate/mate_grammar.lemon b/plugins/epan/mate/mate_grammar.lemon new file mode 100644 index 0000000000..4b9ac3195f --- /dev/null +++ b/plugins/epan/mate/mate_grammar.lemon @@ -0,0 +1,732 @@ +%include { + +/* mate_grammar.lemon +* MATE's configuration language grammar +* +* Copyright 2005, Luis E. Garcia Ontanon <luis@ontanon.org> +* +* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* + * XXX - there's a Lemon bug where this grammar produces a parser that + * fails assertions; to work around it, we disable assert() failures. + */ +#ifndef NDEBUG +#define NDEBUG +#endif + +#include "mate.h" +#include "mate_grammar.h" +#include <wsutil/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 = (mate_config_frame *)g_ptr_array_index(mc->config_stack,(guint)i); + + g_string_append_printf(mc->config_error,"%s%s at line %u",incl, current_frame->filename, current_frame->linenum); + } + + g_string_append_printf(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 = (AVPL_Transf *)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_ascii_strdown(vec[i], -1); + + 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; + } + /* FALL THROUGH */ + 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_append_printf(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 { + (void) mc; /* Mark unused, similar to Q_UNUSED */ + 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 = ws_fopen(Filename,"w"); if (mc->dbg_facility == NULL) report_open_failure(Filename,errno,TRUE); } +dbgfile_default ::= FILENAME_KW NAME(Filename) SEMICOLON. { mc->dbg_facility = ws_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 = (gop_pdu_tree_t)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 gog_show_times_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 ::= . + +gog_show_times_default ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { mc->defaults.gog.show_times = B; } +gog_show_times_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 = (transf_match_t *)g_malloc(sizeof(transf_match_t)); + A->match_mode = Mode; + A->avpl = Avpl; +} + +transform_match(A) ::= . { + A = (transf_match_t *)g_malloc(sizeof(transf_match_t)); + A->match_mode = AVPL_STRICT; + A->avpl = new_avpl(""); + +} + +transform_action(A) ::= . { + A = (transf_action_t *)g_malloc(sizeof(transf_action_t)); + A->replace_mode = AVPL_INSERT; + A->avpl = new_avpl(""); +} +transform_action(A) ::= action_mode(Mode) avpl(Avpl). { + A = (transf_action_t *)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(mc, 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; + + /* + * Add this protocol to our table of wanted hfids. + */ + mc->wanted_hfids = g_array_append_val(mc->wanted_hfids, Field->id); + + /* 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(mc, 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 = (pdu_criteria_t *)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 = (extraction_t *)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 = (int *)g_malloc(sizeof(int)); + + *hfidp = C->id; + g_ptr_array_add(B,hfidp); + A = B; +} + +proto_stack(A) ::= field(B). { + int* hfidp = (int *)g_malloc(sizeof(int)); + *hfidp = B->id; + + 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(mc, 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 = (gop_pdu_tree_t)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 = (gop_tree_mode_t)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_tree_mode_t)GOP_NO_TREE; } +gop_tree_mode(A) ::= PDU_TREE_KW. { A = (gop_tree_mode_t)GOP_PDU_TREE; } +gop_tree_mode(A) ::= FRAME_TREE_KW. { A = (gop_tree_mode_t)GOP_FRAME_TREE; } +gop_tree_mode(A) ::= BASIC_TREE_KW. { A = (gop_tree_mode_t)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 = (mate_cfg_pdu *)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) g_ascii_strtod(B,NULL); +} + +time_value(A) ::= INTEGER(B). { + A = (float) g_ascii_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) + show_times_statement(ShowTimes) + 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(mc, Name); + + cfg->expiration = Expiration; + cfg->gop_tree_mode = Tree; + cfg->transforms = Transforms; + cfg->keys = Keys; + cfg->show_times = ShowTimes; + + 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 = (mate_cfg_gop *)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 = (AVPL_Transf *)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); } + |