Line data Source code
1 : /*
2 : INI LIBRARY
3 :
4 : Parsing functions of the INI interface
5 :
6 : Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
7 :
8 : INI Library is free software: you can redistribute it and/or modify
9 : it under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation, either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : INI Library is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with INI Library. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "config.h"
23 : #include <stdio.h>
24 : /* For error text */
25 : #include <libintl.h>
26 : #define _(String) gettext (String)
27 : /* INI file is used as a collection */
28 : #include "trace.h"
29 : #include "collection.h"
30 : #include "collection_tools.h"
31 : #include "ini_defines.h"
32 : #include "ini_config_priv.h"
33 : #include "ini_configobj.h"
34 :
35 : /* Following declarations are from header file ini_config.h. This file was not
36 : * included, because we don't want on include header file
37 : * with old interface(ini_config.h) and new interface(ini_configobj.h)
38 : * into the one file.
39 : */
40 : void print_config_parsing_errors(FILE *file,
41 : struct collection_item *error_set);
42 :
43 :
44 : void print_file_parsing_errors(FILE *file,
45 : struct collection_item *error_list);
46 :
47 :
48 : /*============================================================*/
49 : /* The following classes moved here from the public header
50 : * They are reserved for future use.
51 : *
52 : * NOTE: before exposing these constants again in the common header
53 : * check that the class IDs did not get reused over time by
54 : * other classes.
55 : */
56 : /**
57 : * @brief Collection of error collections.
58 : *
59 : * When multiple files are read during one call
60 : * each file has its own set of parsing errors
61 : * and warnings. This is the collection
62 : * of such sets.
63 : */
64 : #define COL_CLASS_INI_PESET COL_CLASS_INI_BASE + 3
65 :
66 : /** @brief Collection of grammar errors.
67 : *
68 : * Reserved for future use.
69 : */
70 : #define COL_CLASS_INI_GERROR COL_CLASS_INI_BASE + 5
71 : /** @brief Collection of validation errors.
72 : *
73 : * Reserved for future use.
74 : */
75 : #define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 6
76 :
77 : /**
78 : * @}
79 : */
80 :
81 : /**
82 : * @defgroup gramerr Grammar errors and warnings
83 : *
84 : * Placeholder for now. Reserved for future use.
85 : *
86 : * @{
87 : */
88 : #define ERR_MAXGRAMMAR 0
89 : /**
90 : * @}
91 : */
92 :
93 : /**
94 : * @defgroup valerr Validation errors and warnings
95 : *
96 : * Placeholder for now. Reserved for future use.
97 : *
98 : * @{
99 : */
100 : #define ERR_MAXVALID 0
101 :
102 :
103 : /**
104 : * @}
105 : */
106 :
107 :
108 : #ifdef HAVE_VALIDATION
109 :
110 : /** @brief Collection of lines from the INI file.
111 : *
112 : * Reserved for future use
113 : */
114 : #define COL_CLASS_INI_LINES COL_CLASS_INI_BASE + 7
115 :
116 : #endif /* HAVE_VALIDATION */
117 : /*============================================================*/
118 :
119 :
120 : /* Function to return parsing error */
121 91 : static const char *parsing_error_str(int parsing_error)
122 : {
123 91 : const char *placeholder= _("Unknown pasing error.");
124 1365 : const char *str_error[] = { _("Data is too long."),
125 91 : _("No closing bracket."),
126 91 : _("Section name is missing."),
127 91 : _("Section name is too long."),
128 91 : _("Equal sign is missing."),
129 91 : _("Property name is missing."),
130 91 : _("Property name is too long."),
131 91 : _("Failed to read line."),
132 91 : _("Invalid space character at the "
133 : "beginning of the line."),
134 91 : _("Duplicate key is not allowed."),
135 91 : _("Duplicate key is detected while "
136 : "merging sections."),
137 91 : _("Duplicate section is not allowed."),
138 91 : _("Invalid character at the "
139 : "beginning of the line."),
140 91 : _("Invalid tab character at the "
141 : "beginning of the line."),
142 91 : _("Incomplete comment at the "
143 : "end of the file.")
144 : };
145 :
146 : /* Check the range */
147 91 : if ((parsing_error < 1) || (parsing_error > ERR_MAXPARSE))
148 : return placeholder;
149 : else
150 91 : return str_error[parsing_error-1];
151 : }
152 :
153 : /* Function to return grammar error.
154 : * This function is currently not used.
155 : * It is planned to be used by the INI
156 : * file grammar parser.
157 : *
158 : * The following doxygen description is moved here.
159 : * When the function gets exposed move it into
160 : * the header file.
161 : */
162 : /** @brief Function to return a grammar error in template.
163 : *
164 : * EXPERIMENTAL. Reserved for future use.
165 : *
166 : * This error is returned when the template
167 : * is translated into the grammar object.
168 : *
169 : * @param[in] grammar_error Error code for the grammar error.
170 : *
171 : * @return Error string.
172 : */
173 :
174 0 : static const char *grammar_error_str(int grammar_error)
175 : {
176 0 : const char *placeholder= _("Unknown grammar error.");
177 : /* THIS IS A TEMPORARY PLACEHOLDER !!!! */
178 0 : const char *str_error[] = { _(""),
179 0 : _(""),
180 0 : _(""),
181 0 : _(""),
182 0 : _(""),
183 0 : _(""),
184 0 : _("")
185 : };
186 :
187 : /* Check the range */
188 : if ((grammar_error < 1) || (grammar_error > ERR_MAXGRAMMAR))
189 : return placeholder;
190 : else
191 : return str_error[grammar_error-1];
192 : }
193 :
194 : /* Function to return validation error.
195 : * This function is currently not used.
196 : * It is planned to be used by the INI
197 : * file grammar validator.
198 : *
199 : * The following doxygen description is moved here.
200 : * When the function gets exposed move it into
201 : * the header file.
202 : */
203 : /** @brief Function to return a validation error.
204 : *
205 : * EXPERIMENTAL. Reserved for future use.
206 : *
207 : * This is the error that it is returned when
208 : * the INI file is validated against the
209 : * grammar object.
210 : *
211 : * @param[in] validation_error Error code for the validation error.
212 : *
213 : * @return Error string.
214 : */
215 0 : static const char *validation_error_str(int validation_error)
216 : {
217 0 : const char *placeholder= _("Unknown validation error.");
218 : /* THIS IS A TEMPORARY PLACEHOLDER !!!! */
219 0 : const char *str_error[] = { _(""),
220 0 : _(""),
221 0 : _(""),
222 0 : _(""),
223 0 : _(""),
224 0 : _(""),
225 0 : _("")
226 : };
227 :
228 : /* Check the range */
229 : if ((validation_error < 1) || (validation_error > ERR_MAXVALID))
230 : return placeholder;
231 : else
232 : return str_error[validation_error-1];
233 : }
234 :
235 : /* Wrapper to print errors */
236 91 : const char *ini_get_error_str(int error, int family)
237 : {
238 : const char *val;
239 : TRACE_FLOW_ENTRY();
240 :
241 91 : switch(family) {
242 : case INI_FAMILY_PARSING:
243 91 : val = parsing_error_str(error);
244 91 : break;
245 : case INI_FAMILY_VALIDATION:
246 0 : val = validation_error_str(error);
247 0 : break;
248 : case INI_FAMILY_GRAMMAR:
249 0 : val = grammar_error_str(error);
250 0 : break;
251 : default:
252 0 : val = _("Unknown error category.");
253 0 : break;
254 : }
255 :
256 : TRACE_FLOW_EXIT();
257 91 : return val;
258 : }
259 :
260 : /* Internal function that prints errors */
261 0 : static void print_error_list(FILE *file,
262 : struct collection_item *error_list,
263 : int cclass,
264 : char *wrong_col_error,
265 : char *failed_to_process,
266 : char *error_header,
267 : char *line_format,
268 : int family)
269 : {
270 : struct collection_iterator *iterator;
271 : int error;
272 0 : struct collection_item *item = NULL;
273 : struct ini_parse_error *pe;
274 : unsigned int count;
275 :
276 : TRACE_FLOW_STRING("print_error_list", "Entry");
277 :
278 : /* If we have something to print print it */
279 0 : if (error_list == NULL) {
280 : TRACE_ERROR_STRING("No error list","");
281 0 : return;
282 : }
283 :
284 : /* Make sure we go the right collection */
285 0 : if (!col_is_of_class(error_list, cclass)) {
286 : TRACE_ERROR_STRING("Wrong collection class:", wrong_col_error);
287 0 : fprintf(file,"%s\n", wrong_col_error);
288 0 : return;
289 : }
290 :
291 : /* Bind iterator */
292 0 : error = col_bind_iterator(&iterator, error_list, COL_TRAVERSE_DEFAULT);
293 0 : if (error) {
294 : TRACE_ERROR_STRING("Error (bind):", failed_to_process);
295 0 : fprintf(file, "%s\n", failed_to_process);
296 0 : return;
297 : }
298 :
299 : while(1) {
300 : /* Loop through a collection */
301 0 : error = col_iterate_collection(iterator, &item);
302 0 : if (error) {
303 : TRACE_ERROR_STRING("Error (iterate):", failed_to_process);
304 0 : fprintf(file, "%s\n", failed_to_process);
305 0 : col_unbind_iterator(iterator);
306 0 : return;
307 : }
308 :
309 : /* Are we done ? */
310 0 : if (item == NULL) break;
311 :
312 : /* Process collection header */
313 0 : if (col_get_item_type(item) == COL_TYPE_COLLECTION) {
314 0 : col_get_collection_count(item, &count);
315 0 : if (count <= 2) break;
316 0 : } else if (col_get_item_type(item) == COL_TYPE_STRING) {
317 0 : fprintf(file, error_header, (char *)col_get_item_data(item));
318 : }
319 : else {
320 : /* Put error into provided format */
321 0 : pe = (struct ini_parse_error *)(col_get_item_data(item));
322 0 : fprintf(file, line_format,
323 : col_get_item_property(item, NULL), /* Error or warning */
324 : pe->error, /* Error */
325 : pe->line, /* Line */
326 : ini_get_error_str(pe->error,
327 : family)); /* Error str */
328 : }
329 :
330 : }
331 :
332 : /* Do not forget to unbind iterator - otherwise there will be a leak */
333 0 : col_unbind_iterator(iterator);
334 :
335 : TRACE_FLOW_STRING("print_error_list", "Exit");
336 : }
337 :
338 : /* Print errors and warnings that were detected while parsing one file */
339 0 : void print_file_parsing_errors(FILE *file,
340 : struct collection_item *error_list)
341 : {
342 0 : print_error_list(file,
343 : error_list,
344 : COL_CLASS_INI_PERROR,
345 : WRONG_COLLECTION,
346 : FAILED_TO_PROCCESS,
347 : ERROR_HEADER,
348 : LINE_FORMAT,
349 : INI_FAMILY_PARSING);
350 0 : }
351 :
352 :
353 : void print_grammar_errors(FILE *file,
354 : struct collection_item *error_list);
355 : /* Print errors and warnings that were detected while processing grammar.
356 : *
357 : * The following doxygen description is moved here.
358 : * When the function gets exposed move it into
359 : * the header file and remove prototype from this file.
360 : */
361 : /**
362 : * @brief Print errors and warnings that were detected while
363 : * checking grammar of the template.
364 : *
365 : * EXPERIMENTAL. Reserved for future use.
366 : *
367 : * @param[in] file File descriptor.
368 : * @param[in] error_list List of the parsing errors.
369 : *
370 : */
371 0 : void print_grammar_errors(FILE *file,
372 : struct collection_item *error_list)
373 : {
374 0 : print_error_list(file,
375 : error_list,
376 : COL_CLASS_INI_GERROR,
377 : WRONG_GRAMMAR,
378 : FAILED_TO_PROC_G,
379 : ERROR_HEADER_G,
380 : LINE_FORMAT,
381 : INI_FAMILY_GRAMMAR);
382 0 : }
383 :
384 : void print_validation_errors(FILE *file,
385 : struct collection_item *error_list);
386 : /* Print errors and warnings that were detected while validating INI file.
387 : *
388 : * The following doxygen description is moved here.
389 : * When the function gets exposed move it into
390 : * the header file and remove prototype from this file.
391 : */
392 : /**
393 : * @brief Print errors and warnings that were detected while
394 : * checking INI file against the grammar object.
395 : *
396 : * EXPERIMENTAL. Reserved for future use.
397 : *
398 : * @param[in] file File descriptor.
399 : * @param[in] error_list List of the parsing errors.
400 : *
401 : */
402 0 : void print_validation_errors(FILE *file,
403 : struct collection_item *error_list)
404 : {
405 0 : print_error_list(file,
406 : error_list,
407 : COL_CLASS_INI_VERROR,
408 : WRONG_VALIDATION,
409 : FAILED_TO_PROC_V,
410 : ERROR_HEADER_V,
411 : LINE_FORMAT,
412 : INI_FAMILY_VALIDATION);
413 0 : }
414 :
415 : /* Print errors and warnings that were detected while parsing
416 : * the whole configuration */
417 0 : void print_config_parsing_errors(FILE *file,
418 : struct collection_item *error_list)
419 : {
420 : struct collection_iterator *iterator;
421 : int error;
422 0 : struct collection_item *item = NULL;
423 0 : struct collection_item *file_errors = NULL;
424 :
425 : TRACE_FLOW_STRING("print_config_parsing_errors", "Entry");
426 :
427 : /* If we have something to print print it */
428 0 : if (error_list == NULL) {
429 : TRACE_ERROR_STRING("No error list", "");
430 0 : return;
431 : }
432 :
433 : /* Make sure we go the right collection */
434 0 : if (!col_is_of_class(error_list, COL_CLASS_INI_PESET)) {
435 : TRACE_ERROR_STRING("Wrong collection class:", WRONG_COLLECTION);
436 0 : fprintf(file, "%s\n", WRONG_COLLECTION);
437 0 : return;
438 : }
439 :
440 : /* Bind iterator */
441 0 : error = col_bind_iterator(&iterator, error_list, COL_TRAVERSE_DEFAULT);
442 0 : if (error) {
443 : TRACE_ERROR_STRING("Error (bind):", FAILED_TO_PROCCESS);
444 0 : fprintf(file,"%s\n", FAILED_TO_PROCCESS);
445 0 : return;
446 : }
447 :
448 : while(1) {
449 : /* Loop through a collection */
450 0 : error = col_iterate_collection(iterator, &item);
451 0 : if (error) {
452 : TRACE_ERROR_STRING("Error (iterate):", FAILED_TO_PROCCESS);
453 0 : fprintf(file, "%s\n", FAILED_TO_PROCCESS);
454 0 : col_unbind_iterator(iterator);
455 0 : return;
456 : }
457 :
458 : /* Are we done ? */
459 0 : if (item == NULL) break;
460 :
461 : /* Print per file sets of errors */
462 0 : if (col_get_item_type(item) == COL_TYPE_COLLECTIONREF) {
463 : /* Extract a sub collection */
464 0 : error = col_get_reference_from_item(item, &file_errors);
465 0 : if (error) {
466 : TRACE_ERROR_STRING("Error (extract):", FAILED_TO_PROCCESS);
467 0 : fprintf(file, "%s\n", FAILED_TO_PROCCESS);
468 0 : col_unbind_iterator(iterator);
469 0 : return;
470 : }
471 0 : print_file_parsing_errors(file, file_errors);
472 0 : col_destroy_collection(file_errors);
473 : }
474 : }
475 :
476 : /* Do not forget to unbind iterator - otherwise there will be a leak */
477 0 : col_unbind_iterator(iterator);
478 :
479 : TRACE_FLOW_STRING("print_config_parsing_errors", "Exit");
480 : }
481 :
482 : /* Function to print errors from the list */
483 0 : void ini_config_print_errors(FILE *file, char **error_list)
484 : {
485 0 : unsigned count = 0;
486 :
487 : TRACE_FLOW_ENTRY();
488 :
489 0 : if (!error_list) {
490 : TRACE_FLOW_STRING("List is empty.", "");
491 : return;
492 : }
493 :
494 0 : while (error_list[count]) {
495 0 : fprintf(file, "%s\n", error_list[count]);
496 0 : count++;
497 : }
498 :
499 : TRACE_FLOW_EXIT();
500 : return;
501 : }
|