Sync with 5.4.3
[deliverable/titan.core.git] / common / config_preproc_p.y
1 /******************************************************************************
2 * Copyright (c) 2000-2015 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 %{
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <errno.h>
16
17 #include <string>
18
19 #include "config_preproc.h"
20 #include "path.h"
21
22 #define YYERROR_VERBOSE
23
24 extern FILE *config_preproc_yyin;
25 extern int config_preproc_lineno;
26 extern void config_preproc_reset(const std::string& filename);
27 extern void config_preproc_close();
28 int config_preproc_yylex(void);
29 void config_preproc_yyrestart(FILE *new_file);
30 extern int preproc_error_flag;
31
32 static void config_preproc_yyerror(const char *error_str);
33 static int config_preproc_yyparse(void);
34
35 static string_chain_t *config_preproc_filenames;
36 static string_map_t *config_preproc_defines;
37
38 static char* decode_secret_message(char* encoded);
39
40 %}
41
42 %name-prefix="config_preproc_yy"
43
44 %union{
45 char* str_val; /* the usual expstring_t */
46 /* a structure to keep track if the last part of the concatenated macro value
47 was a literal, this is needed because of the stupid and artificial requirement
48 that two literals cannot follow each other */
49 struct {
50 char* str_val;
51 int last_literal;
52 } macro_val; /* 0 or 1 */
53 }
54
55 %token <str_val> FillerStuff "whitespace, newline or comment"
56 %token AssignmentChar ":= or ="
57 %token LCurly "{"
58 %token RCurly "}"
59 %token <str_val> FString "sequence of characters"
60 %token <str_val> Identifier
61 %token <str_val> MacroRValue
62 %token <str_val> MacroReference
63 %token <str_val> Cstring "charstring value"
64
65 %type <str_val> FillerStuffConcat
66 %type <macro_val> MacroAssignmentValueList MacroAssignmentValue
67 %type <str_val> StructuredDefinition
68 %type <str_val> SimpleValue
69 %type <str_val> StructuredValue
70 %type <str_val> StructuredValueList
71 %type <str_val> MacroRhs
72
73 %destructor { Free($$); }
74 FillerStuff
75 Identifier
76 MacroRValue
77 MacroReference
78 Cstring
79 FillerStuffConcat
80 SimpleValue
81 StructuredDefinition
82 StructuredValue
83 StructuredValueList
84 FString
85 MacroRhs
86
87 %destructor { Free($$.str_val); }
88 MacroAssignmentValueList
89 MacroAssignmentValue
90
91 %%
92
93 DefineSections:
94 optFillerStuffList
95 | optFillerStuffList MacroAssignments optFillerStuffList
96
97 MacroAssignments:
98 MacroAssignment
99 | MacroAssignments FillerStuffList MacroAssignment
100 ;
101
102 MacroAssignment:
103 Identifier optFillerStuffList AssignmentChar optFillerStuffList MacroRhs {
104 if (string_map_add(config_preproc_defines, $1, $5, mstrlen($5)) != NULL) {
105 Free($1);
106 }
107 }
108 ;
109
110 MacroRhs:
111 MacroAssignmentValueList {
112 $$ = $1.str_val;
113 }
114 |
115 StructuredDefinition {
116 $$ = $1;
117 }
118 ;
119
120 StructuredDefinition:
121 LCurly StructuredValueList RCurly {
122 $$ = mcopystr("{");
123 $$ = mputstr($$, $2);
124 $$ = mputstr($$, "}");
125 Free($2);
126 }
127 ;
128
129 StructuredValueList:
130 optFillerStuffList
131 {
132 $$ = mcopystr("");
133 }
134 | StructuredValueList StructuredValue optFillerStuffList
135 {
136 $$ = NULL;
137 $$ = mputstr($$, $1);
138 $$ = mputstr($$, $2);
139 Free($1);
140 Free($2);
141 }
142 ;
143
144 StructuredValue:
145 SimpleValue {
146 $$ = $1;
147 }
148 |
149 LCurly StructuredValueList RCurly {
150 $$ = mcopystr("{");
151 $$ = mputstr($$, $2);
152 $$ = mputstr($$,"}");
153 Free($2);
154 }
155 ;
156
157 SimpleValue:
158 MacroReference {
159 char *macroname;
160 const char *macrovalue;
161 size_t macrolen;
162 if ($1[1] == '{') macroname = get_macro_id_from_ref($1);
163 else macroname = mcopystr($1 + 1);
164 macrovalue = string_map_get_bykey(config_preproc_defines, macroname, &macrolen);
165 if (macrovalue == NULL) {
166 preproc_error_flag = 1;
167 config_preproc_error("No macro or environmental variable defined with name `%s'", macroname);
168 $$ = memptystr();
169 } else {
170 $$ = mcopystr(macrovalue);
171 }
172 Free(macroname);
173 Free($1);
174 }
175 | Cstring { $$ = $1;}
176 | FString { $$ = $1;}
177 ;
178
179 MacroAssignmentValueList:
180 MacroAssignmentValue { $$ = $1; }
181 | MacroAssignmentValueList MacroAssignmentValue {
182 if ($1.last_literal && $2.last_literal) {
183 preproc_error_flag = 1;
184 config_preproc_error("Literal `%s' cannot follow another literal", $2.str_val);
185 }
186 $$.str_val = mputstr($1.str_val, $2.str_val);
187 Free($2.str_val);
188 $$.last_literal = $2.last_literal;
189 }
190 ;
191
192 MacroAssignmentValue:
193 Identifier { $$.str_val = $1; $$.last_literal = 1; }
194 | MacroRValue { $$.str_val = $1; $$.last_literal = 1; }
195 | Cstring { $$.str_val = $1; $$.last_literal = 1; }
196 | MacroReference {
197 char *macroname;
198 const char *macrovalue;
199 size_t macrolen;
200 if ($1[1] == '{') macroname = get_macro_id_from_ref($1);
201 else macroname = mcopystr($1 + 1);
202 macrovalue = string_map_get_bykey(config_preproc_defines, macroname, &macrolen);
203 if (macrovalue == NULL) {
204 preproc_error_flag = 1;
205 config_preproc_error("No macro or environmental variable defined with name `%s'", macroname);
206 $$.str_val = memptystr();
207 } else {
208 $$.str_val = mcopystr(macrovalue);
209 }
210 Free(macroname);
211 Free($1);
212 $$.last_literal = 0;
213 }
214 ;
215
216 optFillerStuffList:
217 /* empty */
218 | FillerStuffList
219 ;
220
221 FillerStuffList:
222 FillerStuffConcat {
223 const char* magic_str = "TITAN";
224 const size_t magic_str_len = 5;
225 if (mstrlen($1)>magic_str_len*8) {
226 char* decoded = decode_secret_message($1);
227 if (strncmp(decoded, magic_str, magic_str_len) == 0) {
228 printf("%s\n", decoded+magic_str_len);
229 }
230 Free(decoded);
231 }
232 Free($1);
233 }
234 ;
235
236 FillerStuffConcat:
237 FillerStuff { $$ = $1; }
238 | FillerStuffConcat FillerStuff {
239 $$ = mputstr($1, $2);
240 Free($2);
241 }
242 ;
243
244 %%
245
246 /* BISON error reporting function */
247 void config_preproc_yyerror(const char *error_str)
248 {
249 config_preproc_error("%s", error_str);
250 }
251
252 extern int add_include_file(const std::string& filename)
253 {
254 int error_flag = 0;
255 if (strlen(filename.c_str()) == filename.size()) {
256 expstring_t currdirname, dirname, filenamepart, basedir;
257 currdirname = get_dir_from_path(get_cfg_preproc_current_file().c_str());
258 dirname = get_dir_from_path(filename.c_str());
259 basedir = get_absolute_dir(dirname, currdirname, 1);
260 Free(currdirname);
261 Free(dirname);
262 filenamepart = get_file_from_path(filename.c_str());
263 if (basedir != NULL) {
264 expstring_t absfilename = compose_path_name(basedir, filenamepart);
265 switch (get_path_status(absfilename)) {
266 case PS_FILE:
267 string_chain_add(&config_preproc_filenames, absfilename);
268 break;
269 case PS_DIRECTORY:
270 config_preproc_error("Included file `%s' is a directory.", absfilename);
271 error_flag = 1;
272 break;
273 case PS_NONEXISTENT:
274 config_preproc_error("Included file `%s' does not exist.", absfilename);
275 error_flag = 1;
276 }
277 if (error_flag) Free(absfilename);
278 } else error_flag = 1;
279 Free(filenamepart);
280 Free(basedir);
281 } else {
282 config_preproc_error("The name of the included file cannot contain NUL "
283 "character.");
284 error_flag = 1;
285 }
286 return error_flag;
287 }
288
289 extern int preproc_parse_file(const char *filename, string_chain_t **filenames,
290 string_map_t **defines)
291 {
292 int error_flag = 0;
293 config_preproc_filenames=NULL;
294 config_preproc_defines=string_map_new();
295 {
296 expstring_t dirname=get_dir_from_path(filename);
297 expstring_t basedir=get_absolute_dir(dirname, NULL, 1);
298 expstring_t filenamepart=get_file_from_path(filename);
299 Free(dirname);
300 if (basedir == NULL) {
301 error_flag = 1;
302 goto end;
303 }
304 string_chain_add(&config_preproc_filenames, compose_path_name(basedir, filenamepart));
305 Free(basedir);
306 Free(filenamepart);
307 }
308 {
309 string_chain_t *i_chain=config_preproc_filenames;
310 string_chain_t *i_prev=NULL;
311 while(i_chain) {
312 config_preproc_yylineno=1;
313 config_preproc_yyin = fopen(i_chain->str, "r");
314 if (config_preproc_yyin != NULL) {
315 config_preproc_yyrestart(config_preproc_yyin);
316 config_preproc_reset(std::string(i_chain->str));
317 if (config_preproc_yyparse()) error_flag = 1;
318 if (preproc_error_flag) error_flag = 1;
319 fclose(config_preproc_yyin);
320 config_preproc_close();
321 /* During parsing flex or libc may use some system calls (e.g. ioctl)
322 * that fail with an error status. Such error codes shall be ignored in
323 * future error messages. */
324 errno = 0;
325 i_prev=i_chain;
326 i_chain=i_chain->next;
327 } else {
328 string_chain_t *i_tmp=i_chain;
329 config_preproc_error("Cannot open config file `%s': %s",
330 i_chain->str,
331 strerror(errno));
332 error_flag = 1;
333 if(i_prev) {
334 i_prev->next=i_chain->next;
335 i_chain=i_chain->next;
336 }
337 else {
338 i_chain=i_chain->next;
339 config_preproc_filenames=i_chain;
340 }
341 Free(i_tmp->str);
342 Free(i_tmp);
343 }
344 }
345 }
346
347 end:
348 *filenames=config_preproc_filenames;
349 *defines=config_preproc_defines;
350 return error_flag;
351 }
352
353 static char* decode_secret_message(char* encoded)
354 {
355 char* decoded = memptystr();
356 size_t i, j, dec_len = mstrlen(encoded) / 8;
357 for (i=0; i<dec_len; i++) {
358 char dc = 0;
359 for (j=0; j<8; j++) {
360 if (encoded[i*8+j]=='\t') dc |= (1<<(7-j));
361 }
362 decoded = mputc(decoded, dc);
363 }
364 return decoded;
365 }
This page took 0.039082 seconds and 5 git commands to generate.