dssl.rl 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * Copyright (C) 2009 Mamadou Diop.
  3. *
  4. * Contact: Mamadou Diop <diopmamadou(at)doubango.org>
  5. *
  6. * This file is part of Open Source Doubango Framework.
  7. *
  8. * DOUBANGO is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * DOUBANGO is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with DOUBANGO.
  20. *
  21. */
  22. #include "dssl.h"
  23. #include "tsk_debug.h"
  24. #include "tsk_memory.h"
  25. #include "tsk_string.h"
  26. #include "tsk_ragel_state.h"
  27. #include <string.h>
  28. #define DEBUG_PARSER 0
  29. #define set_level(_lv) if(opt) opt->lv = _lv;
  30. char* replace_param(char* pivot, int index_1, int index_2, tsk_params_L_t* params)
  31. {
  32. char* pname = tsk_null;
  33. char* ret = tsk_null;
  34. const tsk_param_t* p;
  35. //tsk_size_t len = tsk_strlen(pivot);
  36. //tsk_bool_t parenthesis = tsk_false;
  37. int i1, i2;
  38. /* whether there are parenthesis around the param */
  39. if((i1 = tsk_strindexOf((pivot + index_1), tsk_strlen((pivot + index_1)), "(")) == 2
  40. && (i2 = tsk_strindexOf((pivot + index_1 + i1), tsk_strlen((pivot + index_1 + i1)), ")")) != -1)
  41. {
  42. pname = tsk_strndup((pivot + index_1 + i1 + 1), (i2 - i1 + 1));
  43. index_2 = index_1 + i1 + i2 + 1;
  44. }
  45. else{
  46. pname = tsk_strndup((pivot + index_1 + 2/*$$*/), (index_2 - index_1 - 2));
  47. }
  48. if((p = tsk_params_get_param_by_name(params, pname))){
  49. tsk_strncat(&ret, pivot, index_1);
  50. tsk_strncat(&ret, p->value, tsk_strlen(p->value));
  51. tsk_strncat(&ret, (pivot + index_2), (tsk_strlen(pivot) - index_2));
  52. }
  53. else{
  54. TSK_DEBUG_WARN("Failed to find param [%s]", pname);
  55. }
  56. TSK_FREE(pname);
  57. return ret;
  58. }
  59. tsk_bool_t next_not_(const char* p, const char* pe, char c)
  60. {
  61. if((p && pe) && (pe-p) >=2){
  62. return (*p == c && *(p + 1) == c) ? tsk_false : tsk_true;
  63. }
  64. return tsk_true;
  65. }
  66. #define next_not_hyphens(p, pe) next_not_(p, pe, '-')
  67. #define next_not_arobases(p, pe) next_not_(p, pe, '@')
  68. #define next_not_percents(p, pe) next_not_(p, pe, '%')
  69. #define next_not_redirs(p, pe) next_not_(p, pe, '>')
  70. /***********************************
  71. * Ragel state machine.
  72. */
  73. %%{
  74. machine demo_machine_parser_cmd;
  75. action tag{
  76. tag_start = p;
  77. #if DEBUG_PARSER
  78. // - TSK_DEBUG_INFO("tag=%s", tag_start);
  79. #endif
  80. }
  81. action create_option{
  82. #if DEBUG_PARSER
  83. TSK_DEBUG_INFO("create_option");
  84. #endif
  85. TSK_OBJECT_SAFE_FREE(opt);
  86. opt = opt_create_null();
  87. }
  88. action add_option{
  89. #if DEBUG_PARSER
  90. TSK_DEBUG_INFO("add_option");
  91. #endif
  92. tsk_list_push_back_data(cmd->opts, (void**)&opt);
  93. }
  94. action set_opt_value{
  95. if(opt){
  96. int index_1, index_2;
  97. char* newval = tsk_null;
  98. TSK_PARSER_SET_STRING(opt->value);
  99. /* trim both: left and right */
  100. tsk_strtrim_both(&opt->value);
  101. /* replace params */
  102. replace:
  103. if((index_1 = tsk_strindexOf(opt->value, tsk_strlen(opt->value), "$$")) != -1){
  104. if((index_2 = tsk_strindexOf((opt->value + index_1), tsk_strlen((opt->value + index_1)), " ")) != -1){
  105. newval = replace_param(opt->value, index_1, (index_1 + index_2), params);
  106. }
  107. else{
  108. newval = replace_param(opt->value, index_1, tsk_strlen(opt->value), params);
  109. }
  110. if(newval){
  111. TSK_FREE(opt->value);
  112. opt->value = newval;
  113. /* again */
  114. goto replace;
  115. }
  116. }
  117. #if DEBUG_PARSER
  118. TSK_DEBUG_INFO("set_opt_value [%d] '%s'", opt->type, opt->value);
  119. #endif
  120. }
  121. }
  122. action set_sidparam_value{
  123. TSK_PARSER_SET_STRING(cmd->sidparam);
  124. #if DEBUG_PARSER
  125. TSK_DEBUG_INFO("set_sidparam_value '%s'", cmd->sidparam);
  126. #endif
  127. }
  128. action create_param{
  129. #if DEBUG_PARSER
  130. TSK_DEBUG_INFO("create_param");
  131. #endif
  132. TSK_OBJECT_SAFE_FREE(param);
  133. param = tsk_param_create_null();
  134. }
  135. action add_param{
  136. #if DEBUG_PARSER
  137. TSK_DEBUG_INFO("add_param");
  138. #endif
  139. tsk_params_add_param_2(&params, param);
  140. TSK_OBJECT_SAFE_FREE(param);
  141. }
  142. action set_param_value{
  143. if(param){
  144. TSK_PARSER_SET_STRING(param->value);
  145. /* trim both: left and right */
  146. tsk_strtrim_both(&param->value);
  147. #if DEBUG_PARSER
  148. TSK_DEBUG_INFO("set_param_value [%s] '%s'", param->name, param->value);
  149. #endif
  150. }
  151. }
  152. action set_param_name{
  153. if(param){
  154. TSK_PARSER_SET_STRING(param->name);
  155. }
  156. }
  157. action is_comment{
  158. #if DEBUG_PARSER
  159. TSK_PARSER_SET_STRING(temp);
  160. TSK_DEBUG_INFO("is_comment '%s'", temp);
  161. #endif
  162. // *comment = tsk_true;
  163. // TSK_OBJECT_SAFE_FREE(opts);
  164. }
  165. action next_not_reserved{
  166. next_not_hyphens(p, pe)
  167. && next_not_arobases(p, pe)
  168. && next_not_percents(p, pe)
  169. && next_not_redirs(p, pe)
  170. && (p && *p != '\n')
  171. && (p && *p != '#')
  172. }
  173. action next_not_newline{
  174. (p && *p != '\n')
  175. }
  176. action option_error{
  177. TSK_PARSER_SET_STRING(temp);
  178. TSK_DEBUG_ERROR("'%s' is not a valid option.", temp);
  179. }
  180. action command_error{
  181. TSK_PARSER_SET_STRING(temp);
  182. TSK_DEBUG_ERROR("'%s' is not a valid command.", temp);
  183. }
  184. action level_error{
  185. TSK_PARSER_SET_STRING(temp);
  186. TSK_DEBUG_ERROR("'%s' is not a valid level.", temp);
  187. }
  188. SP = " ";
  189. LF = "\n";
  190. CR = "\r";
  191. endline = ("\n" | "\r");
  192. equal = "=";
  193. hyphens = "-" {2,};
  194. plusplus = "+" {2,};
  195. percents = "%" {2,};
  196. redirs = ">" {2,};
  197. sharp = "#";
  198. arobases = "@" {2,};
  199. command = (("audio"i | "a"i) %{ cmd->type = cmd_audio; } |
  200. ("audiovideo"i | "av"i) %{ cmd->type = cmd_audiovideo; } |
  201. ("config-session"i | "css"i) %{ cmd->type = cmd_config_session; } |
  202. ("config-stack"i | "cst"i) %{ cmd->type = cmd_config_stack; } |
  203. ("dtmf"i) %{ cmd->type = cmd_dtmf; } |
  204. ("dump"i | "d"i) %{ cmd->type = cmd_dump; } |
  205. ("ect"i) %{ cmd->type = cmd_ect; } |
  206. ("exit"i | "e"i | "quit"i | "q"i) %{ cmd->type = cmd_exit; } |
  207. ("file"i | "f"i) %{ cmd->type = cmd_file; } |
  208. ("hangup"i | "hu"i) %{ cmd->type = cmd_hangup; } |
  209. ("help"i | "h"i) %{ cmd->type = cmd_help; } |
  210. ("hold"i | "ho"i) %{ cmd->type = cmd_hold; } |
  211. ("large-message"i | "lm"i) %{ cmd->type = cmd_large_message; } |
  212. ("message"i | "m"i) %{ cmd->type = cmd_message; } |
  213. ("options"i | "opt"i) %{ cmd->type = cmd_options; } |
  214. ("publish"i | "pub"i) %{ cmd->type = cmd_publish; } |
  215. ("register"i | "reg"i) %{ cmd->type = cmd_register; } |
  216. ("resume"i | "res"i) %{ cmd->type = cmd_resume; } |
  217. ("run"i | "r"i) %{ cmd->type = cmd_run; } |
  218. ("scenario"i | "sn"i) %{ cmd->type = cmd_scenario; } |
  219. "sleep"i %{ cmd->type = cmd_sleep; } |
  220. "sms"i %{ cmd->type = cmd_sms; } |
  221. "stop"i %{ cmd->type = cmd_stop; } |
  222. ("subscribe"i | "sub"i) %{ cmd->type = cmd_subscribe; } |
  223. ("video"i | "v"i) %{ cmd->type = cmd_video; }
  224. )** >10 |
  225. (any*) >tag >0 %command_error;
  226. key = ("amf"i % { opt->type = opt_amf; } |
  227. "caps"i % { opt->type = opt_caps; } |
  228. "dhcpv4"i % { opt->type = opt_dhcpv4; } |
  229. "dhcpv6"i % { opt->type = opt_dhcpv6; } |
  230. "dname"i % { opt->type = opt_amf; } |
  231. "dns-naptr"i % { opt->type = opt_dname; } |
  232. "event"i % { opt->type = opt_event; } |
  233. ("expires"i | "xp"i) % { opt->type = opt_expires; } |
  234. "from"i % { opt->type = opt_from; } |
  235. "header"i % { opt->type = opt_header; } |
  236. "impi"i % { opt->type = opt_impi; } |
  237. "impu"i % { opt->type = opt_impu; } |
  238. "ipv6"i % { opt->type = opt_ipv6; } |
  239. "local-ip"i % { opt->type = opt_local_ip; } |
  240. "local-port"i % { opt->type = opt_local_port; } |
  241. "opid"i % { opt->type = opt_opid; } |
  242. ("password"i | "pwd"i) % { opt->type = opt_password; } |
  243. "path"i % { opt->type = opt_path; } |
  244. ("payload"i | "pay"i) % { opt->type = opt_payload; } |
  245. "pcscf-ip"i % { opt->type = opt_pcscf_ip; } |
  246. "pcscf-port"i % { opt->type = opt_pcscf_port; } |
  247. "pcscf-trans"i % { opt->type = opt_pcscf_trans; } |
  248. "realm"i % { opt->type = opt_realm; } |
  249. "sec"i % { opt->type = opt_sec; } |
  250. "sid"i % { opt->type = opt_sid; } |
  251. "sigcomp-id"i % { opt->type = opt_sigcomp_id; } |
  252. "silent"i % { opt->type = opt_silent; } |
  253. "smsc"i % { opt->type = opt_smsc; } |
  254. "stun-ip"i % { opt->type = opt_stun_ip; } |
  255. "stun-pwd"i % { opt->type = opt_stun_pwd; } |
  256. "stun-port"i % { opt->type = opt_stun_port; } |
  257. "stun-usr"i % { opt->type = opt_stun_usr; } |
  258. "to"i % { opt->type = opt_to; }
  259. )** >10 |
  260. (any*) >tag >0 %option_error;
  261. level_stack = ("stack"i | "st"i);
  262. level_session = ("session"i | "ss"i);
  263. level_action= ("action"i | "request"i | "a"i | "r"i);
  264. level = ( (level_stack %{ set_level(lv_stack); } | level_session %{ set_level(lv_session); } | level_action %{ set_level(lv_action); })** > 10
  265. | (any*)>tag >0 %level_error ) :> space*;
  266. value = (any when next_not_reserved)*>tag;
  267. option = key>tag:>SP* <:value %set_opt_value (arobases level)?;
  268. pname = (any when next_not_newline)*>tag %set_param_name;
  269. pvalue = value;
  270. param = pname :>(space | '\n')+ <:pvalue %set_param_value;
  271. main := |*
  272. (plusplus command) >100 { };
  273. (hyphens option>create_option %add_option) >99 { };
  274. (percents param>create_param %add_param) >98 { };
  275. (redirs "("?<: value %set_sidparam_value :>")"?) >97 { };
  276. (sharp (any when next_not_newline)* >tag %is_comment) >96 { };
  277. any >0 { };
  278. *|;
  279. }%%
  280. cmd_t* dssl_parse(const char *buffer, tsk_size_t size, tsk_bool_t *comment, tsk_params_L_t* params)
  281. {
  282. int cs = 0;
  283. const char *p = buffer;
  284. const char *pe;
  285. const char *eof;
  286. opt_t* opt = tsk_null;
  287. tsk_param_t* param = tsk_null;
  288. cmd_t *cmd = cmd_create_null();
  289. char* temp = tsk_null;
  290. int index;
  291. const char *ts = tsk_null, *te = tsk_null;
  292. int act = 0;
  293. const char *tag_start = tsk_null;
  294. /* global vars and initilization (Ragel) */
  295. %%write data;
  296. %%write init;
  297. /* default values */
  298. *comment = tsk_false;
  299. /* only parse one line */
  300. if((index = tsk_strindexOf(p, size, "\n")) != -1){
  301. pe = eof = (p + index + 1/*\n*/);
  302. }
  303. else{
  304. pe = eof = p + size;
  305. }
  306. /* exec */
  307. %%write exec;
  308. if( cs < %%{ write first_final; }%% ){
  309. TSK_DEBUG_ERROR("Failed to parse [%s] command-Line.", p);
  310. TSK_OBJECT_SAFE_FREE(cmd);
  311. }
  312. TSK_OBJECT_SAFE_FREE(opt);
  313. TSK_OBJECT_SAFE_FREE(param);
  314. TSK_FREE(temp);
  315. return cmd;
  316. }