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