316b6349fb6336dbdf3fd58aff6f9ffbfd62babb
[deliverable/titan.core.git] / common / config_preproc_la.l
1 /******************************************************************************
2 * Copyright (c) 2000-2014 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
7 ******************************************************************************/
8
9 %option noyywrap
10 %option never-interactive
11 %option nounput
12 %option prefix="config_preproc_yy"
13
14 %{
15
16 #include <string.h>
17 #include <unistd.h>
18 #include <errno.h>
19
20 #include <deque>
21 #include <string>
22
23 #include "Path2.hh"
24 #include "cfg_process_utils.hh"
25
26 #include "config_preproc.h"
27 #include "path.h"
28 #include "config_preproc_p.tab.hh"
29
30 //#include "dbgnew.hh"
31
32 #define yylineno config_preproc_yylineno
33
34 extern int add_include_file(const std::string&);
35
36 /* If there are errors in the parsed define sections this value changes to 1.
37 flex and bison for preprocessing can set it to 1, sometimes without printing
38 the error message because strings and some other stuff is also parsed by the
39 actual configuration parser which prints errors */
40 int preproc_error_flag;
41
42 /* used to track the curly brackets in the define section */
43 static int paren_stack = 0;
44
45 static std::deque<IncludeElem<YY_BUFFER_STATE> >* include_chain = NULL;
46
47 std::string get_cfg_preproc_current_file() {
48 if (include_chain && !include_chain->empty()) {
49 return include_chain->back().get_full_path();
50 }
51 return std::string();
52 }
53
54 %}
55
56 WHITESPACE [ \t]
57 WS {WHITESPACE}*
58 NEWLINE \r|\n|\r\n
59 LINECOMMENT ("//"|"#")[^\r\n]*{NEWLINE}
60 NUMBER 0|([1-9][0-9]*)
61
62 TTCN3IDENTIFIER [A-Za-z][A-Za-z0-9_]*
63
64 HEX [0-9A-Fa-f]
65
66 MACRORVALUE ([0-9A-Za-z._-]+)|{IPV6}
67 IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)?
68
69 MACRO_REFERENCE \${TTCN3IDENTIFIER}|\$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}charstring{WS})?"}"
70 MACRO_REFERENCE_INT \$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}integer{WS})?"}"
71
72
73 %x SC_blockcomment SC_cstring
74 %s SC_include SC_define SC_define_structured SC_ordered_include
75 %s SC_module_parameters SC_testport_parameters
76
77 %%
78 /* valid in states SC_blockcomment, SC_cstring */
79 int caller_state = INITIAL;
80 /* valid in state SC_cstring */
81 std::string cstring;
82
83 preproc_error_flag = 0;
84
85 "/*" {
86 caller_state = YY_START;
87 BEGIN(SC_blockcomment);
88 }
89
90 <SC_blockcomment>
91 {
92 "*/" {
93 BEGIN(caller_state);
94 if (YY_START==SC_define || YY_START==SC_define_structured) {
95 config_preproc_yylval.str_val = NULL;
96 return FillerStuff;
97 }
98 }
99
100 {NEWLINE} yylineno++;
101
102 . /* do nothing */
103
104 <<EOF>> {
105 preproc_error_flag = 1; /* unterminated block comment, error msg. in parser */
106 BEGIN(caller_state);
107 }
108 } /* SC_blockcomment */
109
110 {WHITESPACE} {
111 if (YY_START==SC_define || YY_START==SC_define_structured) {
112 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng); return FillerStuff;
113 }
114 }
115
116 {NEWLINE}|{LINECOMMENT} {
117 yylineno++;
118 if (YY_START==SC_define || YY_START==SC_define_structured) {
119 config_preproc_yylval.str_val = NULL;
120 return FillerStuff;
121 }
122 }
123
124 /* Section delimiters */
125
126 "["{WS}INCLUDE{WS}"]" BEGIN(SC_include);
127
128 "["{WS}ORDERED_INCLUDE{WS}"]" {
129 caller_state = YY_START;
130 BEGIN(SC_ordered_include);
131 }
132
133 "["{WS}DEFINE{WS}"]" BEGIN(SC_define);
134
135 "["{WS}MODULE_PARAMETERS{WS}"]" BEGIN(SC_module_parameters);
136 "["{WS}TESTPORT_PARAMETERS{WS}"]" BEGIN(SC_testport_parameters);
137
138 <SC_module_parameters,SC_testport_parameters>
139 {
140 "["{NUMBER}"]" ;
141 "["[^\r\n\[\]]*{MACRO_REFERENCE_INT}{WS}[^\r\n\[\]]*"]" ;
142 }
143
144 "["{WS}LOGGING{WS}"]" BEGIN(INITIAL);
145 "["{WS}EXECUTE{WS}"]" BEGIN(INITIAL);
146 "["{WS}EXTERNAL_COMMANDS{WS}"]" BEGIN(INITIAL);
147 "["{WS}GROUPS{WS}"]" BEGIN(INITIAL);
148 "["{WS}COMPONENTS{WS}"]" BEGIN(INITIAL);
149 "["{WS}MAIN_CONTROLLER{WS}"]" BEGIN(INITIAL);
150
151 "["[^\r\n\[\]]*"]" {
152 preproc_error_flag = 1;
153 config_preproc_error("Invalid section name `%s'", yytext);
154 }
155
156 \" {
157 caller_state = YY_START;
158 BEGIN(SC_cstring);
159 cstring.clear();
160
161 if (caller_state == SC_define_structured) {
162 cstring += '"';
163 }
164 }
165
166 <SC_cstring>
167 {
168 \"\" cstring += '"';
169
170 \" {
171 /* end of the string */
172 BEGIN(caller_state);
173 switch (YY_START) {
174 case SC_define_structured:
175 cstring += '"';
176 /* No break */
177 case SC_define:
178 config_preproc_yylval.str_val = mcopystrn(cstring.c_str(), cstring.size());
179 cstring.clear();
180 return Cstring;
181 case SC_include:
182 if (add_include_file(cstring)) preproc_error_flag = 1;
183 cstring.clear();
184 break;
185 case SC_ordered_include:
186 {
187 std::string error_msg = switch_lexer(include_chain, cstring,
188 YY_CURRENT_BUFFER, yy_create_buffer, yy_switch_to_buffer, yylineno,
189 YY_BUF_SIZE);
190 if (error_msg.empty()) {
191 BEGIN(INITIAL);
192 } else {
193 preproc_error_flag = 1;
194 config_preproc_error(error_msg.c_str());
195 }
196 }
197 /* no break */
198 default:
199 cstring.clear();
200 } /* switch */
201 } /* end of string */
202
203 \\[\\'"?] cstring += yytext[1]; /* backslash-quoted \ or " or ' or ? */
204 \\{NEWLINE} yylineno++;
205 \\a cstring += '\a';
206 \\b cstring += '\b';
207 \\f cstring += '\f';
208 \\n cstring += '\n';
209 \\r cstring += '\r';
210 \\t cstring += '\t';
211 \\v cstring += '\v';
212
213 \\[0-7]{1,3} {
214 unsigned int c;
215 sscanf(yytext + 1, "%o", &c);
216 /* do not report error in case of invalid octal escape sequences */
217 if (c <= 255) cstring += c;
218 else preproc_error_flag = 1;
219 }
220
221 \\x{HEX}{1,2} {
222 unsigned int c;
223 sscanf(yytext + 2, "%x", &c);
224 cstring += c;
225 }
226
227 \\(x[^\\\"]|.) preproc_error_flag = 1;
228
229 {NEWLINE} {
230 cstring.append(yytext, yyleng);
231 yylineno++;
232 }
233
234 . { cstring += yytext[0]; }
235
236 <<EOF>> {
237 preproc_error_flag = 1; /* unterminated string literal, error msg. in parser */
238 cstring.clear();
239 BEGIN(caller_state);
240 return EOF;
241 }
242 } /* SC_cstring */
243
244
245 <SC_define>
246 {
247
248 {TTCN3IDENTIFIER} {
249 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
250 return Identifier;
251 }
252
253 ":="|"=" { return AssignmentChar; }
254
255 {MACRORVALUE} {
256 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
257 return MacroRValue;
258 }
259
260 {MACRO_REFERENCE} {
261 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
262 return MacroReference;
263 }
264
265 "{" {
266 ++paren_stack;
267 BEGIN(SC_define_structured);
268 return LCurly;
269 }
270 } /* SC_define */
271
272 <SC_define_structured>
273 {
274
275 {MACRO_REFERENCE} {
276 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
277 return MacroReference;
278 }
279
280 "{" {
281 ++paren_stack;
282 return LCurly;
283 }
284
285 "}" {
286 if (paren_stack == 0) { /* We don't have any opened curly brackets. */
287 preproc_error_flag = 1;
288 config_preproc_error("Invalid structured definition.");
289 BEGIN(SC_define);
290 return RCurly;
291 }
292
293 --paren_stack;
294 if (paren_stack == 0) { /* The end of a structured definition. */
295 BEGIN(SC_define);
296 }
297 return RCurly;
298 }
299
300 \\\" { /* \" is handled separately in the structured definitions */
301 config_preproc_yylval.str_val = mcopystr("\"");
302 return FString;
303 }
304
305 \\. { /* Handle escaped characters */
306 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
307 return FString;
308 }
309
310 [^{}"\\$\n\r\t #/]+ { /* Anything except {,},\,$,#,/ and whitespace */
311 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
312 return FString;
313 }
314
315 "/" {
316 config_preproc_yylval.str_val = mcopystrn(yytext, yyleng);
317 return FString;
318 }
319
320 } /* SC_define_structured */
321
322 <<EOF>> {
323 if (include_chain->size() > 1) { // The last fp is owned by the parser
324 yy_delete_buffer(YY_CURRENT_BUFFER);
325 fclose(include_chain->back().fp);
326 include_chain->pop_back();
327 yy_switch_to_buffer(include_chain->back().buffer_state);
328 BEGIN(SC_ordered_include);
329 } else {
330 return EOF;
331 }
332 }
333
334 . {
335 switch (YY_START) {
336 case SC_define:
337 case SC_define_structured:
338 preproc_error_flag = 1;
339 config_preproc_error("Invalid character in [DEFINE] section: '%c'.", yytext[0]);
340 break;
341 case SC_include:
342 case SC_ordered_include:
343 preproc_error_flag = 1;
344 config_preproc_error("Invalid character in [%s] section: '%c'.",
345 (YY_START==SC_include || YY_START==SC_ordered_include) ? "INCLUDE" : "ORDERED_INCLUDE",
346 yytext[0]);
347 default:
348 break;
349 }
350 }
351
352
353 %%
354
355 void config_preproc_reset(const std::string& filename) {
356 if (!include_chain) {
357 include_chain = new std::deque<IncludeElem<YY_BUFFER_STATE> >();
358 } else {
359 include_chain->clear();
360 }
361
362 include_chain->push_back(IncludeElem<YY_BUFFER_STATE>(
363 filename, config_preproc_yyin));
364 }
365
366 void config_preproc_close() {
367 delete include_chain;
368 include_chain = NULL;
369 }
370
This page took 0.068485 seconds and 4 git commands to generate.