doubango/tinyDEMO/dssl.rl

359 lines
9.8 KiB
Ragel
Executable File

/*
* Copyright (C) 2009 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO 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 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO 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 DOUBANGO.
*
*/
#include "dssl.h"
#include "tsk_debug.h"
#include "tsk_memory.h"
#include "tsk_string.h"
#include "tsk_ragel_state.h"
#include <string.h>
#define DEBUG_PARSER 1
#define set_level(_lv) if(opt) opt->lv = _lv;
char* replace_param(char* pivot, int index_1, int index_2, tsk_params_L_t* params)
{
char* pname = tsk_null;
char* ret = tsk_null;
const tsk_param_t* p;
//tsk_size_t len = tsk_strlen(pivot);
//tsk_bool_t parenthesis = tsk_false;
int i1, i2;
/* whether there are parenthesis around the param */
if((i1 = tsk_strindexOf((pivot + index_1), tsk_strlen((pivot + index_1)), "(")) == 2
&& (i2 = tsk_strindexOf((pivot + index_1 + i1), tsk_strlen((pivot + index_1 + i1)), ")")) != -1)
{
pname = tsk_strndup((pivot + index_1 + i1 + 1), (i2 - i1 + 1));
index_2 = index_1 + i1 + i2 + 1;
}
else{
pname = tsk_strndup((pivot + index_1 + 2/*$$*/), (index_2 - index_1 - 2));
}
if((p = tsk_params_get_param_by_name(params, pname))){
tsk_strncat(&ret, pivot, index_1);
tsk_strncat(&ret, p->value, tsk_strlen(p->value));
tsk_strncat(&ret, (pivot + index_2), (tsk_strlen(pivot) - index_2));
}
else{
TSK_DEBUG_WARN("Failed to find param [%s]", pname);
}
TSK_FREE(pname);
return ret;
}
tsk_bool_t next_not_(const char* p, const char* pe, char c)
{
if((p && pe) && (pe-p) >=2){
return (*p == c && *(p + 1) == c) ? tsk_false : tsk_true;
}
return tsk_true;
}
#define next_not_hyphens(p, pe) next_not_(p, pe, '-')
#define next_not_arobases(p, pe) next_not_(p, pe, '@')
#define next_not_percents(p, pe) next_not_(p, pe, '%')
#define next_not_redirs(p, pe) next_not_(p, pe, '>')
/***********************************
* Ragel state machine.
*/
%%{
machine demo_machine_parser_cmd;
action tag{
tag_start = p;
#if DEBUG_PARSER
// - TSK_DEBUG_INFO("tag=%s", tag_start);
#endif
}
action create_option{
#if DEBUG_PARSER
TSK_DEBUG_INFO("create_option");
#endif
TSK_OBJECT_SAFE_FREE(opt);
opt = opt_create_null();
}
action add_option{
#if DEBUG_PARSER
TSK_DEBUG_INFO("add_option");
#endif
tsk_list_push_back_data(cmd->opts, (void**)&opt);
}
action set_opt_value{
if(opt){
int index_1, index_2;
char* newval = tsk_null;
TSK_PARSER_SET_STRING(opt->value);
/* trim both: left and right */
tsk_strtrim_both(&opt->value);
/* replace params */
replace:
if((index_1 = tsk_strindexOf(opt->value, tsk_strlen(opt->value), "$$")) != -1){
if((index_2 = tsk_strindexOf((opt->value + index_1), tsk_strlen((opt->value + index_1)), " ")) != -1){
newval = replace_param(opt->value, index_1, (index_1 + index_2), params);
}
else{
newval = replace_param(opt->value, index_1, tsk_strlen(opt->value), params);
}
if(newval){
TSK_FREE(opt->value);
opt->value = newval;
/* again */
goto replace;
}
}
#if DEBUG_PARSER
TSK_DEBUG_INFO("set_opt_value [%d] '%s'", opt->type, opt->value);
#endif
}
}
action set_sidparam_value{
TSK_PARSER_SET_STRING(cmd->sidparam);
#if DEBUG_PARSER
TSK_DEBUG_INFO("set_sidparam_value '%s'", cmd->sidparam);
#endif
}
action create_param{
#if DEBUG_PARSER
TSK_DEBUG_INFO("create_param");
#endif
TSK_OBJECT_SAFE_FREE(param);
param = tsk_param_create_null();
}
action add_param{
#if DEBUG_PARSER
TSK_DEBUG_INFO("add_param");
#endif
tsk_params_add_param_2(&params, param);
TSK_OBJECT_SAFE_FREE(param);
}
action set_param_value{
if(param){
TSK_PARSER_SET_STRING(param->value);
/* trim both: left and right */
tsk_strtrim_both(&param->value);
#if DEBUG_PARSER
TSK_DEBUG_INFO("set_param_value [%s] '%s'", param->name, param->value);
#endif
}
}
action set_param_name{
if(param){
TSK_PARSER_SET_STRING(param->name);
}
}
action is_comment{
#if DEBUG_PARSER
TSK_PARSER_SET_STRING(temp);
TSK_DEBUG_INFO("is_comment '%s'", temp);
#endif
// *comment = tsk_true;
// TSK_OBJECT_SAFE_FREE(opts);
}
action next_not_reserved{
next_not_hyphens(p, pe)
&& next_not_arobases(p, pe)
&& next_not_percents(p, pe)
&& next_not_redirs(p, pe)
&& (p && *p != '\n')
&& (p && *p != '#')
}
action next_not_newline{
(p && *p != '\n')
}
action option_error{
TSK_PARSER_SET_STRING(temp);
TSK_DEBUG_ERROR("'%s' is not a valid option.", temp);
}
action command_error{
TSK_PARSER_SET_STRING(temp);
TSK_DEBUG_ERROR("'%s' is not a valid command.", temp);
}
action level_error{
TSK_PARSER_SET_STRING(temp);
TSK_DEBUG_ERROR("'%s' is not a valid level.", temp);
}
SP = " ";
LF = "\n";
CR = "\r";
endline = ("\n" | "\r");
equal = "=";
hyphens = "-" {2,};
plusplus = "+" {2,};
percents = "%" {2,};
redirs = ">" {2,};
sharp = "#";
arobases = "@" {2,};
command = (("audio"i | "a"i) %{ cmd->type = cmd_audio; } |
("audiovideo"i | "av"i) %{ cmd->type = cmd_audiovideo; } |
("config-session"i | "css"i) %{ cmd->type = cmd_config_session; } |
("config-stack"i | "cst"i) %{ cmd->type = cmd_config_stack; } |
("dtmf"i) %{ cmd->type = cmd_dtmf; } |
("dump"i | "d"i) %{ cmd->type = cmd_dump; } |
("ect"i) %{ cmd->type = cmd_ect; } |
("exit"i | "e"i | "quit"i | "q"i) %{ cmd->type = cmd_exit; } |
("file"i | "f"i) %{ cmd->type = cmd_file; } |
("hangup"i | "hu"i) %{ cmd->type = cmd_hangup; } |
("help"i | "h"i) %{ cmd->type = cmd_help; } |
("hold"i | "ho"i) %{ cmd->type = cmd_hold; } |
("large-message"i | "lm"i) %{ cmd->type = cmd_large_message; } |
("message"i | "m"i) %{ cmd->type = cmd_message; } |
("options"i | "opt"i) %{ cmd->type = cmd_options; } |
("publish"i | "pub"i) %{ cmd->type = cmd_publish; } |
("register"i | "reg"i) %{ cmd->type = cmd_register; } |
("resume"i | "res"i) %{ cmd->type = cmd_resume; } |
("run"i | "r"i) %{ cmd->type = cmd_run; } |
("scenario"i | "sn"i) %{ cmd->type = cmd_scenario; } |
"sleep"i %{ cmd->type = cmd_sleep; } |
"sms"i %{ cmd->type = cmd_sms; } |
"stop"i %{ cmd->type = cmd_stop; } |
("subscribe"i | "sub"i) %{ cmd->type = cmd_subscribe; } |
("video"i | "v"i) %{ cmd->type = cmd_video; }
)** >10 |
(any*) >tag >0 %command_error;
key = ("amf"i % { opt->type = opt_amf; } |
"caps"i % { opt->type = opt_caps; } |
"dhcpv4"i % { opt->type = opt_dhcpv4; } |
"dhcpv6"i % { opt->type = opt_dhcpv6; } |
"dname"i % { opt->type = opt_amf; } |
"dns-naptr"i % { opt->type = opt_dname; } |
"event"i % { opt->type = opt_event; } |
("expires"i | "xp"i) % { opt->type = opt_expires; } |
"from"i % { opt->type = opt_from; } |
"header"i % { opt->type = opt_header; } |
"impi"i % { opt->type = opt_impi; } |
"impu"i % { opt->type = opt_impu; } |
"ipv6"i % { opt->type = opt_ipv6; } |
"local-ip"i % { opt->type = opt_local_ip; } |
"local-port"i % { opt->type = opt_local_port; } |
"opid"i % { opt->type = opt_opid; } |
("password"i | "pwd"i) % { opt->type = opt_password; } |
"path"i % { opt->type = opt_path; } |
("payload"i | "pay"i) % { opt->type = opt_payload; } |
"pcscf-ip"i % { opt->type = opt_pcscf_ip; } |
"pcscf-port"i % { opt->type = opt_pcscf_port; } |
"pcscf-trans"i % { opt->type = opt_pcscf_trans; } |
"realm"i % { opt->type = opt_realm; } |
"sec"i % { opt->type = opt_sec; } |
"sid"i % { opt->type = opt_sid; } |
"sigcomp-id"i % { opt->type = opt_sigcomp_id; } |
"silent"i % { opt->type = opt_silent; } |
"smsc"i % { opt->type = opt_smsc; } |
"stun-ip"i % { opt->type = opt_stun_ip; } |
"stun-pwd"i % { opt->type = opt_stun_pwd; } |
"stun-port"i % { opt->type = opt_stun_port; } |
"stun-usr"i % { opt->type = opt_stun_usr; } |
"to"i % { opt->type = opt_to; }
)** >10 |
(any*) >tag >0 %option_error;
level_stack = ("stack"i | "st"i);
level_session = ("session"i | "ss"i);
level_action= ("action"i | "request"i | "a"i | "r"i);
level = ( (level_stack %{ set_level(lv_stack); } | level_session %{ set_level(lv_session); } | level_action %{ set_level(lv_action); })** > 10
| (any*)>tag >0 %level_error ) :> space*;
value = (any when next_not_reserved)*>tag;
option = key>tag:>SP* <:value %set_opt_value (arobases level)?;
pname = (any when next_not_newline)*>tag %set_param_name;
pvalue = value;
param = pname :>(space | '\n')+ <:pvalue %set_param_value;
main := |*
(plusplus command) >100 { };
(hyphens option>create_option %add_option) >99 { };
(percents param>create_param %add_param) >98 { };
(redirs "("?<: value %set_sidparam_value :>")"?) >97 { };
(sharp (any when next_not_newline)* >tag %is_comment) >96 { };
any >0 { };
*|;
}%%
cmd_t* dssl_parse(const char *buffer, tsk_size_t size, tsk_bool_t *comment, tsk_params_L_t* params)
{
int cs = 0;
const char *p = buffer;
const char *pe;
const char *eof;
opt_t* opt = tsk_null;
tsk_param_t* param = tsk_null;
cmd_t *cmd = cmd_create_null();
char* temp = tsk_null;
int index;
const char *ts = tsk_null, *te = tsk_null;
int act = 0;
const char *tag_start = tsk_null;
/* global vars and initilization (Ragel) */
%%write data;
%%write init;
/* default values */
*comment = tsk_false;
/* only parse one line */
if((index = tsk_strindexOf(p, size, "\n")) != -1){
pe = eof = (p + index + 1/*\n*/);
}
else{
pe = eof = p + size;
}
/* exec */
%%write exec;
if( cs < %%{ write first_final; }%% ){
TSK_DEBUG_ERROR("Failed to parse [%s] command-Line.", p);
TSK_OBJECT_SAFE_FREE(cmd);
}
TSK_OBJECT_SAFE_FREE(opt);
TSK_OBJECT_SAFE_FREE(param);
TSK_FREE(temp);
return cmd;
}