1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
16 * Szabo, Janos Zoltan – initial implementation
18 ******************************************************************************/
21 %option never-interactive
23 %option prefix="config_preproc_yy"
35 #include "cfg_process_utils.hh"
37 #include "config_preproc.h"
39 #include "config_preproc_p.tab.hh"
41 //#include "dbgnew.hh"
43 #define yylineno config_preproc_yylineno
45 extern int add_include_file(const std::string&);
47 /* If there are errors in the parsed define sections this value changes to 1.
48 flex and bison for preprocessing can set it to 1, sometimes without printing
49 the error message because strings and some other stuff is also parsed by the
50 actual configuration parser which prints errors */
51 int preproc_error_flag;
53 /* used to track the curly brackets in the define section */
54 static int paren_stack = 0;
56 static std::deque<IncludeElem<YY_BUFFER_STATE> >* include_chain = NULL;
58 std::string get_cfg_preproc_current_file() {
59 if (include_chain && !include_chain->empty()) {
60 return include_chain->back().get_full_path();
70 LINECOMMENT ("//"|"#")[^\r\n]*{NEWLINE}
71 NUMBER 0|([1-9][0-9]*)
73 TTCN3IDENTIFIER [A-Za-z][A-Za-z0-9_]*
77 MACRORVALUE ([0-9A-Za-z._-]+)|{IPV6}
78 IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)?
80 MACRO_REFERENCE \${TTCN3IDENTIFIER}|\$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}charstring{WS})?"}"
81 MACRO_REFERENCE_INT \$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}integer{WS})?"}"
84 %x SC_blockcomment SC_cstring
85 %s SC_include SC_define SC_define_structured SC_ordered_include
86 %s SC_module_parameters SC_testport_parameters
89 /* valid in states SC_blockcomment, SC_cstring */
90 int caller_state = INITIAL;
91 /* valid in state SC_cstring */
94 preproc_error_flag = 0;
97 caller_state = YY_START;
98 BEGIN(SC_blockcomment);
105 if (YY_START==SC_define || YY_START==SC_define_structured) {
106 config_preproc_yylval.str_val = NULL;
111 {NEWLINE} yylineno++;
116 preproc_error_flag = 1; /* unterminated block comment, error msg. in parser */
119 } /* SC_blockcomment */
122 if (YY_START==SC_define || YY_START==SC_define_structured) {
123 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); return FillerStuff;
127 {NEWLINE}|{LINECOMMENT} {
129 if (YY_START==SC_define || YY_START==SC_define_structured) {
130 config_preproc_yylval.str_val = NULL;
135 /* Section delimiters */
137 "["{WS}INCLUDE{WS}"]" BEGIN(SC_include);
139 "["{WS}ORDERED_INCLUDE{WS}"]" {
140 caller_state = YY_START;
141 BEGIN(SC_ordered_include);
144 "["{WS}DEFINE{WS}"]" BEGIN(SC_define);
146 "["{WS}MODULE_PARAMETERS{WS}"]" BEGIN(SC_module_parameters);
147 "["{WS}TESTPORT_PARAMETERS{WS}"]" BEGIN(SC_testport_parameters);
149 <SC_testport_parameters>
154 <SC_module_parameters>
156 "["[ \t0-9a-zA-Z+*/&-]*"]" ;
159 <SC_module_parameters,SC_testport_parameters>
161 "["[^\r\n\[\]]*{MACRO_REFERENCE_INT}{WS}[^\r\n\[\]]*"]" ;
164 "["{WS}LOGGING{WS}"]" BEGIN(INITIAL);
165 "["{WS}PROFILER{WS}"]" BEGIN(INITIAL);
166 "["{WS}EXECUTE{WS}"]" BEGIN(INITIAL);
167 "["{WS}EXTERNAL_COMMANDS{WS}"]" BEGIN(INITIAL);
168 "["{WS}GROUPS{WS}"]" BEGIN(INITIAL);
169 "["{WS}COMPONENTS{WS}"]" BEGIN(INITIAL);
170 "["{WS}MAIN_CONTROLLER{WS}"]" BEGIN(INITIAL);
173 preproc_error_flag = 1;
174 config_preproc_error("Invalid section name `%s'", yytext);
178 caller_state = YY_START;
182 if (caller_state == SC_define_structured) {
192 /* end of the string */
195 case SC_define_structured:
199 config_preproc_yylval.str_val = mcopystrn(cstring.c_str(), cstring.size());
203 if (add_include_file(cstring)) preproc_error_flag = 1;
206 case SC_ordered_include:
208 std::string error_msg = switch_lexer(include_chain, cstring,
209 YY_CURRENT_BUFFER, yy_create_buffer, yy_switch_to_buffer, yylineno,
211 if (error_msg.empty()) {
214 preproc_error_flag = 1;
215 config_preproc_error("%s", error_msg.c_str());
222 } /* end of string */
224 \\[\\'"?] cstring += yytext[1]; /* backslash-quoted \ or " or ' or ? */
225 \\{NEWLINE} yylineno++;
236 sscanf(yytext + 1, "%o", &c);
237 /* do not report error in case of invalid octal escape sequences */
238 if (c <= 255) cstring += c;
239 else preproc_error_flag = 1;
244 sscanf(yytext + 2, "%x", &c);
248 \\(x[^\\\"]|.) preproc_error_flag = 1;
251 cstring.append(yytext, yyleng);
255 . { cstring += yytext[0]; }
258 preproc_error_flag = 1; /* unterminated string literal, error msg. in parser */
270 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
274 ":="|"=" { return AssignmentChar; }
277 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
282 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
283 return MacroReference;
288 BEGIN(SC_define_structured);
293 <SC_define_structured>
297 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
298 return MacroReference;
307 if (paren_stack == 0) { /* We don't have any opened curly brackets. */
308 preproc_error_flag = 1;
309 config_preproc_error("Invalid structured definition.");
315 if (paren_stack == 0) { /* The end of a structured definition. */
321 \\\" { /* \" is handled separately in the structured definitions */
322 config_preproc_yylval.str_val = mcopystr("\"");
326 \\. { /* Handle escaped characters */
327 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
331 [^{}"\\$\n\r\t #/]+ { /* Anything except {,},\,$,#,/ and whitespace */
332 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
337 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
341 } /* SC_define_structured */
344 if (include_chain->size() > 1) { // The last fp is owned by the parser
345 yy_delete_buffer(YY_CURRENT_BUFFER);
346 fclose(include_chain->back().fp);
347 include_chain->pop_back();
348 yy_switch_to_buffer(include_chain->back().buffer_state);
349 BEGIN(SC_ordered_include);
358 case SC_define_structured:
359 preproc_error_flag = 1;
360 config_preproc_error("Invalid character in [DEFINE] section: '%c'.", yytext[0]);
363 case SC_ordered_include:
364 preproc_error_flag = 1;
365 config_preproc_error("Invalid character in [%s] section: '%c'.",
366 (YY_START==SC_include || YY_START==SC_ordered_include) ? "INCLUDE" : "ORDERED_INCLUDE",
376 void config_preproc_reset(const std::string& filename) {
377 if (!include_chain) {
378 include_chain = new std::deque<IncludeElem<YY_BUFFER_STATE> >();
380 include_chain->clear();
383 include_chain->push_back(IncludeElem<YY_BUFFER_STATE>(
384 filename, config_preproc_yyin));
387 void config_preproc_close() {
388 delete include_chain;
389 include_chain = NULL;