Commit | Line | Data |
---|---|---|
970ed795 | 1 | /****************************************************************************** |
3abe9331 | 2 | * Copyright (c) 2000-2015 Ericsson Telecom AB |
970ed795 EL |
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 | %option yylineno | |
9 | %option noyywrap | |
10 | %option never-interactive | |
11 | %option nounput | |
12 | ||
13 | %{ | |
14 | ||
15 | #include <string.h> | |
16 | #include <ctype.h> | |
17 | #include <stdlib.h> | |
18 | ||
19 | #include <deque> | |
20 | #include <string> | |
21 | ||
22 | #include <openssl/crypto.h> | |
23 | #include <openssl/bn.h> | |
24 | ||
25 | #include "../../common/cfg_process_utils.hh" | |
26 | #include "../../common/Path2.hh" | |
27 | #include "../../common/config_preproc.h" | |
28 | ||
29 | #include "../../common/memory.h" | |
30 | #include "../mctr/config_data.h" | |
31 | #include "../../core/Types.h" | |
32 | #include "config_read.tab.hh" | |
33 | ||
34 | //#include "../../common/dbgnew.hh" | |
35 | ||
36 | extern string_map_t *config_defines; | |
37 | ||
38 | #define yylval config_read_lval | |
39 | ||
40 | /* This buffer stores the state of the main buffer | |
41 | while the macro expansion is happening. */ | |
42 | static YY_BUFFER_STATE main_buffer = NULL; | |
43 | /* This buffer is active while the expansion of | |
44 | a reference to a structured macro definition is happening. | |
45 | Otherwise its value is NULL. */ | |
46 | static YY_BUFFER_STATE expansion_buffer = NULL; | |
47 | ||
48 | static void update_buffer(); | |
49 | static boolean whether_update_buffer(); | |
50 | ||
51 | #define RETURN(x) do {update_buffer(); return (x);} while(0) | |
52 | ||
53 | void config_read_warning(const char *warning_str, ...); | |
54 | extern void config_read_error(const char *error_str, ...); | |
55 | extern config_data *cfg; | |
56 | ||
57 | static std::deque<IncludeElem<YY_BUFFER_STATE> >* include_chain = NULL; | |
58 | ||
59 | std::string get_cfg_read_current_file() { | |
60 | if (include_chain && !include_chain->empty()) { | |
61 | return include_chain->back().get_full_path(); | |
62 | } | |
63 | return std::string(); | |
64 | } | |
65 | ||
66 | %} | |
67 | ||
68 | WHITESPACE [ \t] | |
69 | WS {WHITESPACE}* | |
70 | NEWLINE \r|\n|\r\n | |
71 | LINECOMMENT ("//"|"#")[^\r\n]*{NEWLINE} | |
72 | ||
73 | NUMBER 0|([1-9][0-9]*) | |
74 | ||
75 | FLOAT [+-]?({NUMBER}\.[0-9]+)|((({NUMBER}(\.[0-9]+)?)|(\.[0-9]+))[Ee][+-]?{NUMBER}) | |
76 | ||
77 | BIN 0|1 | |
78 | BITSTRING '{BIN}*'B | |
79 | BINMATCH 0|1|\?|\* | |
80 | BITSTRINGMATCH '{BINMATCH}*'B | |
81 | BITSTRING_BAD '[^']*'B | |
82 | ||
83 | HEX [0-9A-Fa-f] | |
84 | HEXSTRING '{HEX}*'H | |
85 | HEXMATCH [0-9A-Fa-f\?\*] | |
86 | HEXSTRINGMATCH '{HEXMATCH}*'H | |
87 | HEXSTRING_BAD '[^']*'H | |
88 | ||
89 | OCT {HEX}{HEX} | |
90 | OCTETSTRING '{OCT}*'O | |
91 | OCTMATCH {HEX}{HEX}|\?|\* | |
92 | OCTETSTRINGMATCH '{OCTMATCH}*'O | |
93 | OCTETSTRING_BAD '[^']*'O | |
94 | ||
95 | BINSTRING_BAD '[^']*' | |
96 | ||
97 | TTCN3IDENTIFIER [A-Za-z][A-Za-z0-9_]* | |
98 | ASN1LOWERIDENTIFIER [a-z](-?[A-Za-z0-9]+)* | |
99 | ||
100 | MACRORVALUE ([0-9A-Za-z._-]+)|{IPV6} | |
101 | MACRO_CSTR \${TTCN3IDENTIFIER}|\$"{"{WS}{TTCN3IDENTIFIER}{WS}(","{WS}charstring{WS})?"}" | |
102 | MACRO_BOOL \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}boolean{WS}"}" | |
103 | MACRO_FLOAT \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}float{WS}"}" | |
104 | MACRO_ID \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}identifier{WS}"}" | |
105 | MACRO_INT \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}integer{WS}"}" | |
106 | MACRO_BSTR \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}bitstring{WS}"}" | |
107 | MACRO_HSTR \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}hexstring{WS}"}" | |
108 | MACRO_OSTR \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}octetstring{WS}"}" | |
109 | MACRO_BINARY \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}binaryoctet{WS}"}" | |
110 | MACRO_HOSTNAME \$"{"{WS}{TTCN3IDENTIFIER}{WS}","{WS}hostname{WS}"}" | |
111 | ||
112 | CHAR [^\\\"]|\\([\\\'\"\?abfnrtv]|{NEWLINE}|[0-7]{1,3}|x{HEX}{1,2})|\"\" | |
113 | CHARSTRING \"{CHAR}*\" | |
114 | ||
115 | HOSTNAME [A-Za-z0-9]([A-Za-z0-9_\-]*[A-Za-z0-9])? | |
116 | DNSNAME {HOSTNAME}(\.{HOSTNAME})*\.? | |
117 | ||
118 | /* Example: fe80::c002:37ff:fe6c:0%fastethernet0/0 */ | |
119 | IPV6 [0-9A-Fa-f:.]+(%[0-9A-Za-z]+)? | |
120 | ||
121 | ||
122 | %x SC_blockcomment SC_DEFINE SC_CSTRING SC_ORDERED_INCLUDE | |
123 | %s SC_MODULE_PARAMETERS SC_LOGGING SC_TESTPORT_PARAMETERS SC_EXECUTE SC_GROUPS | |
af710487 | 124 | %s SC_COMPONENTS SC_EXTERNAL_COMMANDS SC_MAIN_CONTROLLER SC_INCLUDE SC_PROFILER |
970ed795 EL |
125 | |
126 | %% | |
127 | int comment_caller = INITIAL; | |
128 | ||
129 | std::string cstring; | |
130 | ||
131 | /* Eat up comments and whitespaces */ | |
132 | ||
133 | "/*" { | |
134 | comment_caller = YY_START; | |
135 | BEGIN(SC_blockcomment); | |
136 | } | |
137 | <SC_blockcomment> | |
138 | { | |
139 | "*/" BEGIN(comment_caller); | |
140 | .|\n | |
141 | } | |
142 | ||
143 | {LINECOMMENT}|{WHITESPACE}|{NEWLINE} | |
144 | ||
145 | /* Section delimiters */ | |
146 | ||
147 | <*>"["{WS}MODULE_PARAMETERS{WS}"]" { | |
148 | if (YY_START!=SC_blockcomment) { | |
149 | BEGIN(SC_MODULE_PARAMETERS); | |
150 | RETURN(ModuleParametersKeyword); | |
151 | } | |
152 | } | |
153 | ||
154 | <*>"["{WS}LOGGING{WS}"]" { | |
155 | if (YY_START!=SC_blockcomment) { | |
156 | BEGIN(SC_LOGGING); | |
157 | RETURN(LoggingKeyword); | |
158 | } | |
159 | } | |
160 | ||
af710487 | 161 | <*>"["{WS}PROFILER{WS}"]" { |
162 | if (YY_START!=SC_blockcomment) { | |
163 | BEGIN(SC_PROFILER); | |
164 | RETURN(ProfilerKeyword); | |
165 | } | |
166 | } | |
167 | ||
970ed795 EL |
168 | <*>"["{WS}TESTPORT_PARAMETERS{WS}"]" { |
169 | if (YY_START!=SC_blockcomment) { | |
170 | BEGIN(SC_TESTPORT_PARAMETERS); | |
171 | RETURN(TestportParametersKeyword); | |
172 | } | |
173 | } | |
174 | ||
175 | <*>"["{WS}EXECUTE{WS}"]" { | |
176 | if (YY_START!=SC_blockcomment) { | |
177 | BEGIN(SC_EXECUTE); | |
178 | RETURN(ExecuteKeyword); | |
179 | } | |
180 | } | |
181 | ||
182 | <*>"["{WS}EXTERNAL_COMMANDS{WS}"]" { | |
183 | if (YY_START!=SC_blockcomment) { | |
184 | BEGIN(SC_EXTERNAL_COMMANDS); | |
185 | RETURN(ExternalCommandsKeyword); | |
186 | } | |
187 | } | |
188 | ||
189 | <*>"["{WS}GROUPS{WS}"]" { | |
190 | if (YY_START!=SC_blockcomment) { | |
191 | BEGIN(SC_GROUPS); | |
192 | RETURN(GroupsKeyword); | |
193 | } | |
194 | } | |
195 | ||
196 | <*>"["{WS}COMPONENTS{WS}"]" { | |
197 | if (YY_START!=SC_blockcomment) { | |
198 | BEGIN(SC_COMPONENTS); | |
199 | RETURN(ComponentsKeyword); | |
200 | } | |
201 | } | |
202 | ||
203 | <*>"["{WS}MAIN_CONTROLLER{WS}"]" { | |
204 | if (YY_START!=SC_blockcomment) { | |
205 | BEGIN(SC_MAIN_CONTROLLER); | |
206 | RETURN(MainControllerKeyword); | |
207 | } | |
208 | } | |
209 | ||
210 | <*>"["{WS}INCLUDE{WS}"]" { | |
211 | if (YY_START!=SC_blockcomment) { | |
212 | BEGIN(SC_INCLUDE); | |
213 | RETURN(IncludeKeyword); | |
214 | } | |
215 | } | |
216 | ||
217 | <*>"["{WS}ORDERED_INCLUDE{WS}"]" { | |
218 | if (YY_START!=SC_blockcomment) { | |
219 | BEGIN(SC_ORDERED_INCLUDE); | |
220 | } | |
221 | } | |
222 | ||
223 | ||
224 | <*>"["{WS}DEFINE{WS}"]" { | |
225 | if (YY_START!=SC_blockcomment) { | |
226 | BEGIN(SC_DEFINE); | |
227 | RETURN(DefineKeyword); | |
228 | } | |
229 | } | |
230 | ||
231 | /* Rules for SC_DEFINE must precede everything else */ | |
232 | ||
233 | <SC_DEFINE>{ | |
234 | ||
235 | "/*" { | |
236 | comment_caller = SC_DEFINE; | |
237 | BEGIN(SC_blockcomment); | |
238 | } | |
239 | ||
240 | {CHARSTRING} /* eats string */ | |
241 | ||
242 | {LINECOMMENT} | |
243 | ||
244 | {NEWLINE} /* this is not in . */ | |
245 | ||
246 | \\\" | |
247 | ||
248 | . /* eats unnecessary things */ | |
249 | ||
250 | } | |
251 | ||
252 | <SC_ORDERED_INCLUDE>{ | |
253 | ||
254 | "/*" { | |
255 | comment_caller = YY_START; | |
256 | BEGIN(SC_blockcomment); | |
257 | } | |
258 | ||
259 | \" { BEGIN(SC_CSTRING); } | |
260 | ||
261 | {LINECOMMENT} | |
262 | ||
263 | {NEWLINE} /* this is not in . */ | |
264 | ||
265 | \\\" | |
266 | ||
267 | . /* eat unnecessary chars */ | |
268 | ||
269 | } | |
270 | ||
271 | ||
272 | <SC_CSTRING>{ | |
273 | ||
274 | \"\" cstring += '"'; | |
275 | ||
276 | \" { | |
277 | std::string error_msg = switch_lexer(include_chain, cstring, | |
278 | YY_CURRENT_BUFFER, yy_create_buffer, yy_switch_to_buffer, yylineno, | |
279 | YY_BUF_SIZE); | |
280 | if (error_msg.empty()) { | |
281 | BEGIN(INITIAL); | |
282 | } else { | |
283 | config_read_error(error_msg.c_str()); | |
284 | } | |
285 | ||
286 | cstring.clear(); | |
287 | } /* end of string */ | |
288 | ||
289 | \\[\\'"?] cstring += yytext[1]; /* backslash-quoted \ or " or ' or ? */ | |
290 | \\{NEWLINE} yylineno++; | |
291 | \\a cstring += '\a'; | |
292 | \\b cstring += '\b'; | |
293 | \\f cstring += '\f'; | |
294 | \\n cstring += '\n'; | |
295 | \\r cstring += '\r'; | |
296 | \\t cstring += '\t'; | |
297 | \\v cstring += '\v'; | |
298 | ||
299 | \\[0-7]{1,3} { | |
300 | unsigned int c; | |
301 | sscanf(yytext + 1, "%o", &c); | |
302 | if (c <= 255) cstring += c; | |
303 | else config_read_error("Invalid octal character code in string literal"); | |
304 | } | |
305 | ||
306 | \\x{HEX}{1,2} { | |
307 | unsigned int c; | |
308 | sscanf(yytext + 2, "%x", &c); | |
309 | cstring += c; | |
310 | } | |
311 | ||
312 | \\(x[^\\\"]|.) config_read_error("Invalid excape sequence in string literal."); | |
313 | ||
314 | {NEWLINE} { | |
315 | cstring.append(yytext, yyleng); | |
316 | yylineno++; | |
317 | } | |
318 | ||
319 | . { | |
320 | cstring += yytext[0]; | |
321 | } | |
322 | } | |
323 | /* SC_cstring */ | |
324 | ||
325 | ||
a38c6d4c | 326 | <SC_PROFILER>{HEX}+ { |
327 | /* numeric statistics filter (check this before checking NUMBERs) */ | |
328 | RETURN(ProfilerStatsFlag); | |
329 | } | |
330 | ||
331 | ||
970ed795 EL |
332 | /* Values */ |
333 | ||
334 | {NUMBER} { | |
335 | yylval.int_val = NULL; | |
336 | BN_dec2bn(&yylval.int_val, *yytext == '+' ? yytext + 1 : yytext); | |
3abe9331 | 337 | if (YY_START == SC_MODULE_PARAMETERS) { |
338 | RETURN(MPNumber); | |
339 | } | |
970ed795 EL |
340 | RETURN(Number); |
341 | } | |
342 | ||
343 | {FLOAT} { | |
344 | yylval.float_val = atof(yytext); | |
3abe9331 | 345 | if (YY_START == SC_MODULE_PARAMETERS) { |
346 | RETURN(MPFloat); | |
347 | } | |
970ed795 EL |
348 | RETURN(Float); |
349 | } | |
350 | ||
351 | {BITSTRING} RETURN(Bstring); | |
352 | ||
353 | {BITSTRINGMATCH} RETURN(BstringMatch); | |
354 | ||
355 | {BITSTRING_BAD} { | |
356 | config_read_error("Invalid bitstring value."); | |
357 | RETURN(Bstring); | |
358 | } | |
359 | ||
360 | {HEXSTRING} RETURN(Hstring); | |
361 | ||
362 | {HEXSTRINGMATCH} RETURN(HstringMatch); | |
363 | ||
364 | {HEXSTRING_BAD} { | |
365 | config_read_error("Invalid hexstring value."); | |
366 | RETURN(Hstring); | |
367 | } | |
368 | ||
369 | {OCTETSTRING} RETURN(Ostring); | |
370 | ||
371 | {OCTETSTRINGMATCH} RETURN(OstringMatch); | |
372 | ||
373 | {OCTETSTRING_BAD} { | |
374 | config_read_error("Invalid octetstring value."); | |
375 | RETURN(Ostring); | |
376 | } | |
377 | ||
378 | {BINSTRING_BAD} config_read_error("Invalid string value."); | |
379 | ||
380 | ' config_read_error("Unmatched ' character."); | |
381 | ||
382 | {CHARSTRING} { | |
383 | yylval.str_val = mcopystrn(yytext, yyleng); | |
3abe9331 | 384 | if (YY_START == SC_MODULE_PARAMETERS) { |
385 | RETURN(MPCstring); | |
386 | } | |
970ed795 EL |
387 | RETURN(Cstring); |
388 | } | |
389 | ||
390 | /* Section-wide keywords */ | |
391 | ||
392 | <SC_MODULE_PARAMETERS> | |
393 | { | |
394 | NULL RETURN(NULLKeyword); | |
395 | null RETURN(nullKeyword); | |
396 | char RETURN(CharKeyword); | |
397 | objid RETURN(ObjIdKeyword); | |
398 | omit RETURN(OmitKeyword); | |
399 | none | | |
400 | pass | | |
401 | inconc | | |
402 | fail | | |
403 | error RETURN(VerdictValue); | |
404 | complement RETURN(ComplementKeyword); | |
405 | "\.\." RETURN(DotDot); | |
406 | superset RETURN(SupersetKeyword); | |
407 | subset RETURN(SubsetKeyword); | |
408 | pattern RETURN(PatternKeyword); | |
409 | permutation RETURN(PermutationKeyword); | |
410 | length RETURN(LengthKeyword); | |
411 | ifpresent RETURN(IfpresentKeyword); | |
412 | infinity RETURN(InfinityKeyword); | |
413 | } | |
414 | ||
af710487 | 415 | <SC_MODULE_PARAMETERS,SC_LOGGING,SC_PROFILER> |
970ed795 EL |
416 | { |
417 | true | | |
418 | false RETURN(BooleanValue); | |
419 | } | |
420 | ||
421 | <SC_MODULE_PARAMETERS,SC_LOGGING,SC_TESTPORT_PARAMETERS> | |
422 | { | |
423 | mtc RETURN(MTCKeyword); | |
424 | system RETURN(SystemKeyword); | |
425 | } | |
426 | ||
427 | <SC_LOGGING> | |
428 | { | |
429 | [Ff]ile[Nn]ame | | |
430 | [Ll]og[Ff]ile RETURN(LogFile); | |
431 | ||
432 | [Ee]mergency[Ll]ogging RETURN(EmergencyLogging); | |
433 | ||
434 | [Ee]mergency[Ll]ogging[Bb]ehaviour RETURN(EmergencyLoggingBehaviour); | |
435 | ||
436 | [Bb]uffer[Aa]ll | | |
437 | [Bb]uffer[Ma]asked RETURN(EmergencyLoggingBehaviourValue); | |
438 | ||
439 | [Ee]mergency[Ll]ogging[Mm]ask RETURN(EmergencyLoggingMask); | |
440 | ||
441 | ||
442 | [Ff]ile[Mm]ask RETURN(FileMask); | |
443 | ||
444 | [Cc]onsole[Mm]ask RETURN(ConsoleMask); | |
445 | ||
446 | [Tt]ime[Ss]tamp[Ff]ormat RETURN(TimestampFormat); | |
447 | [Cc]onsole[Tt]ime[Ss]tamp[Ff]ormat RETURN(ConsoleTimestampFormat); | |
448 | ||
449 | [Ll]og[Ss]ource[Ii]nfo | | |
450 | [Ss]ource[Ii]nfo[Ff]ormat RETURN(SourceInfoFormat); | |
451 | ||
452 | [Aa]ppend[Ff]ile RETURN(AppendFile); | |
453 | ||
454 | [Ll]og[Ee]vent[Tt]ypes RETURN(LogEventTypes); | |
455 | ||
456 | [Ll]og[Ee]ntity[Nn]ame RETURN(LogEntityName); | |
457 | ||
458 | [Ll]og[Ff]ile[Ss]ize RETURN(LogFileSize); | |
459 | ||
460 | [Ll]og[Ff]ile[Nn]umber RETURN(LogFileNumber); | |
461 | ||
462 | [Dd]isk[Ff]ull[Aa]ction RETURN(DiskFullAction); | |
463 | ||
464 | [Mm]atching[Hh]ints RETURN(MatchingHints); | |
465 | ||
466 | [Ll]ogger[Pp]lugins RETURN(LoggerPlugins); | |
467 | ||
468 | LOG_NOTHING RETURN(LoggingBit); | |
469 | ||
470 | (TTCN_)?ACTION | | |
471 | (TTCN_)?DEBUG | | |
472 | (TTCN_)?DEFAULTOP | | |
473 | (TTCN_)?ERROR | | |
474 | (TTCN_)?EXECUTOR | | |
475 | (TTCN_)?FUNCTION | | |
476 | (TTCN_)?MATCHING | | |
477 | (TTCN_)?PARALLEL | | |
478 | (TTCN_)?PORTEVENT | | |
479 | (TTCN_)?STATISTICS | | |
480 | (TTCN_)?TESTCASE | | |
481 | (TTCN_)?TIMEROP | | |
482 | (TTCN_)?USER | | |
483 | (TTCN_)?VERDICTOP | | |
484 | (TTCN_)?WARNING | | |
485 | LOG_ALL RETURN(LoggingBitCollection); | |
486 | ||
487 | ACTION_UNQUALIFIED | | |
488 | DEBUG_ENCDEC | | |
3f84031e | 489 | DEBUG_FRAMEWORK | |
970ed795 EL |
490 | DEBUG_TESTPORT | |
491 | DEBUG_UNQUALIFIED | | |
3f84031e | 492 | DEBUG_USER | |
970ed795 EL |
493 | DEFAULTOP_ACTIVATE | |
494 | DEFAULTOP_DEACTIVATE | | |
495 | DEFAULTOP_EXIT | | |
496 | DEFAULTOP_UNQUALIFIED | | |
497 | ERROR_UNQUALIFIED | | |
498 | EXECUTOR_COMPONENT | | |
499 | EXECUTOR_CONFIGDATA | | |
500 | EXECUTOR_EXTCOMMAND | | |
501 | EXECUTOR_LOGOPTIONS | | |
502 | EXECUTOR_RUNTIME | | |
503 | EXECUTOR_UNQUALIFIED | | |
504 | FUNCTION_RND | | |
505 | FUNCTION_UNQUALIFIED | | |
506 | MATCHING_DONE | | |
507 | MATCHING_MCSUCCESS | | |
508 | MATCHING_MCUNSUCC | | |
509 | MATCHING_MMSUCCESS | | |
510 | MATCHING_MMUNSUCC | | |
511 | MATCHING_PCSUCCESS | | |
512 | MATCHING_PCUNSUCC | | |
513 | MATCHING_PMSUCCESS | | |
514 | MATCHING_PMUNSUCC | | |
515 | MATCHING_PROBLEM | | |
516 | MATCHING_TIMEOUT | | |
517 | MATCHING_UNQUALIFIED | | |
518 | PARALLEL_PORTCONN | | |
519 | PARALLEL_PORTMAP | | |
520 | PARALLEL_PTC | | |
521 | PARALLEL_UNQUALIFIED | | |
522 | PORTEVENT_DUALRECV | | |
523 | PORTEVENT_DUALSEND | | |
524 | PORTEVENT_MCRECV | | |
525 | PORTEVENT_MCSEND | | |
526 | PORTEVENT_MMRECV | | |
527 | PORTEVENT_MMSEND | | |
528 | PORTEVENT_MQUEUE | | |
529 | PORTEVENT_PCIN | | |
530 | PORTEVENT_PCOUT | | |
531 | PORTEVENT_PMIN | | |
532 | PORTEVENT_PMOUT | | |
533 | PORTEVENT_PQUEUE | | |
534 | PORTEVENT_STATE | | |
535 | PORTEVENT_UNQUALIFIED | | |
536 | STATISTICS_UNQUALIFIED | | |
537 | STATISTICS_VERDICT | | |
538 | TESTCASE_FINISH | | |
539 | TESTCASE_START | | |
540 | TESTCASE_UNQUALIFIED | | |
541 | TIMEROP_GUARD | | |
542 | TIMEROP_READ | | |
543 | TIMEROP_START | | |
544 | TIMEROP_STOP | | |
545 | TIMEROP_TIMEOUT | | |
546 | TIMEROP_UNQUALIFIED | | |
547 | USER_UNQUALIFIED | | |
548 | VERDICTOP_FINAL | | |
549 | VERDICTOP_GETVERDICT | | |
550 | VERDICTOP_SETVERDICT | | |
551 | VERDICTOP_UNQUALIFIED | | |
552 | WARNING_UNQUALIFIED RETURN(LoggingBit); | |
553 | ||
554 | [Tt][Ii][Mm][Ee] {yylval.ts_val=TSF_TIME; RETURN(TimestampValue);} | |
555 | [Dd][Aa][Tt][Ee][Tt][Ii][Mm][Ee] {yylval.ts_val=TSF_DATE_TIME; RETURN(TimestampValue);} | |
556 | [Ss][Ee][Cc][Oo][Nn][Dd][Ss] {yylval.ts_val=TSF_SEC; RETURN(TimestampValue);} | |
557 | ||
558 | [Nn][Oo][Nn][Ee] | | |
559 | [Ss][Ii][Nn][Gg][Ll][Ee] | | |
560 | [Ss][Tt][Aa][Cc][Kk] RETURN(SourceInfoValue); | |
561 | ||
562 | [Yy][Ee][Ss] | | |
563 | [Nn][Oo] RETURN(YesNo); | |
564 | ||
565 | [Dd]etailed RETURN(Detailed); | |
566 | [Cc]ompact RETURN(Compact); | |
567 | [Ss]ub[Cc]ategories RETURN(SubCategories); | |
568 | ||
569 | [Ee]rror RETURN(Error); | |
570 | ||
571 | [Ss]top RETURN(Stop); | |
572 | ||
573 | [Rr]etry RETURN(Re_try); | |
574 | ||
575 | [Dd]elete RETURN(Delete); | |
576 | } | |
577 | ||
af710487 | 578 | <SC_PROFILER> |
579 | { | |
a38c6d4c | 580 | [Dd]isable[Pp]rofiler RETURN(DisableProfilerKeyword); |
581 | [Dd]isable[Cc]overage RETURN(DisableCoverageKeyword); | |
582 | [Dd]ata[Bb]ase[Ff]ile RETURN(DatabaseFileKeyword); | |
583 | [Aa]ggregate[Dd]ata RETURN(AggregateDataKeyword); | |
584 | [Ss]tatistics[Ff]ile RETURN(StatisticsFileKeyword); | |
585 | [Dd]isable[Ss]tatistics RETURN(DisableStatisticsKeyword); | |
586 | [Ss]tatistics[Ff]ilter RETURN(StatisticsFilterKeyword); | |
587 | [Ss]tart[Aa]utomatically RETURN(StartAutomaticallyKeyword); | |
588 | [Nn]et[Ll]ine[Tt]imes RETURN(NetLineTimesKeyword); | |
589 | [Nn]et[Ff]unction[Tt]imes RETURN(NetFunctionTimesKeyword); | |
590 | ||
591 | /* statistics filters */ | |
592 | [Nn]umber[Oo]f[Ll]ines | | |
593 | [Ll]ine[Dd]ata[Rr]aw | | |
594 | [Ff]unc[Dd]ata[Rr]aw | | |
595 | [Ll]ine[Aa]vg[Rr]aw | | |
596 | [Ff]unc[Aa]vg[Rr]aw | | |
597 | [Ll]ine[Tt]imes[Ss]orted[Bb]y[Mm]od | | |
598 | [Ff]unc[Tt]imes[Ss]orted[Bb]y[Mm]od | | |
599 | [Ll]ine[Tt]imes[Ss]orted[Tt]otal | | |
600 | [Ff]unc[Tt]imes[Ss]orted[Tt]otal | | |
601 | [Ll]ine[Cc]ount[Ss]orted[Bb]y[Mm]od | | |
602 | [Ff]unc[Cc]ount[Ss]orted[Bb]y[Mm]od | | |
603 | [Ll]ine[Cc]ount[Ss]orted[Tt]otal | | |
604 | [Ff]unc[Cc]ount[Ss]orted[Tt]otal | | |
605 | [Ll]ine[Aa]vg[Ss]orted[Bb]y[Mm]od | | |
606 | [Ff]unc[Aa]vg[Ss]orted[Bb]y[Mm]od | | |
607 | [Ll]ine[Aa]vg[Ss]orted[Tt]otal | | |
608 | [Ff]unc[Aa]vg[Ss]orted[Tt]otal | | |
609 | [Tt]op10[Ll]ine[Tt]imes | | |
610 | [Tt]op10[Ff]unc[Tt]imes | | |
611 | [Tt]op10[Ll]ine[Cc]ount | | |
612 | [Tt]op10[Ff]unc[Cc]ount | | |
613 | [Tt]op10[Ll]ine[Aa]vg | | |
614 | [Tt]op10[Ff]unc[Aa]vg | | |
615 | [Uu]nused[Ll]ines | | |
616 | [Uu]nused[Ff]unc | | |
617 | [Aa]ll[Rr]aw[Dd]ata | | |
618 | [Ll]ine[Dd]ata[Ss]orted[Bb]y[Mm]od | | |
619 | [Ff]unc[Dd]ata[Ss]orted[Bb]y[Mm]od | | |
620 | [Ll]ine[Dd]ata[Ss]orted[Tt]otal | | |
621 | [Ff]unc[Dd]ata[Ss]orted[Tt]otal | | |
622 | [Ll]ine[Dd]ata[Ss]orted | | |
623 | [Ff]unc[Dd]ata[Ss]orted | | |
624 | [Aa]ll[Dd]ata[Ss]orted | | |
625 | [Tt]op10[Ll]ine[Dd]ata | | |
626 | [Tt]op10[Ff]unc[Dd]ata | | |
627 | [Tt]op10[Aa]ll[Dd]ata | | |
628 | [Uu]nused[Dd]ata | | |
629 | [Aa]ll RETURN(ProfilerStatsFlag); | |
af710487 | 630 | } |
631 | ||
970ed795 EL |
632 | <SC_EXECUTE>control RETURN(ControlKeyword); |
633 | ||
634 | <SC_EXTERNAL_COMMANDS> | |
635 | { | |
636 | [Bb]egin[Cc]ontrol[Pp]art RETURN(BeginControlPart); | |
637 | [Ee]nd[Cc]ontrol[Pp]art RETURN(EndControlPart); | |
638 | [Bb]egin[Tt]est[Cc]ase RETURN(BeginTestCase); | |
639 | [Ee]nd[Tt]est[Cc]ase RETURN(EndTestCase); | |
640 | } | |
641 | ||
642 | <SC_MAIN_CONTROLLER> | |
643 | { | |
644 | [Ll]ocal[Aa]ddress RETURN(LocalAddress); | |
645 | [Tt][Cc][Pp][Pp]ort RETURN(TCPPort); | |
646 | [Kk]ill[Tt]imer RETURN(KillTimer); | |
647 | [Nn]um[Hh][Cc]s RETURN(NumHCs); | |
648 | [Uu]nix[Ss]ockets[Ee]nabled RETURN(UnixSocketEnabled); | |
649 | [Yy][Ee][Ss] RETURN(YesToken); | |
650 | [Nn][Oo] RETURN(NoToken); | |
651 | } | |
652 | ||
653 | {TTCN3IDENTIFIER} { | |
654 | switch (YY_START) { | |
655 | case SC_GROUPS: | |
656 | case SC_COMPONENTS: | |
657 | case SC_EXECUTE: | |
658 | case SC_MAIN_CONTROLLER: | |
659 | yylval.str_val = (char*)Malloc(yyleng + 1); | |
660 | memcpy(yylval.str_val, yytext, yyleng + 1); | |
661 | break; | |
662 | default: | |
663 | yylval.str_val = NULL; | |
664 | } | |
665 | RETURN(Identifier); | |
666 | } | |
667 | ||
668 | <SC_MODULE_PARAMETERS>{ASN1LOWERIDENTIFIER} { | |
669 | char *ttcn3_id = (char*)Malloc(yyleng + 1); | |
3abe9331 | 670 | for (size_t i = 0; i < yyleng; i++) { |
970ed795 EL |
671 | if (yytext[i] == '-') ttcn3_id[i] = '_'; |
672 | else ttcn3_id[i] = yytext[i]; | |
673 | } | |
674 | ttcn3_id[yyleng] = '\0'; | |
675 | config_read_warning("`%s' is not a valid TTCN-3 identifier. Did you mean " | |
676 | "`%s'?", yytext, ttcn3_id); | |
677 | cfg->config_read_buffer = mputprintf(cfg->config_read_buffer, "%s ", ttcn3_id); | |
678 | Free(ttcn3_id); | |
679 | return ASN1LowerIdentifier; | |
680 | } | |
681 | ||
682 | <SC_GROUPS,SC_COMPONENTS,SC_MAIN_CONTROLLER>{DNSNAME}|{IPV6} { | |
683 | yylval.str_val = (char*)Malloc(yyleng + 1); | |
3abe9331 | 684 | for (size_t i = 0; i < yyleng; i++) yylval.str_val[i] = tolower(yytext[i]); |
970ed795 EL |
685 | yylval.str_val[yyleng] = '\0'; |
686 | RETURN(DNSName); | |
687 | } | |
688 | ||
689 | {MACRO_BOOL} { | |
690 | char *macroname = get_macro_id_from_ref(yytext); | |
691 | size_t macrolen; | |
692 | const char *macrovalue = | |
693 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
694 | boolean bool_val; | |
695 | if (macrovalue != NULL) { | |
696 | if (!strcmp(macrovalue, "true")) bool_val = TRUE; | |
697 | else if (!strcmp(macrovalue, "false")) bool_val = FALSE; | |
698 | else { | |
699 | config_read_error("Macro `%s' cannot be interpreted as boolean value: " | |
700 | "`%s'", macroname, macrovalue); | |
701 | bool_val = FALSE; | |
702 | } | |
703 | } else { | |
704 | config_read_error("No macro or environmental variable defined with name " | |
705 | "`%s'", macroname); | |
706 | bool_val = FALSE; | |
707 | } | |
708 | Free(macroname); | |
709 | if (whether_update_buffer()) cfg->config_read_buffer = | |
710 | mputprintf(cfg->config_read_buffer, "%s ", bool_val ? "true" : "false"); | |
711 | return BooleanValue; | |
712 | } | |
713 | ||
714 | {MACRO_INT} { | |
715 | char *macroname = get_macro_id_from_ref(yytext); | |
716 | size_t macrolen = 0; | |
717 | BIGNUM *BN_0 = BN_new(); | |
718 | BN_set_word(BN_0, 0); | |
719 | const char *macrovalue = | |
720 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
721 | if (macrovalue != NULL) { | |
722 | if (string_is_int(macrovalue, macrolen)) { | |
723 | yylval.int_val = NULL; | |
724 | BN_dec2bn(&yylval.int_val, | |
725 | *macrovalue == '+' ? macrovalue + 1 : macrovalue); | |
726 | } else { | |
727 | config_read_error("Macro `%s' cannot be interpreted as integer value: " | |
728 | "`%s'", macroname, macrovalue); | |
729 | yylval.int_val = BN_dup(BN_0); | |
730 | } | |
731 | } else { | |
732 | config_read_error("No macro or environmental variable defined with name " | |
733 | "`%s'", macroname); | |
734 | yylval.int_val = BN_dup(BN_0); | |
735 | } | |
736 | BN_free(BN_0); | |
737 | Free(macroname); | |
738 | char *int_val_str = BN_bn2dec(yylval.int_val); | |
739 | if (whether_update_buffer()) | |
740 | cfg->config_read_buffer = mputprintf(cfg->config_read_buffer, "%s ", int_val_str); | |
741 | OPENSSL_free(int_val_str); | |
3abe9331 | 742 | if (YY_START == SC_MODULE_PARAMETERS) { |
743 | return MPNumber; | |
744 | } | |
970ed795 EL |
745 | return Number; |
746 | } | |
747 | ||
748 | {MACRO_FLOAT} { | |
749 | char *macroname = get_macro_id_from_ref(yytext); | |
750 | size_t macrolen; | |
751 | const char *macrovalue = | |
752 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
753 | if (macrovalue != NULL) { | |
754 | if (string_is_float(macrovalue, macrolen)) | |
755 | yylval.float_val = atof(macrovalue); | |
756 | else { | |
757 | config_read_error("Macro `%s' cannot be interpreted as float value: " | |
758 | "`%s'", macroname, macrovalue); | |
759 | yylval.float_val = 0.0; | |
760 | } | |
761 | } else { | |
762 | config_read_error("No macro or environmental variable defined" | |
763 | " with name `%s'", macroname); | |
764 | yylval.float_val = 0.0; | |
765 | } | |
766 | Free(macroname); | |
767 | if (whether_update_buffer()) cfg->config_read_buffer = | |
768 | mputprintf(cfg->config_read_buffer, "%f ", yylval.float_val); | |
3abe9331 | 769 | if (YY_START == SC_MODULE_PARAMETERS) { |
770 | return MPFloat; | |
771 | } | |
970ed795 EL |
772 | return Float; |
773 | } | |
774 | ||
775 | {MACRO_ID} { | |
776 | char *macroname = get_macro_id_from_ref(yytext); | |
777 | size_t macrolen; | |
778 | const char *macrovalue = | |
779 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
780 | boolean is_asn = FALSE; | |
781 | if (macrovalue != NULL) { | |
782 | if (string_is_id(macrovalue, macrolen)) { | |
783 | yylval.str_val = mcopystr(macrovalue); | |
784 | for (size_t i = 0; i < macrolen; i++) { | |
785 | if (yylval.str_val[i] == '-') { | |
786 | is_asn = TRUE; | |
787 | yylval.str_val[i] = '_'; | |
788 | } | |
789 | } | |
790 | if (is_asn) config_read_warning("`%s' is not a valid TTCN-3 identifier. " | |
791 | "Did you mean `%s'?", macrovalue, yylval.str_val); | |
792 | if (whether_update_buffer()) cfg->config_read_buffer = | |
793 | mputprintf(cfg->config_read_buffer, "%s ", yylval.str_val); | |
794 | } else { | |
795 | config_read_error("Macro `%s' cannot be interpreted as identifier: `%s'", | |
796 | macroname, macrovalue); | |
797 | yylval.str_val = NULL; | |
798 | } | |
799 | } else { | |
800 | config_read_error("No macro or environmental variable defined with name " | |
801 | "`%s'", macroname); | |
802 | yylval.str_val = NULL; | |
803 | } | |
804 | Free(macroname); | |
805 | return Identifier; | |
806 | } | |
807 | ||
808 | {MACRO_CSTR} { | |
809 | char *macroname; | |
810 | if (yytext[1] == '{') macroname = get_macro_id_from_ref(yytext); | |
811 | else macroname = mcopystr(yytext + 1); | |
812 | size_t macrolen; | |
813 | const char *macrovalue = string_map_get_bykey | |
814 | (config_defines, macroname, ¯olen); | |
815 | if (macrovalue == NULL) { | |
816 | config_read_error("No macro or environmental variable defined with " | |
817 | "name `%s'", macroname); | |
818 | yylval.str_val = memptystr(); | |
819 | Free(macroname); | |
3abe9331 | 820 | if (YY_START == SC_MODULE_PARAMETERS) { |
821 | return MPCstring; | |
822 | } | |
970ed795 EL |
823 | return Cstring; |
824 | } | |
825 | ||
826 | if (macrolen > 0 && macrovalue[0] == '{') { // structured | |
827 | main_buffer = YY_CURRENT_BUFFER; | |
828 | expansion_buffer = yy_scan_string(macrovalue); | |
829 | yy_switch_to_buffer(expansion_buffer); | |
830 | Free(macroname); | |
831 | } else { | |
832 | if (whether_update_buffer()) { | |
833 | cfg->config_read_buffer=mputc(cfg->config_read_buffer, '"'); | |
834 | for (size_t i = 0; i < macrolen; i++) { | |
835 | switch (macrovalue[i]) { | |
836 | case '"': | |
837 | cfg->config_read_buffer = mputstr(cfg->config_read_buffer, "\\\""); | |
838 | break; | |
839 | case '\\': | |
840 | cfg->config_read_buffer = mputstr(cfg->config_read_buffer, "\\\\"); | |
841 | break; | |
842 | case '\0': | |
843 | cfg->config_read_buffer = mputstr(cfg->config_read_buffer, "\\000"); | |
844 | break; | |
845 | default: | |
846 | cfg->config_read_buffer = mputc(cfg->config_read_buffer, macrovalue[i]); | |
847 | } /* switch */ | |
848 | } /* for */ | |
849 | cfg->config_read_buffer=mputstr(cfg->config_read_buffer, "\" "); | |
850 | } | |
851 | Free(macroname); | |
852 | yylval.str_val = mcopystr(macrovalue); | |
3abe9331 | 853 | if (YY_START == SC_MODULE_PARAMETERS) { |
854 | return MPCstring; | |
855 | } | |
970ed795 EL |
856 | return Cstring; |
857 | } | |
858 | } | |
859 | ||
860 | {MACRO_BSTR} { | |
861 | char *macroname = get_macro_id_from_ref(yytext); | |
862 | size_t macrolen; | |
863 | const char *macrovalue = | |
864 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
865 | if (macrovalue != NULL) { | |
866 | if (string_is_bstr(macrovalue, macrolen)) { | |
867 | if (whether_update_buffer()) cfg->config_read_buffer = | |
868 | mputprintf(cfg->config_read_buffer, "'%s'B ", macrovalue); | |
869 | } else config_read_error("Macro `%s' cannot be interpreted as bitstring " | |
870 | "value: `%s'", macroname, macrovalue); | |
871 | } else config_read_error("No macro or environmental variable defined with " | |
872 | "name `%s'", macroname); | |
873 | Free(macroname); | |
874 | return Bstring; | |
875 | } | |
876 | ||
877 | {MACRO_HSTR} { | |
878 | char *macroname = get_macro_id_from_ref(yytext); | |
879 | size_t macrolen; | |
880 | const char *macrovalue = | |
881 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
882 | if (macrovalue != NULL) { | |
883 | if (string_is_hstr(macrovalue, macrolen)) { | |
884 | if (whether_update_buffer()) cfg->config_read_buffer = | |
885 | mputprintf(cfg->config_read_buffer, "'%s'H ", macrovalue); | |
886 | } else config_read_error("Macro `%s' cannot be interpreted as hexstring " | |
887 | "value: `%s'", macroname, macrovalue); | |
888 | } else config_read_error("No macro or environmental variable defined with " | |
889 | "name `%s'", macroname); | |
890 | Free(macroname); | |
891 | return Hstring; | |
892 | } | |
893 | ||
894 | {MACRO_OSTR} { | |
895 | char *macroname = get_macro_id_from_ref(yytext); | |
896 | size_t macrolen; | |
897 | const char *macrovalue = | |
898 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
899 | if (macrovalue != NULL) { | |
900 | if (string_is_ostr(macrovalue, macrolen)) { | |
901 | if (whether_update_buffer()) cfg->config_read_buffer = | |
902 | mputprintf(cfg->config_read_buffer, "'%s'O ", macrovalue); | |
903 | } else config_read_error("Macro `%s' cannot be interpreted as octetstring " | |
904 | "value: `%s'", macroname, macrovalue); | |
905 | } else config_read_error("No macro or environmental variable defined with " | |
906 | "name `%s'", macroname); | |
907 | Free(macroname); | |
908 | return Ostring; | |
909 | } | |
910 | ||
911 | {MACRO_BINARY} { | |
912 | char *macroname = get_macro_id_from_ref(yytext); | |
913 | size_t macrolen; | |
914 | const char *macrovalue = | |
915 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
916 | if (macrovalue != NULL) { | |
917 | if (whether_update_buffer()) { | |
918 | cfg->config_read_buffer = mputc(cfg->config_read_buffer, '\''); | |
919 | for (size_t i = 0; i < macrolen; i++) { | |
920 | cfg->config_read_buffer = mputprintf(cfg->config_read_buffer, "%02X", | |
921 | macrovalue[i]); | |
922 | } | |
923 | cfg->config_read_buffer = mputstr(cfg->config_read_buffer, "'O "); | |
924 | } | |
925 | } else config_read_error("No macro or environmental variable defined with " | |
926 | "name `%s'", macroname); | |
927 | Free(macroname); | |
928 | return Ostring; | |
929 | } | |
930 | ||
931 | {MACRO_HOSTNAME} { | |
932 | char *macroname = get_macro_id_from_ref(yytext); | |
933 | size_t macrolen; | |
934 | const char *macrovalue = | |
935 | string_map_get_bykey(config_defines, macroname, ¯olen); | |
936 | if (macrovalue != NULL) { | |
937 | if (string_is_hostname(macrovalue, macrolen)) { | |
938 | if (whether_update_buffer()) { | |
939 | for (size_t i = 0; i < macrolen; i++) { | |
940 | cfg->config_read_buffer = | |
941 | mputc(cfg->config_read_buffer, tolower(macrovalue[i])); | |
942 | } | |
943 | yylval.str_val = NULL; | |
944 | } else { | |
945 | yylval.str_val = (char*)Malloc(macrolen + 1); | |
946 | for (size_t i = 0; i < macrolen; i++) | |
947 | yylval.str_val[i] = tolower(macrovalue[i]); | |
948 | yylval.str_val[macrolen] = '\0'; | |
949 | } | |
950 | } else { | |
951 | config_read_error("Macro `%s' cannot be interpreted as host name: " | |
952 | "`%s'", macroname, macrovalue); | |
953 | yylval.str_val = NULL; | |
954 | } | |
955 | } else { | |
956 | config_read_error("No macro or environmental variable defined with " | |
957 | "name `%s'", macroname); | |
958 | yylval.str_val = NULL; | |
959 | } | |
960 | Free(macroname); | |
961 | return DNSName; | |
962 | } | |
963 | ||
964 | ":="|"=" RETURN(AssignmentChar); | |
965 | "&=" RETURN(ConcatChar); | |
966 | ||
967 | . RETURN(yytext[0]); | |
968 | ||
969 | <*><<EOF>> { | |
970 | if (expansion_buffer) { | |
971 | yy_switch_to_buffer(main_buffer); | |
972 | yy_delete_buffer(expansion_buffer); | |
973 | expansion_buffer = NULL; | |
974 | } else { | |
975 | if (YY_START == SC_blockcomment) { | |
976 | config_read_error("Unterminated block " | |
977 | "comment (missing */ at the end of file)."); | |
978 | return EOF; | |
979 | } else { | |
980 | if (include_chain->size() > 1) { | |
981 | yy_delete_buffer(YY_CURRENT_BUFFER); | |
982 | fclose(include_chain->back().fp); | |
983 | include_chain->pop_back(); | |
984 | yy_switch_to_buffer(include_chain->back().buffer_state); | |
985 | yylineno = include_chain->back().line_number; | |
986 | BEGIN(SC_ORDERED_INCLUDE); | |
987 | } else { | |
988 | return EOF; | |
989 | } | |
990 | } | |
991 | } | |
992 | } | |
993 | ||
994 | %% | |
995 | ||
996 | static void update_buffer() | |
997 | { | |
998 | if (whether_update_buffer()) { | |
999 | cfg->config_read_buffer = mputstr(cfg->config_read_buffer, yytext); | |
1000 | cfg->config_read_buffer = mputc (cfg->config_read_buffer, ' '); | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | static boolean whether_update_buffer() | |
1005 | { | |
1006 | switch (YY_START) { | |
1007 | case SC_MODULE_PARAMETERS: | |
1008 | case SC_LOGGING: | |
1009 | case SC_TESTPORT_PARAMETERS: | |
1010 | case SC_EXTERNAL_COMMANDS: | |
a38c6d4c | 1011 | case SC_PROFILER: |
970ed795 EL |
1012 | return TRUE; |
1013 | default: | |
1014 | return FALSE; | |
1015 | } /* switch */ | |
1016 | } | |
1017 | ||
1018 | void config_read_reset(const char* current_filename_) { | |
1019 | if (!include_chain) { | |
1020 | include_chain = new std::deque<IncludeElem<YY_BUFFER_STATE> >(); | |
1021 | } | |
1022 | ||
1023 | include_chain->clear(); | |
1024 | include_chain->push_back( | |
1025 | IncludeElem<YY_BUFFER_STATE>(std::string(current_filename_), config_read_in)); | |
1026 | } | |
1027 | ||
1028 | void config_read_close() { | |
1029 | delete include_chain; | |
1030 | include_chain = NULL; | |
1031 | } | |
1032 |