1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /**************************************************************************
15 the idea with this file is to create something similar to the ms-windows
17 however the interface is nice. ie:
18 secfile_lookup_str(file, "player%d.unit%d.name", plrno, unitno);
19 ***************************************************************************/
21 /**************************************************************************
22 Description of the file format:
23 (This is based on a format by the original authors, with
24 various incremental extensions. --dwp)
26 - Whitespace lines are ignored, as are lines where the first
27 non-whitespace character is ';' (comment lines).
28 Optionally '#' can also be used for comments.
32 includes the named file at that point. (The '*' must be the
33 first character on the line.) The file is found by looking in
34 FREECIV_DATA_PATH. Non-infinite recursive includes are allowed.
36 - A line with "[name]" labels the start of a section with
37 that name; one of these must be the first non-comment line in
38 the file. Any spaces within the brackets are included in the
39 name, but this feature (?) should probably not be used...
41 - Within a section, lines have one of the following forms:
42 subname = "stringvalue"
47 for a value with given name and string, negative integer, and
48 positive integer values, respectively. These entries are
49 referenced in the following functions as "sectionname.subname".
50 The section name should not contain any dots ('.'); the subname
51 can, but they have no particular significance. There can be
52 optional whitespace before and/or after the equals sign.
53 You can put a newline after (but not before) the equals sign.
55 Backslash is an escape character in strings (double-quoted strings
56 only, not names); recognised escapes are \n, \\, and \".
57 (Any other \<char> is just treated as <char>.)
59 - Gettext markings: You can surround strings like so:
60 foo = _("stringvalue")
61 The registry just ignores these extra markings, but this is
62 useful for marking strings for translations via gettext tools.
64 - Multiline strings: Strings can have embeded newlines, eg:
69 This is equivalent to:
70 foo = _("\nThis is a string\nover multiple lines\n")
71 Note that if you missplace the trailing doublequote you can
72 easily end up with strange errors reading the file...
74 - Strings read from a file: A file can be read as a string value:
77 - Vector format: An entry can have multiple values separated
80 These are accessed by names "foo", "foo,1" and "foo,2"
81 (with section prefix as above). So the above is equivalent to:
85 As in the example, in principle you can mix integers and strings,
86 but the calling program will probably require elements to be the
87 same type. Note that the first element of a vector is not "foo,0",
88 in order that the name of the first element is the same whether or
89 not there are subsequent elements. However as a convenience, if
90 you try to lookup "foo,0" then you get back "foo". (So you should
91 never have "foo,0" as a real name in the datafile.)
93 - Tabular format: The lines:
94 foo = { "bar", "baz", "bax"
97 "hmm", 314, 99, 33, 11
99 are equivalent to the following:
110 The first line specifies the base name and the column names, and the
111 subsequent lines have data. Again it is possible to mix string and
112 integer values in a column, and have either more or less values
113 in a row than there are column headings, but the code which uses
114 this information (via the registry) may set more stringent conditions.
115 If a row has more entries than column headings, the last column is
116 treated as a vector (as above). You can optionally put a newline
117 after '=' and/or after '{'.
119 The equivalence above between the new and old formats is fairly
120 direct: internally, data is converted to the old format.
121 In principle it could be a good idea to represent the data
122 as a table (2-d array) internally, but the current method
123 seems sufficient and relatively simple...
125 There is a limited ability to save data in tabular:
126 So long as the section_file is constructed in an expected way,
127 tabular data (with no missing or extra values) can be saved
128 in tabular form. (See section_file_save().)
130 - Multiline vectors: if the last non-comment non-whitespace
131 character in a line is a comma, the line is considered to
132 continue on to the next line. Eg:
136 This is equivalent to the original "vector format" example above.
137 Such multi-lines can occur for column headings, vectors, or
138 table rows, again with some potential for strange errors...
140 ***************************************************************************/
142 /**************************************************************************
143 Hashing registry lookups: (by dwp)
144 - Have a hash table direct to entries, bypassing sections division.
145 - For convenience, store the key (the full section+entry name)
146 in the hash table (some memory overhead).
147 - The number of entries is fixed when the hash table is built.
149 **************************************************************************/
152 #include <fc_config.h>
161 #include "deprecations.h"
163 #include "inputfile.h"
167 #include "registry.h"
168 #include "section_file.h"
172 #include "registry_ini.h"
174 #define MAX_LEN_SECPATH 1024
176 /* Set to FALSE for old-style savefiles. */
177 #define SAVE_TABLES TRUE
179 #define SPECVEC_TAG astring
182 static inline bool entry_used(const struct entry
*pentry
);
183 static inline void entry_use(struct entry
*pentry
);
185 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
);
186 static void entry_from_inf_token(struct section
*psection
, const char *name
,
187 const char *tok
, struct inputfile
*file
);
189 static struct entry
*section_entry_filereference_new(struct section
*psection
,
190 const char *name
, const char *value
);
192 /***************************************************************************
193 Simplification of fileinfoname().
194 ***************************************************************************/
195 static const char *datafilename(const char *filename
)
197 return fileinfoname(get_data_dirs(), filename
);
200 /**************************************************************************
201 Ensure name is correct to use it as section or entry name.
202 **************************************************************************/
203 static bool is_secfile_entry_name_valid(const char *name
)
205 static const char *const allowed
= "_.,-[]";
207 while ('\0' != *name
) {
208 if (!fc_isalnum(*name
) && NULL
== strchr(allowed
, *name
)) {
216 /**************************************************************************
217 Insert an entry into the hash table. Returns TRUE on success.
218 **************************************************************************/
219 static bool secfile_hash_insert(struct section_file
*secfile
,
220 struct entry
*pentry
)
223 struct entry
*hentry
;
225 if (NULL
== secfile
->hash
.entries
) {
226 /* Consider as success if this secfile doesn't have built the entries
231 entry_path(pentry
, buf
, sizeof(buf
));
232 if (entry_hash_replace_full(secfile
->hash
.entries
, buf
, pentry
,
235 if (!secfile
->allow_duplicates
) {
236 SECFILE_LOG(secfile
, entry_section(hentry
),
237 "Tried to insert same value twice: %s", buf
);
245 /**************************************************************************
246 Delete an entry from the hash table. Returns TRUE on success.
247 **************************************************************************/
248 static bool secfile_hash_delete(struct section_file
*secfile
,
249 struct entry
*pentry
)
253 if (NULL
== secfile
->hash
.entries
) {
254 /* Consider as success if this secfile doesn't have built the entries
259 entry_path(pentry
, buf
, sizeof(buf
));
260 return entry_hash_remove(secfile
->hash
.entries
, buf
);
263 /**************************************************************************
264 Base function to load a section file. Note it closes the inputfile.
265 **************************************************************************/
266 static struct section_file
*secfile_from_input_file(struct inputfile
*inf
,
267 const char *filename
,
269 bool allow_duplicates
)
271 struct section_file
*secfile
;
272 struct section
*psection
= NULL
;
273 struct section
*single_section
= NULL
;
274 bool table_state
= FALSE
; /* TRUE when within tabular format. */
275 int table_lineno
= 0; /* Row number in tabular, 0 top data row. */
278 struct astring base_name
= ASTRING_INIT
; /* for table or single entry */
279 struct astring field_name
= ASTRING_INIT
;
280 struct astring_vector columns
; /* astrings for column headings */
281 bool found_my_section
= FALSE
;
288 /* Assign the real value later, to speed up the creation of new entries. */
289 secfile
= secfile_new(TRUE
);
291 secfile
->name
= fc_strdup(filename
);
293 secfile
->name
= NULL
;
296 astring_vector_init(&columns
);
299 log_verbose("Reading registry from \"%s\"", filename
);
301 log_verbose("Reading registry");
304 while (!inf_at_eof(inf
)) {
305 if (inf_token(inf
, INF_TOK_EOL
)) {
308 if (inf_at_eof(inf
)) {
309 /* may only realise at eof after trying to read eol above */
312 tok
= inf_token(inf
, INF_TOK_SECTION_NAME
);
314 if (found_my_section
) {
315 /* This shortcut will stop any further loading after the requested
316 * section has been loaded (i.e., at the start of a new section).
317 * This is needed to make the behavior useful, since the whole
318 * purpose is to short-cut further loading of the file. However
319 * normally a section may be split up, and that will no longer
320 * work here because it will be short-cut. */
321 SECFILE_LOG(secfile
, psection
, "%s",
322 inf_log_str(inf
, "Found requested section; finishing"));
326 SECFILE_LOG(secfile
, psection
, "%s",
327 inf_log_str(inf
, "New section during table"));
331 /* Check if we already have a section with this name.
332 (Could ignore this and have a duplicate sections internally,
333 but then secfile_get_secnames_prefix would return duplicates.)
334 Duplicate section in input are likely to be useful for includes.
336 psection
= secfile_section_by_name(secfile
, tok
);
338 if (!section
|| strcmp(tok
, section
) == 0) {
339 psection
= secfile_section_new(secfile
, tok
);
341 single_section
= psection
;
342 found_my_section
= TRUE
;
346 if (!inf_token(inf
, INF_TOK_EOL
)) {
347 SECFILE_LOG(secfile
, psection
, "%s",
348 inf_log_str(inf
, "Expected end of line"));
354 if (inf_token(inf
, INF_TOK_TABLE_END
)) {
356 SECFILE_LOG(secfile
, psection
, "%s",
357 inf_log_str(inf
, "Misplaced \"}\""));
361 if (!inf_token(inf
, INF_TOK_EOL
)) {
362 SECFILE_LOG(secfile
, psection
, "%s",
363 inf_log_str(inf
, "Expected end of line"));
373 int num_columns
= astring_vector_size(&columns
);
376 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
377 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
378 SECFILE_LOG(secfile
, psection
, "%s",
379 inf_log_str(inf
, "Expected value"));
384 if (i
< num_columns
) {
385 astr_set(&field_name
, "%s%d.%s", astr_str(&base_name
),
386 table_lineno
, astr_str(&columns
.p
[i
]));
388 astr_set(&field_name
, "%s%d.%s,%d", astr_str(&base_name
),
389 table_lineno
, astr_str(&columns
.p
[num_columns
- 1]),
390 (int) (i
- num_columns
+ 1));
392 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
393 } while (inf_token(inf
, INF_TOK_COMMA
));
395 if (!inf_token(inf
, INF_TOK_EOL
)) {
396 SECFILE_LOG(secfile
, psection
, "%s",
397 inf_log_str(inf
, "Expected end of line"));
405 if (!(tok
= inf_token(inf
, INF_TOK_ENTRY_NAME
))) {
406 SECFILE_LOG(secfile
, psection
, "%s",
407 inf_log_str(inf
, "Expected entry name"));
412 /* need to store tok before next calls: */
413 astr_set(&base_name
, "%s", tok
);
415 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
417 if (inf_token(inf
, INF_TOK_TABLE_START
)) {
421 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
422 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
423 SECFILE_LOG(secfile
, psection
, "%s",
424 inf_log_str(inf
, "Expected value"));
428 if (tok
[0] != '\"') {
429 SECFILE_LOG(secfile
, psection
, "%s",
430 inf_log_str(inf
, "Table column header non-string"));
434 { /* expand columns: */
436 n_prev
= astring_vector_size(&columns
);
437 for (j
= i
+ 1; j
< n_prev
; j
++) {
438 astr_free(&columns
.p
[j
]);
440 astring_vector_reserve(&columns
, i
+ 1);
441 for (j
= n_prev
; j
< i
+ 1; j
++) {
442 astr_init(&columns
.p
[j
]);
445 astr_set(&columns
.p
[i
], "%s", tok
+ 1);
447 } while (inf_token(inf
, INF_TOK_COMMA
));
449 if (!inf_token(inf
, INF_TOK_EOL
)) {
450 SECFILE_LOG(secfile
, psection
, "%s",
451 inf_log_str(inf
, "Expected end of line"));
459 /* ordinary value: */
463 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
464 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
465 SECFILE_LOG(secfile
, psection
, "%s",
466 inf_log_str(inf
, "Expected value"));
471 entry_from_inf_token(psection
, astr_str(&base_name
), tok
, inf
);
473 astr_set(&field_name
, "%s,%d", astr_str(&base_name
), i
);
474 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
476 } while (inf_token(inf
, INF_TOK_COMMA
));
477 if (!inf_token(inf
, INF_TOK_EOL
)) {
478 SECFILE_LOG(secfile
, psection
, "%s",
479 inf_log_str(inf
, "Expected end of line"));
486 SECFILE_LOG(secfile
, psection
,
487 "Finished registry before end of table");
493 astr_free(&base_name
);
494 astr_free(&field_name
);
495 for (i
= 0; i
< astring_vector_size(&columns
); i
++) {
496 astr_free(&columns
.p
[i
]);
498 astring_vector_free(&columns
);
500 if (section
!= NULL
) {
501 if (!found_my_section
) {
502 secfile_destroy(secfile
);
506 /* Build the entry hash table with single section information */
507 secfile
->allow_duplicates
= allow_duplicates
;
508 entry_list_iterate(section_entries(single_section
), pentry
) {
509 if (!secfile_hash_insert(secfile
, pentry
)) {
510 secfile_destroy(secfile
);
513 } entry_list_iterate_end
;
519 /* Build the entry hash table. */
520 secfile
->allow_duplicates
= allow_duplicates
;
521 secfile
->hash
.entries
= entry_hash_new_nentries(secfile
->num_entries
);
523 section_list_iterate(secfile
->sections
, hashing_section
) {
524 entry_list_iterate(section_entries(hashing_section
), pentry
) {
525 if (!secfile_hash_insert(secfile
, pentry
)) {
529 } entry_list_iterate_end
;
533 } section_list_iterate_end
;
536 secfile_destroy(secfile
);
543 /**************************************************************************
544 Create a section file from a file, read only one particular section.
545 Returns NULL on error.
546 **************************************************************************/
547 struct section_file
*secfile_load_section(const char *filename
,
549 bool allow_duplicates
)
551 char real_filename
[1024];
553 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
554 return secfile_from_input_file(inf_from_file(real_filename
, datafilename
),
555 filename
, section
, allow_duplicates
);
558 /**************************************************************************
559 Create a section file from a stream. Returns NULL on error.
560 **************************************************************************/
561 struct section_file
*secfile_from_stream(fz_FILE
*stream
,
562 bool allow_duplicates
)
564 return secfile_from_input_file(inf_from_stream(stream
, datafilename
),
565 NULL
, NULL
, allow_duplicates
);
568 /**************************************************************************
569 Returns TRUE iff the character is legal in a table entry name.
570 **************************************************************************/
571 static bool is_legal_table_entry_name(char c
, bool num
)
573 return (num
? fc_isalnum(c
) : fc_isalpha(c
)) || c
== '_';
576 /**************************************************************************
577 Save the previously filled in section_file to disk.
579 There is now limited ability to save in the new tabular format
580 (to give smaller savefiles).
581 The start of a table is detected by an entry with name of the form:
582 (alphabetical_component)(zero)(period)(alphanumeric_component)
583 Eg: u0.id, or c0.id, in the freeciv savefile.
584 The alphabetical component is taken as the "name" of the table,
585 and the component after the period as the first column name.
586 This should be followed by the other column values for u0,
587 and then subsequent u1, u2, etc, in strict order with no omissions,
588 and with all of the columns for all uN in the same order as for u0.
590 If compression_level is non-zero, then compress using zlib. (Should
591 only supply non-zero compression_level if already know that FREECIV_HAVE_LIBZ.)
592 Below simply specifies FZ_ZLIB method, since fz_fromFile() automatically
593 changes to FZ_PLAIN method when level == 0.
594 **************************************************************************/
595 bool secfile_save(const struct section_file
*secfile
, const char *filename
,
596 int compression_level
, enum fz_method compression_method
)
598 char real_filename
[1024];
599 char pentry_name
[128];
600 const char *col_entry_name
;
602 const struct entry_list_link
*ent_iter
, *save_iter
, *col_iter
;
603 struct entry
*pentry
, *col_pentry
;
606 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
608 if (NULL
== filename
) {
609 filename
= secfile
->name
;
612 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
613 fs
= fz_from_file(real_filename
, "w",
614 compression_method
, compression_level
);
620 section_list_iterate(secfile
->sections
, psection
) {
621 if (psection
->include
) {
622 for (ent_iter
= entry_list_head(section_entries(psection
));
623 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
624 ent_iter
= entry_list_link_next(ent_iter
)) {
626 fc_assert(!strcmp(entry_name(pentry
), "file"));
628 fz_fprintf(fs
, "*include ");
629 entry_to_file(pentry
, fs
);
630 fz_fprintf(fs
, "\n");
633 fz_fprintf(fs
, "\n[%s]\n", section_name(psection
));
635 /* Following doesn't use entry_list_iterate() because we want to do
636 * tricky things with the iterators...
638 for (ent_iter
= entry_list_head(section_entries(psection
));
639 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
640 ent_iter
= entry_list_link_next(ent_iter
)) {
643 /* Tables: break out of this loop if this is a non-table
644 * entry (pentry and ent_iter unchanged) or after table (pentry
645 * and ent_iter suitably updated, pentry possibly NULL).
646 * After each table, loop again in case the next entry
650 char *c
, *first
, base
[64];
651 int offset
, irow
, icol
, ncol
;
653 /* Example: for first table name of "xyz0.blah":
654 * first points to the original string pentry->name
655 * base contains "xyz";
656 * offset = 5 (so first+offset gives "blah")
657 * note strlen(base) = offset - 2
664 sz_strlcpy(pentry_name
, entry_name(pentry
));
665 c
= first
= pentry_name
;
666 if (*c
== '\0' || !is_legal_table_entry_name(*c
, FALSE
)) {
669 for (; *c
!= '\0' && is_legal_table_entry_name(*c
, FALSE
); c
++) {
672 if (0 != strncmp(c
, "0.", 2)) {
676 if (*c
== '\0' || !is_legal_table_entry_name(*c
, TRUE
)) {
681 first
[offset
- 2] = '\0';
682 sz_strlcpy(base
, first
);
683 first
[offset
- 2] = '0';
684 fz_fprintf(fs
, "%s={", base
);
686 /* Save an iterator at this first entry, which we can later use
687 * to repeatedly iterate over column names:
689 save_iter
= ent_iter
;
691 /* write the column names, and calculate ncol: */
693 col_iter
= save_iter
;
694 for(; (col_pentry
= entry_list_link_data(col_iter
));
695 col_iter
= entry_list_link_next(col_iter
)) {
696 col_entry_name
= entry_name(col_pentry
);
697 if (strncmp(col_entry_name
, first
, offset
) != 0) {
700 fz_fprintf(fs
, "%s\"%s\"", (ncol
== 0 ? "" : ","),
701 col_entry_name
+ offset
);
704 fz_fprintf(fs
, "\n");
706 /* Iterate over rows and columns, incrementing ent_iter as we go,
707 * and writing values to the table. Have a separate iterator
708 * to the column names to check they all match.
711 col_iter
= save_iter
;
713 char expect
[128]; /* pentry->name we're expecting */
715 pentry
= entry_list_link_data(ent_iter
);
716 col_pentry
= entry_list_link_data(col_iter
);
718 fc_snprintf(expect
, sizeof(expect
), "%s%d.%s",
719 base
, irow
, entry_name(col_pentry
) + offset
);
721 /* break out of tabular if doesn't match: */
722 if ((!pentry
) || (strcmp(entry_name(pentry
), expect
) != 0)) {
724 /* If the second or later row of a table is missing some
725 * entries that the first row had, we drop out of the tabular
726 * format. This is inefficient so we print a warning message;
727 * the calling code probably needs to be fixed so that it can
728 * use the more efficient tabular format.
730 * FIXME: If the first row is missing some entries that the
731 * second or later row has, then we'll drop out of tabular
732 * format without an error message. */
733 log_error("In file %s, there is no entry in the registry for\n"
734 "%s.%s (or the entries are out of order). This means\n"
735 "a less efficient non-tabular format will be used.\n"
736 "To avoid this make sure all rows of a table are\n"
737 "filled out with an entry for every column.",
738 real_filename
, section_name(psection
), expect
);
739 /* TRANS: No full stop after the URL, could cause confusion. */
740 log_error(_("Please report this message at %s"), BUG_URL
);
741 fz_fprintf(fs
, "\n");
743 fz_fprintf(fs
, "}\n");
750 entry_to_file(pentry
, fs
);
752 ent_iter
= entry_list_link_next(ent_iter
);
753 col_iter
= entry_list_link_next(col_iter
);
757 fz_fprintf(fs
, "\n");
760 col_iter
= save_iter
;
772 col_entry_name
= entry_name(pentry
);
773 fz_fprintf(fs
, "%s=", col_entry_name
);
774 entry_to_file(pentry
, fs
);
776 /* Check for vector. */
778 col_iter
= entry_list_link_next(ent_iter
);
779 col_pentry
= entry_list_link_data(col_iter
);
780 if (NULL
== col_pentry
) {
783 fc_snprintf(pentry_name
, sizeof(pentry_name
),
784 "%s,%d", col_entry_name
, i
);
785 if (0 != strcmp(pentry_name
, entry_name(col_pentry
))) {
789 entry_to_file(col_pentry
, fs
);
793 comment
= entry_comment(pentry
);
795 fz_fprintf(fs
, "#%s\n", comment
);
797 fz_fprintf(fs
, "\n");
801 } section_list_iterate_end
;
803 if (0 != fz_ferror(fs
)) {
804 SECFILE_LOG(secfile
, NULL
, "Error before closing %s: %s",
805 real_filename
, fz_strerror(fs
));
809 if (0 != fz_fclose(fs
)) {
810 SECFILE_LOG(secfile
, NULL
, "Error closing %s", real_filename
);
817 /**************************************************************************
818 Print log messages for any entries in the file which have
819 not been looked up -- ie, unused or unrecognised entries.
820 To mark an entry as used without actually doing anything with it,
821 you could do something like:
822 section_file_lookup(&file, "foo.bar"); / * unused * /
823 **************************************************************************/
824 void secfile_check_unused(const struct section_file
*secfile
)
828 section_list_iterate(secfile_sections(secfile
), psection
) {
829 entry_list_iterate(section_entries(psection
), pentry
) {
830 if (!entry_used(pentry
)) {
831 if (!any
&& secfile
->name
) {
832 log_verbose("Unused entries in file %s:", secfile
->name
);
835 if (are_deprecation_warnings_enabled()) {
836 log_deprecation_always("%s: unused entry: %s.%s",
837 secfile
->name
!= NULL
? secfile
->name
: "nameless",
838 section_name(psection
), entry_name(pentry
));
840 #ifdef FREECIV_TESTMATIC
841 log_testmatic("%s: unused entry: %s.%s",
842 secfile
->name
!= NULL
? secfile
->name
: "nameless",
843 section_name(psection
), entry_name(pentry
));
844 #else /* FREECIV_TESTMATIC */
845 log_verbose(" unused entry: %s.%s",
846 section_name(psection
), entry_name(pentry
));
847 #endif /* FREECIV_TESTMATIC */
850 } entry_list_iterate_end
;
851 } section_list_iterate_end
;
854 /**************************************************************************
855 Return the filename the section file was loaded as, or "(anonymous)"
856 if this sectionfile was created rather than loaded from file.
857 The memory is managed internally, and should not be altered,
858 nor used after secfile_destroy() called for the section file.
859 **************************************************************************/
860 const char *secfile_name(const struct section_file
*secfile
)
862 if (NULL
== secfile
) {
864 } else if (secfile
->name
) {
865 return secfile
->name
;
867 return "(anonymous)";
871 /**************************************************************************
872 Seperates the section and entry names. Create the section if missing.
873 **************************************************************************/
874 static struct section
*secfile_insert_base(struct section_file
*secfile
,
876 const char **pent_name
)
878 char fullpath
[MAX_LEN_SECPATH
];
880 struct section
*psection
;
882 sz_strlcpy(fullpath
, path
);
884 ent_name
= strchr(fullpath
, '.');
886 SECFILE_LOG(secfile
, NULL
,
887 "Section and entry names must be separated by a dot.");
891 /* Separates section and entry names. */
893 *pent_name
= path
+ (ent_name
- fullpath
) + 1;
894 psection
= secfile_section_by_name(secfile
, fullpath
);
898 return secfile_section_new(secfile
, fullpath
);
902 /**************************************************************************
903 Insert a boolean entry.
904 **************************************************************************/
905 struct entry
*secfile_insert_bool_full(struct section_file
*secfile
,
906 bool value
, const char *comment
,
908 const char *path
, ...)
910 char fullpath
[MAX_LEN_SECPATH
];
911 const char *ent_name
;
912 struct section
*psection
;
913 struct entry
*pentry
= NULL
;
916 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
918 va_start(args
, path
);
919 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
922 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
928 pentry
= section_entry_by_name(psection
, ent_name
);
929 if (NULL
!= pentry
) {
930 if (ENTRY_BOOL
== entry_type(pentry
)) {
931 if (!entry_bool_set(pentry
, value
)) {
935 entry_destroy(pentry
);
941 if (NULL
== pentry
) {
942 pentry
= section_entry_bool_new(psection
, ent_name
, value
);
945 if (NULL
!= pentry
&& NULL
!= comment
) {
946 entry_set_comment(pentry
, comment
);
952 /**************************************************************************
953 Insert 'dim' boolean entries at 'path,0', 'path,1' etc. Returns
954 the number of entries inserted or replaced.
955 **************************************************************************/
956 size_t secfile_insert_bool_vec_full(struct section_file
*secfile
,
957 const bool *values
, size_t dim
,
958 const char *comment
, bool allow_replace
,
959 const char *path
, ...)
961 char fullpath
[MAX_LEN_SECPATH
];
965 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
967 va_start(args
, path
);
968 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
971 /* NB: 'path,0' is actually 'path'. See comment in the head
974 && NULL
!= secfile_insert_bool_full(secfile
, values
[0], comment
,
975 allow_replace
, "%s", fullpath
)) {
978 for (i
= 1; i
< dim
; i
++) {
979 if (NULL
!= secfile_insert_bool_full(secfile
, values
[i
], comment
,
980 allow_replace
, "%s,%d",
981 fullpath
, (int) i
)) {
989 /**************************************************************************
990 Insert a integer entry.
991 **************************************************************************/
992 struct entry
*secfile_insert_int_full(struct section_file
*secfile
,
993 int value
, const char *comment
,
995 const char *path
, ...)
997 char fullpath
[MAX_LEN_SECPATH
];
998 const char *ent_name
;
999 struct section
*psection
;
1000 struct entry
*pentry
= NULL
;
1003 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1005 va_start(args
, path
);
1006 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1009 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1014 if (allow_replace
) {
1015 pentry
= section_entry_by_name(psection
, ent_name
);
1016 if (NULL
!= pentry
) {
1017 if (ENTRY_INT
== entry_type(pentry
)) {
1018 if (!entry_int_set(pentry
, value
)) {
1022 entry_destroy(pentry
);
1028 if (NULL
== pentry
) {
1029 pentry
= section_entry_int_new(psection
, ent_name
, value
);
1032 if (NULL
!= pentry
&& NULL
!= comment
) {
1033 entry_set_comment(pentry
, comment
);
1039 /**************************************************************************
1040 Insert 'dim' integer entries at 'path,0', 'path,1' etc. Returns
1041 the number of entries inserted or replaced.
1042 **************************************************************************/
1043 size_t secfile_insert_int_vec_full(struct section_file
*secfile
,
1044 const int *values
, size_t dim
,
1045 const char *comment
, bool allow_replace
,
1046 const char *path
, ...)
1048 char fullpath
[MAX_LEN_SECPATH
];
1052 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1054 va_start(args
, path
);
1055 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1058 /* NB: 'path,0' is actually 'path'. See comment in the head
1061 && NULL
!= secfile_insert_int_full(secfile
, values
[0], comment
,
1062 allow_replace
, "%s", fullpath
)) {
1065 for (i
= 1; i
< dim
; i
++) {
1066 if (NULL
!= secfile_insert_int_full(secfile
, values
[i
], comment
,
1067 allow_replace
, "%s,%d",
1068 fullpath
, (int) i
)) {
1076 /**************************************************************************
1077 Insert a floating entry.
1078 **************************************************************************/
1079 struct entry
*secfile_insert_float_full(struct section_file
*secfile
,
1080 float value
, const char *comment
,
1082 const char *path
, ...)
1084 char fullpath
[MAX_LEN_SECPATH
];
1085 const char *ent_name
;
1086 struct section
*psection
;
1087 struct entry
*pentry
= NULL
;
1090 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1092 va_start(args
, path
);
1093 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1096 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1101 if (allow_replace
) {
1102 pentry
= section_entry_by_name(psection
, ent_name
);
1103 if (NULL
!= pentry
) {
1104 if (ENTRY_FLOAT
== entry_type(pentry
)) {
1105 if (!entry_float_set(pentry
, value
)) {
1109 entry_destroy(pentry
);
1115 if (NULL
== pentry
) {
1116 pentry
= section_entry_float_new(psection
, ent_name
, value
);
1119 if (NULL
!= pentry
&& NULL
!= comment
) {
1120 entry_set_comment(pentry
, comment
);
1126 /**************************************************************************
1127 Insert a include entry.
1128 **************************************************************************/
1129 struct section
*secfile_insert_include(struct section_file
*secfile
,
1130 const char *filename
)
1132 struct section
*psection
;
1135 fc_snprintf(buffer
, sizeof(buffer
), "include_%u", secfile
->num_includes
++);
1137 fc_assert_ret_val(secfile_section_by_name(secfile
, filename
) == NULL
, NULL
);
1139 /* Create include section. */
1140 psection
= secfile_section_new(secfile
, buffer
);
1141 psection
->include
= TRUE
;
1143 /* Then add string entry "file" to it. */
1144 secfile_insert_str_full(secfile
, filename
, NULL
, FALSE
, FALSE
, TRUE
, "%s.file", buffer
);
1149 /**************************************************************************
1150 Insert a string entry.
1151 **************************************************************************/
1152 struct entry
*secfile_insert_str_full(struct section_file
*secfile
,
1154 const char *comment
,
1158 const char *path
, ...)
1160 char fullpath
[MAX_LEN_SECPATH
];
1161 const char *ent_name
;
1162 struct section
*psection
;
1163 struct entry
*pentry
= NULL
;
1166 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1168 va_start(args
, path
);
1169 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1172 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1177 if (psection
->include
&& !include
) {
1178 log_error("Tried to insert normal entry to include section");
1182 if (allow_replace
) {
1183 pentry
= section_entry_by_name(psection
, ent_name
);
1184 if (NULL
!= pentry
) {
1185 if (ENTRY_STR
== entry_type(pentry
)) {
1186 if (!entry_str_set(pentry
, str
)) {
1190 entry_destroy(pentry
);
1196 if (NULL
== pentry
) {
1197 pentry
= section_entry_str_new(psection
, ent_name
, str
, !no_escape
);
1200 if (NULL
!= pentry
&& NULL
!= comment
) {
1201 entry_set_comment(pentry
, comment
);
1207 /**************************************************************************
1208 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1209 the number of entries inserted or replaced.
1210 **************************************************************************/
1211 size_t secfile_insert_str_vec_full(struct section_file
*secfile
,
1212 const char *const *strings
, size_t dim
,
1213 const char *comment
, bool allow_replace
,
1214 bool no_escape
, const char *path
, ...)
1216 char fullpath
[MAX_LEN_SECPATH
];
1220 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1222 va_start(args
, path
);
1223 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1226 /* NB: 'path,0' is actually 'path'. See comment in the head
1229 && NULL
!= secfile_insert_str_full(secfile
, strings
[0], comment
,
1230 allow_replace
, no_escape
, FALSE
,
1234 for (i
= 1; i
< dim
; i
++) {
1235 if (NULL
!= secfile_insert_str_full(secfile
, strings
[i
], comment
,
1236 allow_replace
, no_escape
, FALSE
,
1237 "%s,%d", fullpath
, (int) i
)) {
1245 /****************************************************************************
1246 Insert a read-from-a-file string entry
1247 ****************************************************************************/
1248 struct entry
*secfile_insert_filereference(struct section_file
*secfile
,
1249 char *filename
, char *path
, ...)
1251 char fullpath
[MAX_LEN_SECPATH
];
1252 const char *ent_name
;
1253 struct section
*psection
;
1254 struct entry
*pentry
= NULL
;
1257 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1259 va_start(args
, path
);
1260 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1263 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1268 if (psection
->include
) {
1269 log_error("Tried to insert normal entry to include section");
1273 if (NULL
== pentry
) {
1274 pentry
= section_entry_filereference_new(psection
, ent_name
, filename
);
1280 /****************************************************************************
1281 Insert a enumerator entry.
1282 ****************************************************************************/
1283 struct entry
*secfile_insert_plain_enum_full(struct section_file
*secfile
,
1285 secfile_enum_name_fn_t name_fn
,
1286 const char *comment
,
1288 const char *path
, ...)
1290 char fullpath
[MAX_LEN_SECPATH
];
1292 const char *ent_name
;
1293 struct section
*psection
;
1294 struct entry
*pentry
= NULL
;
1297 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1298 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1299 str
= name_fn(enumerator
);
1300 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= str
, NULL
);
1302 va_start(args
, path
);
1303 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1306 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1311 if (allow_replace
) {
1312 pentry
= section_entry_by_name(psection
, ent_name
);
1313 if (NULL
!= pentry
) {
1314 if (ENTRY_STR
== entry_type(pentry
)) {
1315 if (!entry_str_set(pentry
, str
)) {
1319 entry_destroy(pentry
);
1325 if (NULL
== pentry
) {
1326 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1329 if (NULL
!= pentry
&& NULL
!= comment
) {
1330 entry_set_comment(pentry
, comment
);
1336 /****************************************************************************
1337 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1338 the number of entries inserted or replaced.
1339 ****************************************************************************/
1340 size_t secfile_insert_plain_enum_vec_full(struct section_file
*secfile
,
1341 const int *enumurators
, size_t dim
,
1342 secfile_enum_name_fn_t name_fn
,
1343 const char *comment
,
1345 const char *path
, ...)
1347 char fullpath
[MAX_LEN_SECPATH
];
1351 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1352 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1354 va_start(args
, path
);
1355 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1358 /* NB: 'path,0' is actually 'path'. See comment in the head
1361 && NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[0],
1363 allow_replace
, "%s",
1367 for (i
= 1; i
< dim
; i
++) {
1368 if (NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[i
],
1370 allow_replace
, "%s,%d",
1371 fullpath
, (int) i
)) {
1379 /****************************************************************************
1380 Insert a bitwise value entry.
1381 ****************************************************************************/
1382 struct entry
*secfile_insert_bitwise_enum_full(struct section_file
*secfile
,
1384 secfile_enum_name_fn_t
1386 secfile_enum_iter_fn_t
1388 secfile_enum_iter_fn_t
1390 secfile_enum_next_fn_t
1392 const char *comment
,
1394 const char *path
, ...)
1396 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1397 const char *ent_name
;
1398 struct section
*psection
;
1399 struct entry
*pentry
= NULL
;
1403 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1404 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1405 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, NULL
);
1406 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, NULL
);
1407 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, NULL
);
1409 /* Compute a string containing all the values separated by '|'. */
1410 str
[0] = '\0'; /* Insert at least an empty string. */
1411 if (0 != bitwise_val
) {
1412 for (i
= begin_fn(); i
!= end_fn(); i
= next_fn(i
)) {
1413 if (i
& bitwise_val
) {
1414 if ('\0' == str
[0]) {
1415 sz_strlcpy(str
, name_fn(i
));
1417 cat_snprintf(str
, sizeof(str
), "|%s", name_fn(i
));
1423 va_start(args
, path
);
1424 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1427 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1432 if (allow_replace
) {
1433 pentry
= section_entry_by_name(psection
, ent_name
);
1434 if (NULL
!= pentry
) {
1435 if (ENTRY_STR
== entry_type(pentry
)) {
1436 if (!entry_str_set(pentry
, str
)) {
1440 entry_destroy(pentry
);
1446 if (NULL
== pentry
) {
1447 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1450 if (NULL
!= pentry
&& NULL
!= comment
) {
1451 entry_set_comment(pentry
, comment
);
1457 /****************************************************************************
1458 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1459 the number of entries inserted or replaced.
1460 ****************************************************************************/
1461 size_t secfile_insert_bitwise_enum_vec_full(struct section_file
*secfile
,
1462 const int *bitwise_vals
,
1464 secfile_enum_name_fn_t name_fn
,
1465 secfile_enum_iter_fn_t begin_fn
,
1466 secfile_enum_iter_fn_t end_fn
,
1467 secfile_enum_next_fn_t next_fn
,
1468 const char *comment
,
1470 const char *path
, ...)
1472 char fullpath
[MAX_LEN_SECPATH
];
1476 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1477 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1478 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, 0);
1479 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, 0);
1480 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, 0);
1482 va_start(args
, path
);
1483 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1486 /* NB: 'path,0' is actually 'path'. See comment in the head
1489 && NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[0],
1490 name_fn
, begin_fn
, end_fn
,
1492 allow_replace
, "%s",
1496 for (i
= 1; i
< dim
; i
++) {
1497 if (NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[i
],
1498 name_fn
, begin_fn
, end_fn
,
1500 allow_replace
, "%s,%d",
1501 fullpath
, (int) i
)) {
1509 /****************************************************************************
1510 Insert an enumerator value entry that we only have a name accessor
1512 ****************************************************************************/
1513 struct entry
*secfile_insert_enum_data_full(struct section_file
*secfile
,
1514 int value
, bool bitwise
,
1515 secfile_enum_name_data_fn_t name_fn
,
1516 secfile_data_t data
,
1517 const char *comment
,
1519 const char *path
, ...)
1521 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1522 const char *ent_name
, *val_name
;
1523 struct section
*psection
;
1524 struct entry
*pentry
= NULL
;
1528 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1529 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1532 /* Compute a string containing all the values separated by '|'. */
1533 str
[0] = '\0'; /* Insert at least an empty string. */
1535 for (i
= 0; (val_name
= name_fn(data
, i
)); i
++) {
1536 if ((1 << i
) & value
) {
1537 if ('\0' == str
[0]) {
1538 sz_strlcpy(str
, val_name
);
1540 cat_snprintf(str
, sizeof(str
), "|%s", val_name
);
1546 if (!(val_name
= name_fn(data
, value
))) {
1547 SECFILE_LOG(secfile
, NULL
, "Value %d not supported.", value
);
1550 sz_strlcpy(str
, val_name
);
1553 va_start(args
, path
);
1554 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1557 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1562 if (allow_replace
) {
1563 pentry
= section_entry_by_name(psection
, ent_name
);
1564 if (NULL
!= pentry
) {
1565 if (ENTRY_STR
== entry_type(pentry
)) {
1566 if (!entry_str_set(pentry
, str
)) {
1570 entry_destroy(pentry
);
1576 if (NULL
== pentry
) {
1577 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1580 if (NULL
!= pentry
&& NULL
!= comment
) {
1581 entry_set_comment(pentry
, comment
);
1587 /****************************************************************************
1588 Insert 'dim' entries at 'path,0', 'path,1' etc. Returns the number of
1589 entries inserted or replaced.
1590 ****************************************************************************/
1591 size_t secfile_insert_enum_vec_data_full(struct section_file
*secfile
,
1592 const int *values
, size_t dim
,
1594 secfile_enum_name_data_fn_t name_fn
,
1595 secfile_data_t data
,
1596 const char *comment
,
1598 const char *path
, ...)
1600 char fullpath
[MAX_LEN_SECPATH
];
1604 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1605 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1607 va_start(args
, path
);
1608 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1611 /* NB: 'path,0' is actually 'path'. See comment in the head
1614 && NULL
!= secfile_insert_enum_data_full(secfile
, values
[0], bitwise
,
1615 name_fn
, data
, comment
,
1616 allow_replace
, "%s",
1620 for (i
= 1; i
< dim
; i
++) {
1621 if (NULL
!= secfile_insert_enum_data_full(secfile
, values
[i
], bitwise
,
1622 name_fn
, data
, comment
,
1623 allow_replace
, "%s,%d",
1624 fullpath
, (int) i
)) {
1632 /****************************************************************************
1633 Returns the entry by the name or NULL if not matched.
1634 ****************************************************************************/
1635 struct entry
*secfile_entry_by_path(const struct section_file
*secfile
,
1638 char fullpath
[MAX_LEN_SECPATH
];
1641 struct section
*psection
;
1643 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1645 sz_strlcpy(fullpath
, path
);
1647 /* treat "sec.foo,0" as "sec.foo": */
1648 len
= strlen(fullpath
);
1649 if (len
> 2 && fullpath
[len
- 2] == ',' && fullpath
[len
- 1] == '0') {
1650 fullpath
[len
- 2] = '\0';
1653 if (NULL
!= secfile
->hash
.entries
) {
1654 struct entry
*pentry
;
1656 if (entry_hash_lookup(secfile
->hash
.entries
, fullpath
, &pentry
)) {
1662 /* I dont like strtok.
1664 ent_name
= strchr(fullpath
, '.');
1669 /* Separates section and entry names. */
1671 psection
= secfile_section_by_name(secfile
, fullpath
);
1673 return section_entry_by_name(psection
, ent_name
);
1679 /**************************************************************************
1681 **************************************************************************/
1682 bool secfile_entry_delete(struct section_file
*secfile
,
1683 const char *path
, ...)
1685 char fullpath
[MAX_LEN_SECPATH
];
1687 struct entry
*pentry
;
1689 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1691 va_start(args
, path
);
1692 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1695 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1696 SECFILE_LOG(secfile
, NULL
, "Path %s does not exists.", fullpath
);
1700 entry_destroy(pentry
);
1705 /**************************************************************************
1706 Returns the entry at "fullpath" or NULL if not matched.
1707 **************************************************************************/
1708 struct entry
*secfile_entry_lookup(const struct section_file
*secfile
,
1709 const char *path
, ...)
1711 char fullpath
[MAX_LEN_SECPATH
];
1714 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1716 va_start(args
, path
);
1717 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1720 return secfile_entry_by_path(secfile
, fullpath
);
1723 /**************************************************************************
1724 Lookup a boolean value in the secfile. Returns TRUE on success.
1725 **************************************************************************/
1726 bool secfile_lookup_bool(const struct section_file
*secfile
, bool *bval
,
1727 const char *path
, ...)
1729 char fullpath
[MAX_LEN_SECPATH
];
1730 const struct entry
*pentry
;
1733 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1735 va_start(args
, path
);
1736 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1739 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1740 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1744 return entry_bool_get(pentry
, bval
);
1747 /**************************************************************************
1748 Lookup a boolean value in the secfile. On failure, use the default
1750 **************************************************************************/
1751 bool secfile_lookup_bool_default(const struct section_file
*secfile
,
1752 bool def
, const char *path
, ...)
1754 char fullpath
[MAX_LEN_SECPATH
];
1755 const struct entry
*pentry
;
1759 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1761 va_start(args
, path
);
1762 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1765 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1769 if (entry_bool_get(pentry
, &bval
)) {
1776 /**************************************************************************
1777 Lookup a boolean vector in the secfile. Returns NULL on error. This
1778 vector is not owned by the registry module, and should be free by the
1780 **************************************************************************/
1781 bool *secfile_lookup_bool_vec(const struct section_file
*secfile
,
1782 size_t *dim
, const char *path
, ...)
1784 char fullpath
[MAX_LEN_SECPATH
];
1789 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1790 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
1792 va_start(args
, path
);
1793 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1797 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
1803 /* Doesn't exist. */
1804 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1808 vec
= fc_malloc(i
* sizeof(bool));
1809 for(i
= 0; i
< *dim
; i
++) {
1810 if (!secfile_lookup_bool(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
1811 SECFILE_LOG(secfile
, NULL
,
1812 "An error occurred when looking up to \"%s,%d\" entry.",
1823 /**************************************************************************
1824 Lookup a integer value in the secfile. Returns TRUE on success.
1825 **************************************************************************/
1826 bool secfile_lookup_int(const struct section_file
*secfile
, int *ival
,
1827 const char *path
, ...)
1829 char fullpath
[MAX_LEN_SECPATH
];
1830 const struct entry
*pentry
;
1833 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1835 va_start(args
, path
);
1836 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1839 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1840 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1844 return entry_int_get(pentry
, ival
);
1847 /**************************************************************************
1848 Lookup a integer value in the secfile. On failure, use the default
1850 **************************************************************************/
1851 int secfile_lookup_int_default(const struct section_file
*secfile
, int def
,
1852 const char *path
, ...)
1854 char fullpath
[MAX_LEN_SECPATH
];
1855 const struct entry
*pentry
;
1859 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1861 va_start(args
, path
);
1862 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1865 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1869 if (entry_int_get(pentry
, &ival
)) {
1876 /**************************************************************************
1877 Lookup a integer value in the secfile. The value will be arranged to
1878 match the interval [minval, maxval]. On failure, use the default
1880 **************************************************************************/
1881 int secfile_lookup_int_def_min_max(const struct section_file
*secfile
,
1882 int defval
, int minval
, int maxval
,
1883 const char *path
, ...)
1885 char fullpath
[MAX_LEN_SECPATH
];
1886 const struct entry
*pentry
;
1890 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
1892 va_start(args
, path
);
1893 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1896 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1900 if (!entry_int_get(pentry
, &value
)) {
1904 if (value
< minval
) {
1905 SECFILE_LOG(secfile
, entry_section(pentry
),
1906 "\"%s\" should be in the interval [%d, %d] but is %d;"
1907 "using the minimal value.",
1908 fullpath
, minval
, maxval
, value
);
1912 if (value
> maxval
) {
1913 SECFILE_LOG(secfile
, entry_section(pentry
),
1914 "\"%s\" should be in the interval [%d, %d] but is %d;"
1915 "using the maximal value.",
1916 fullpath
, minval
, maxval
, value
);
1923 /**************************************************************************
1924 Lookup a integer vector in the secfile. Returns NULL on error. This
1925 vector is not owned by the registry module, and should be free by the
1927 **************************************************************************/
1928 int *secfile_lookup_int_vec(const struct section_file
*secfile
,
1929 size_t *dim
, const char *path
, ...)
1931 char fullpath
[MAX_LEN_SECPATH
];
1936 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1937 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
1939 va_start(args
, path
);
1940 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1944 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
1950 /* Doesn't exist. */
1951 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1955 vec
= fc_malloc(i
* sizeof(int));
1956 for(i
= 0; i
< *dim
; i
++) {
1957 if (!secfile_lookup_int(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
1958 SECFILE_LOG(secfile
, NULL
,
1959 "An error occurred when looking up to \"%s,%d\" entry.",
1970 /**************************************************************************
1971 Lookup a floating point value in the secfile. Returns TRUE on success.
1972 **************************************************************************/
1973 bool secfile_lookup_float(const struct section_file
*secfile
, float *fval
,
1974 const char *path
, ...)
1976 char fullpath
[MAX_LEN_SECPATH
];
1977 const struct entry
*pentry
;
1980 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1982 va_start(args
, path
);
1983 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1986 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1987 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1991 return entry_float_get(pentry
, fval
);
1994 /**************************************************************************
1995 Lookup a floating point value in the secfile. On failure, use the default
1997 **************************************************************************/
1998 float secfile_lookup_float_default(const struct section_file
*secfile
,
1999 float def
, const char *path
, ...)
2001 char fullpath
[MAX_LEN_SECPATH
];
2002 const struct entry
*pentry
;
2006 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2008 va_start(args
, path
);
2009 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2012 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2016 if (entry_float_get(pentry
, &fval
)) {
2023 /**************************************************************************
2024 Lookup a string value in the secfile. Returns NULL on error.
2025 **************************************************************************/
2026 const char *secfile_lookup_str(const struct section_file
*secfile
,
2027 const char *path
, ...)
2029 char fullpath
[MAX_LEN_SECPATH
];
2030 const struct entry
*pentry
;
2034 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2036 va_start(args
, path
);
2037 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2040 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2041 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2045 if (entry_str_get(pentry
, &str
)) {
2052 /**************************************************************************
2053 Lookup a string value in the secfile. On failure, use the default
2055 **************************************************************************/
2056 const char *secfile_lookup_str_default(const struct section_file
*secfile
,
2058 const char *path
, ...)
2060 char fullpath
[MAX_LEN_SECPATH
];
2061 const struct entry
*pentry
;
2065 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2067 va_start(args
, path
);
2068 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2071 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2075 if (entry_str_get(pentry
, &str
)) {
2082 /**************************************************************************
2083 Lookup a string vector in the secfile. Returns NULL on error. This
2084 vector is not owned by the registry module, and should be free by the
2085 user, but the string pointers stored inside the vector shouldn't be
2087 **************************************************************************/
2088 const char **secfile_lookup_str_vec(const struct section_file
*secfile
,
2089 size_t *dim
, const char *path
, ...)
2091 char fullpath
[MAX_LEN_SECPATH
];
2096 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2097 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2099 va_start(args
, path
);
2100 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2104 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2110 /* Doesn't exist. */
2111 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2115 vec
= fc_malloc(i
* sizeof(const char *));
2116 for(i
= 0; i
< *dim
; i
++) {
2117 if (!(vec
[i
] = secfile_lookup_str(secfile
, "%s,%d",
2118 fullpath
, (int) i
))) {
2119 SECFILE_LOG(secfile
, NULL
,
2120 "An error occurred when looking up to \"%s,%d\" entry.",
2131 /****************************************************************************
2132 Lookup an enumerator value in the secfile. Returns FALSE on error.
2133 ****************************************************************************/
2134 bool secfile_lookup_plain_enum_full(const struct section_file
*secfile
,
2136 secfile_enum_is_valid_fn_t is_valid_fn
,
2137 secfile_enum_by_name_fn_t by_name_fn
,
2138 const char *path
, ...)
2140 char fullpath
[MAX_LEN_SECPATH
];
2141 const struct entry
*pentry
;
2145 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2146 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2147 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2148 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2150 va_start(args
, path
);
2151 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2154 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2155 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2159 if (!entry_str_get(pentry
, &str
)) {
2163 *penumerator
= by_name_fn(str
, strcmp
);
2164 if (is_valid_fn(*penumerator
)) {
2168 SECFILE_LOG(secfile
, entry_section(pentry
),
2169 "Entry \"%s\": no match for \"%s\".",
2170 entry_name(pentry
), str
);
2174 /****************************************************************************
2175 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2176 ****************************************************************************/
2177 int secfile_lookup_plain_enum_default_full(const struct section_file
2178 *secfile
, int defval
,
2179 secfile_enum_is_valid_fn_t
2181 secfile_enum_by_name_fn_t
2183 const char *path
, ...)
2185 char fullpath
[MAX_LEN_SECPATH
];
2186 const struct entry
*pentry
;
2191 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2192 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2193 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2195 va_start(args
, path
);
2196 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2199 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2203 if (!entry_str_get(pentry
, &str
)) {
2207 val
= by_name_fn(str
, strcmp
);
2208 if (is_valid_fn(val
)) {
2215 /**************************************************************************
2216 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2217 vector is not owned by the registry module, and should be free by the
2219 **************************************************************************/
2220 int *secfile_lookup_plain_enum_vec_full(const struct section_file
*secfile
,
2222 secfile_enum_is_valid_fn_t
2224 secfile_enum_by_name_fn_t
2226 const char *path
, ...)
2228 char fullpath
[MAX_LEN_SECPATH
];
2233 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2234 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2235 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2236 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2238 va_start(args
, path
);
2239 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2243 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2249 /* Doesn't exist. */
2250 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2254 vec
= fc_malloc(i
* sizeof(int));
2255 for(i
= 0; i
< *dim
; i
++) {
2256 if (!secfile_lookup_plain_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2257 by_name_fn
, "%s,%d",
2258 fullpath
, (int) i
)) {
2259 SECFILE_LOG(secfile
, NULL
,
2260 "An error occurred when looking up to \"%s,%d\" entry.",
2271 /****************************************************************************
2272 Lookup a bitwise enumerator value in the secfile. Returns FALSE on error.
2273 ****************************************************************************/
2274 bool secfile_lookup_bitwise_enum_full(const struct section_file
*secfile
,
2276 secfile_enum_is_valid_fn_t is_valid_fn
,
2277 secfile_enum_by_name_fn_t by_name_fn
,
2278 const char *path
, ...)
2280 char fullpath
[MAX_LEN_SECPATH
];
2281 const struct entry
*pentry
;
2282 const char *str
, *p
;
2283 char val_name
[MAX_LEN_SECPATH
];
2287 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2288 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2289 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2290 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2292 va_start(args
, path
);
2293 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2296 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2297 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2301 if (!entry_str_get(pentry
, &str
)) {
2306 if ('\0' == str
[0]) {
2307 /* Empty string = no value. */
2311 /* Value names are separated by '|'. */
2313 p
= strchr(str
, '|');
2316 fc_strlcpy(val_name
, str
, p
- str
);
2318 /* Last segment, full copy. */
2319 sz_strlcpy(val_name
, str
);
2321 remove_leading_trailing_spaces(val_name
);
2322 val
= by_name_fn(val_name
, strcmp
);
2323 if (!is_valid_fn(val
)) {
2324 SECFILE_LOG(secfile
, entry_section(pentry
),
2325 "Entry \"%s\": no match for \"%s\".",
2326 entry_name(pentry
), val_name
);
2329 *penumerator
|= val
;
2331 } while (NULL
!= p
);
2336 /****************************************************************************
2337 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2338 ****************************************************************************/
2339 int secfile_lookup_bitwise_enum_default_full(const struct section_file
2340 *secfile
, int defval
,
2341 secfile_enum_is_valid_fn_t
2343 secfile_enum_by_name_fn_t
2345 const char *path
, ...)
2347 char fullpath
[MAX_LEN_SECPATH
];
2348 const struct entry
*pentry
;
2349 const char *str
, *p
;
2350 char val_name
[MAX_LEN_SECPATH
];
2354 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2355 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2356 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2358 va_start(args
, path
);
2359 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2362 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2366 if (!entry_str_get(pentry
, &str
)) {
2370 if ('\0' == str
[0]) {
2371 /* Empty string = no value. */
2375 /* Value names are separated by '|'. */
2378 p
= strchr(str
, '|');
2381 fc_strlcpy(val_name
, str
, p
- str
);
2383 /* Last segment, full copy. */
2384 sz_strlcpy(val_name
, str
);
2386 remove_leading_trailing_spaces(val_name
);
2387 val
= by_name_fn(val_name
, strcmp
);
2388 if (!is_valid_fn(val
)) {
2393 } while (NULL
!= p
);
2398 /**************************************************************************
2399 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2400 vector is not owned by the registry module, and should be free by the
2402 **************************************************************************/
2403 int *secfile_lookup_bitwise_enum_vec_full(const struct section_file
*secfile
,
2405 secfile_enum_is_valid_fn_t
2407 secfile_enum_by_name_fn_t
2409 const char *path
, ...)
2411 char fullpath
[MAX_LEN_SECPATH
];
2416 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2417 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2418 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2419 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2421 va_start(args
, path
);
2422 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2426 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2432 /* Doesn't exist. */
2433 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2437 vec
= fc_malloc(i
* sizeof(int));
2438 for(i
= 0; i
< *dim
; i
++) {
2439 if (!secfile_lookup_bitwise_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2440 by_name_fn
, "%s,%d",
2441 fullpath
, (int) i
)) {
2442 SECFILE_LOG(secfile
, NULL
,
2443 "An error occurred when looking up to \"%s,%d\" entry.",
2454 /****************************************************************************
2455 Lookup a value saved as string in the secfile. Returns FALSE on error.
2456 ****************************************************************************/
2457 bool secfile_lookup_enum_data(const struct section_file
*secfile
,
2458 int *pvalue
, bool bitwise
,
2459 secfile_enum_name_data_fn_t name_fn
,
2460 secfile_data_t data
, const char *path
, ...)
2462 char fullpath
[MAX_LEN_SECPATH
];
2463 const struct entry
*pentry
;
2464 const char *str
, *p
, *name
;
2465 char val_name
[MAX_LEN_SECPATH
];
2469 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2470 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= pvalue
, FALSE
);
2471 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, FALSE
);
2473 va_start(args
, path
);
2474 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2477 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2478 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2482 if (!entry_str_get(pentry
, &str
)) {
2488 if ('\0' == str
[0]) {
2489 /* Empty string = no value. */
2493 /* Value names are separated by '|'. */
2495 p
= strchr(str
, '|');
2498 fc_strlcpy(val_name
, str
, p
- str
);
2500 /* Last segment, full copy. */
2501 sz_strlcpy(val_name
, str
);
2503 remove_leading_trailing_spaces(val_name
);
2504 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2505 if (0 == fc_strcasecmp(name
, val_name
)) {
2510 SECFILE_LOG(secfile
, entry_section(pentry
),
2511 "Entry \"%s\": no match for \"%s\".",
2512 entry_name(pentry
), val_name
);
2515 *pvalue
|= 1 << val
;
2517 } while (NULL
!= p
);
2519 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2520 if (0 == fc_strcasecmp(name
, str
)) {
2526 SECFILE_LOG(secfile
, entry_section(pentry
),
2527 "Entry \"%s\": no match for \"%s\".",
2528 entry_name(pentry
), str
);
2536 /****************************************************************************
2537 Lookup a value saved as string in the secfile. Returns 'defval' on error.
2538 ****************************************************************************/
2539 int secfile_lookup_enum_default_data(const struct section_file
*secfile
,
2540 int defval
, bool bitwise
,
2541 secfile_enum_name_data_fn_t name_fn
,
2542 secfile_data_t data
,
2543 const char *path
, ...)
2545 char fullpath
[MAX_LEN_SECPATH
];
2546 const struct entry
*pentry
;
2547 const char *str
, *p
, *name
;
2548 char val_name
[MAX_LEN_SECPATH
];
2552 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2553 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, defval
);
2555 va_start(args
, path
);
2556 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2559 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2560 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2564 if (!entry_str_get(pentry
, &str
)) {
2570 if ('\0' == str
[0]) {
2571 /* Empty string = no value. */
2575 /* Value names are separated by '|'. */
2577 p
= strchr(str
, '|');
2580 fc_strlcpy(val_name
, str
, p
- str
);
2582 /* Last segment, full copy. */
2583 sz_strlcpy(val_name
, str
);
2585 remove_leading_trailing_spaces(val_name
);
2586 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2587 if (0 == strcmp(name
, val_name
)) {
2592 SECFILE_LOG(secfile
, entry_section(pentry
),
2593 "Entry \"%s\": no match for \"%s\".",
2594 entry_name(pentry
), val_name
);
2599 } while (NULL
!= p
);
2601 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2602 if (0 == strcmp(name
, str
)) {
2608 SECFILE_LOG(secfile
, entry_section(pentry
),
2609 "Entry \"%s\": no match for \"%s\".",
2610 entry_name(pentry
), str
);
2618 /****************************************************************************
2619 Lookup a vector in the secfile. Returns NULL on error. This vector
2620 is not owned by the registry module, and should be free by the user.
2621 ****************************************************************************/
2622 int *secfile_lookup_enum_vec_data(const struct section_file
*secfile
,
2623 size_t *dim
, bool bitwise
,
2624 secfile_enum_name_data_fn_t name_fn
,
2625 secfile_data_t data
, const char *path
, ...)
2627 char fullpath
[MAX_LEN_SECPATH
];
2632 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2633 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2634 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
2636 va_start(args
, path
);
2637 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2641 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2647 /* Doesn't exist. */
2648 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2652 vec
= fc_malloc(i
* sizeof(int));
2653 for (i
= 0; i
< *dim
; i
++) {
2654 if (!secfile_lookup_enum_data(secfile
, vec
+ i
, bitwise
, name_fn
, data
,
2655 "%s,%d", fullpath
, (int) i
)) {
2656 SECFILE_LOG(secfile
, NULL
,
2657 "An error occurred when looking up to \"%s,%d\" entry.",
2668 /****************************************************************************
2669 Returns the first section matching the name.
2670 ****************************************************************************/
2671 struct section
*secfile_section_by_name(const struct section_file
*secfile
,
2674 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2676 section_list_iterate(secfile
->sections
, psection
) {
2677 if (0 == strcmp(section_name(psection
), name
)) {
2680 } section_list_iterate_end
;
2685 /**************************************************************************
2686 Find a section by path.
2687 **************************************************************************/
2688 struct section
*secfile_section_lookup(const struct section_file
*secfile
,
2689 const char *path
, ...)
2691 char fullpath
[MAX_LEN_SECPATH
];
2694 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2696 va_start(args
, path
);
2697 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2700 return secfile_section_by_name(secfile
, fullpath
);
2703 /**************************************************************************
2704 Returns the list of sections. This list is owned by the registry module
2705 and shouldn't be modified and destroyed.
2706 **************************************************************************/
2707 const struct section_list
*
2708 secfile_sections(const struct section_file
*secfile
)
2710 return (NULL
!= secfile
? secfile
->sections
: NULL
);
2713 /**************************************************************************
2714 Returns the list of sections which match the name prefix. Returns NULL
2715 if no section was found. This list is not owned by the registry module
2716 and the user must destroy it when he finished to work with it.
2717 **************************************************************************/
2718 struct section_list
*
2719 secfile_sections_by_name_prefix(const struct section_file
*secfile
,
2722 struct section_list
*matches
= NULL
;
2725 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2726 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= prefix
, NULL
);
2728 len
= strlen(prefix
);
2733 section_list_iterate(secfile
->sections
, psection
) {
2734 if (0 == strncmp(section_name(psection
), prefix
, len
)) {
2735 if (NULL
== matches
) {
2736 matches
= section_list_new();
2738 section_list_append(matches
, psection
);
2740 } section_list_iterate_end
;
2745 /**************************************************************************
2746 Create a new section in the secfile.
2747 **************************************************************************/
2748 struct section
*secfile_section_new(struct section_file
*secfile
,
2751 struct section
*psection
;
2753 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2755 if (NULL
== name
|| '\0' == name
[0]) {
2756 SECFILE_LOG(secfile
, NULL
, "Cannot create a section without name.");
2760 if (!is_secfile_entry_name_valid(name
)) {
2761 SECFILE_LOG(secfile
, NULL
, "\"%s\" is not a valid section name.",
2766 if (NULL
!= secfile_section_by_name(secfile
, name
)) {
2767 /* We cannot duplicate sections in any case! Not even if one is
2768 * include -section and the other not. */
2769 SECFILE_LOG(secfile
, NULL
, "Section \"%s\" already exists.", name
);
2773 psection
= fc_malloc(sizeof(struct section
));
2774 psection
->include
= FALSE
;
2775 psection
->name
= fc_strdup(name
);
2776 psection
->entries
= entry_list_new_full(entry_destroy
);
2778 /* Append to secfile. */
2779 psection
->secfile
= secfile
;
2780 section_list_append(secfile
->sections
, psection
);
2782 if (NULL
!= secfile
->hash
.sections
) {
2783 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2789 /**************************************************************************
2790 Remove this section from the secfile.
2791 **************************************************************************/
2792 void section_destroy(struct section
*psection
)
2794 struct section_file
*secfile
;
2796 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2798 section_clear_all(psection
);
2800 if ((secfile
= psection
->secfile
)) {
2801 /* Detach from secfile. */
2802 if (section_list_remove(secfile
->sections
, psection
)) {
2803 /* This has called section_destroy() already then. */
2806 if (NULL
!= secfile
->hash
.sections
) {
2807 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2811 entry_list_destroy(psection
->entries
);
2812 free(psection
->name
);
2816 /**************************************************************************
2818 **************************************************************************/
2819 void section_clear_all(struct section
*psection
)
2821 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2823 /* This include the removing of the hash datas. */
2824 entry_list_clear(psection
->entries
);
2826 if (0 < entry_list_size(psection
->entries
)) {
2827 SECFILE_LOG(psection
->secfile
, psection
,
2828 "After clearing all, %d entries are still remaining.",
2829 entry_list_size(psection
->entries
));
2833 /**************************************************************************
2834 Change the section name. Returns TRUE on success.
2835 **************************************************************************/
2836 bool section_set_name(struct section
*psection
, const char *name
)
2838 struct section_file
*secfile
;
2839 struct section
*pother
;
2841 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, FALSE
);
2842 secfile
= psection
->secfile
;
2843 SECFILE_RETURN_VAL_IF_FAIL(secfile
, psection
, NULL
!= secfile
, FALSE
);
2845 if (NULL
== name
|| '\0' == name
[0]) {
2846 SECFILE_LOG(secfile
, psection
, "No new name for section \"%s\".",
2851 if (!is_secfile_entry_name_valid(name
)) {
2852 SECFILE_LOG(secfile
, psection
,
2853 "\"%s\" is not a valid section name for section \"%s\".",
2854 name
, psection
->name
);
2858 if ((pother
= secfile_section_by_name(secfile
, name
))
2859 && pother
!= psection
) {
2860 /* We cannot duplicate sections in any case! */
2861 SECFILE_LOG(secfile
, psection
, "Section \"%s\" already exists.", name
);
2865 /* Remove old references in the hash tables. */
2866 if (NULL
!= secfile
->hash
.sections
) {
2867 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2869 if (NULL
!= secfile
->hash
.entries
) {
2870 entry_list_iterate(psection
->entries
, pentry
) {
2871 secfile_hash_delete(secfile
, pentry
);
2872 } entry_list_iterate_end
;
2875 /* Really rename. */
2876 free(psection
->name
);
2877 psection
->name
= fc_strdup(name
);
2879 /* Reinsert new references into the hash tables. */
2880 if (NULL
!= secfile
->hash
.sections
) {
2881 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2883 if (NULL
!= secfile
->hash
.entries
) {
2884 entry_list_iterate(psection
->entries
, pentry
) {
2885 secfile_hash_insert(secfile
, pentry
);
2886 } entry_list_iterate_end
;
2892 /**************************************************************************
2893 Returns a list containing all the entries. This list is owned by the
2894 secfile, so don't modify or destroy it.
2895 **************************************************************************/
2896 const struct entry_list
*section_entries(const struct section
*psection
)
2898 return (NULL
!= psection
? psection
->entries
: NULL
);
2901 /**************************************************************************
2902 Returns the the first entry matching the name.
2903 **************************************************************************/
2904 struct entry
*section_entry_by_name(const struct section
*psection
,
2907 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2909 entry_list_iterate(psection
->entries
, pentry
) {
2910 if (0 == strcmp(entry_name(pentry
), name
)) {
2914 } entry_list_iterate_end
;
2919 /**************************************************************************
2920 Returns the entry matching the path.
2921 **************************************************************************/
2922 struct entry
*section_entry_lookup(const struct section
*psection
,
2923 const char *path
, ...)
2925 char fullpath
[MAX_LEN_SECPATH
];
2926 struct entry
*pentry
;
2929 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2931 va_start(args
, path
);
2932 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2935 if ((pentry
= section_entry_by_name(psection
, fullpath
))) {
2939 /* Try with full path. */
2940 if ((pentry
= secfile_entry_by_path(psection
->secfile
, fullpath
))
2941 && psection
== entry_section(pentry
)) {
2942 /* Unsure this is really owned by this section. */
2950 /* An 'entry' is a string, integer, boolean or string vector;
2951 * See enum entry_type in registry.h.
2954 struct section
*psection
; /* Parent section. */
2955 char *name
; /* Name, not including section prefix. */
2956 enum entry_type type
; /* The type of the entry. */
2957 int used
; /* Number of times entry looked up. */
2958 char *comment
; /* Comment, may be NULL. */
2975 char *value
; /* Malloced string. */
2976 bool escaped
; /* " or $. Usually TRUE */
2977 bool gt_marking
; /* Save with gettext marking. */
2982 /**************************************************************************
2983 Returns a new entry.
2984 **************************************************************************/
2985 static struct entry
*entry_new(struct section
*psection
, const char *name
)
2987 struct section_file
*secfile
;
2988 struct entry
*pentry
;
2990 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2992 secfile
= psection
->secfile
;
2993 if (NULL
== name
|| '\0' == name
[0]) {
2994 SECFILE_LOG(secfile
, psection
, "Cannot create an entry without name.");
2998 if (!is_secfile_entry_name_valid(name
)) {
2999 SECFILE_LOG(secfile
, psection
, "\"%s\" is not a valid entry name.",
3004 if (!secfile
->allow_duplicates
3005 && NULL
!= section_entry_by_name(psection
, name
)) {
3006 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3010 pentry
= fc_malloc(sizeof(struct entry
));
3011 pentry
->name
= fc_strdup(name
);
3012 pentry
->type
= -1; /* Invalid case. */
3014 pentry
->comment
= NULL
;
3016 /* Append to section. */
3017 pentry
->psection
= psection
;
3018 entry_list_append(psection
->entries
, pentry
);
3020 /* Notify secfile. */
3021 secfile
->num_entries
++;
3022 secfile_hash_insert(secfile
, pentry
);
3027 /**************************************************************************
3028 Returns a new entry of type ENTRY_INT.
3029 **************************************************************************/
3030 struct entry
*section_entry_int_new(struct section
*psection
,
3031 const char *name
, int value
)
3033 struct entry
*pentry
= entry_new(psection
, name
);
3035 if (NULL
!= pentry
) {
3036 pentry
->type
= ENTRY_INT
;
3037 pentry
->integer
.value
= value
;
3043 /**************************************************************************
3044 Returns a new entry of type ENTRY_BOOL.
3045 **************************************************************************/
3046 struct entry
*section_entry_bool_new(struct section
*psection
,
3047 const char *name
, bool value
)
3049 struct entry
*pentry
= entry_new(psection
, name
);
3051 if (NULL
!= pentry
) {
3052 pentry
->type
= ENTRY_BOOL
;
3053 pentry
->boolean
.value
= value
;
3059 /**************************************************************************
3060 Returns a new entry of type ENTRY_FLOAT.
3061 **************************************************************************/
3062 struct entry
*section_entry_float_new(struct section
*psection
,
3063 const char *name
, float value
)
3065 struct entry
*pentry
= entry_new(psection
, name
);
3067 if (NULL
!= pentry
) {
3068 pentry
->type
= ENTRY_FLOAT
;
3069 pentry
->floating
.value
= value
;
3075 /**************************************************************************
3076 Returns a new entry of type ENTRY_STR.
3077 **************************************************************************/
3078 struct entry
*section_entry_str_new(struct section
*psection
,
3079 const char *name
, const char *value
,
3082 struct entry
*pentry
= entry_new(psection
, name
);
3084 if (NULL
!= pentry
) {
3085 pentry
->type
= ENTRY_STR
;
3086 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3087 pentry
->string
.escaped
= escaped
;
3088 pentry
->string
.gt_marking
= FALSE
;
3094 /**************************************************************************
3095 Returns a new entry of type ENTRY_FILEREFERENCE.
3096 **************************************************************************/
3097 static struct entry
*section_entry_filereference_new(struct section
*psection
,
3098 const char *name
, const char *value
)
3100 struct entry
*pentry
= entry_new(psection
, name
);
3102 if (NULL
!= pentry
) {
3103 pentry
->type
= ENTRY_FILEREFERENCE
;
3104 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3110 /**************************************************************************
3111 Entry structure destructor.
3112 **************************************************************************/
3113 void entry_destroy(struct entry
*pentry
)
3115 struct section_file
*secfile
;
3116 struct section
*psection
;
3118 if (NULL
== pentry
) {
3122 if ((psection
= pentry
->psection
)) {
3123 /* Detach from section. */
3124 if (entry_list_remove(psection
->entries
, pentry
)) {
3125 /* This has called entry_destroy() already then. */
3128 if ((secfile
= psection
->secfile
)) {
3129 /* Detach from secfile. */
3130 secfile
->num_entries
--;
3131 secfile_hash_delete(secfile
, pentry
);
3135 /* Specific type free. */
3136 switch (pentry
->type
) {
3143 case ENTRY_FILEREFERENCE
:
3144 free(pentry
->string
.value
);
3150 if (NULL
!= pentry
->comment
) {
3151 free(pentry
->comment
);
3156 /**************************************************************************
3157 Returns the parent section of this entry.
3158 **************************************************************************/
3159 struct section
*entry_section(const struct entry
*pentry
)
3161 return (NULL
!= pentry
? pentry
->psection
: NULL
);
3164 /**************************************************************************
3165 Returns the type of this entry or -1 or error.
3166 **************************************************************************/
3167 enum entry_type
entry_type(const struct entry
*pentry
)
3169 return (NULL
!= pentry
? pentry
->type
: -1);
3172 /**************************************************************************
3173 Build the entry path. Returns like snprintf().
3174 **************************************************************************/
3175 int entry_path(const struct entry
*pentry
, char *buf
, size_t buf_len
)
3177 return fc_snprintf(buf
, buf_len
, "%s.%s",
3178 section_name(entry_section(pentry
)),
3179 entry_name(pentry
));
3182 /**************************************************************************
3183 Returns the name of this entry.
3184 **************************************************************************/
3185 const char *entry_name(const struct entry
*pentry
)
3187 return (NULL
!= pentry
? pentry
->name
: NULL
);
3190 /**************************************************************************
3191 Sets the name of the entry. Returns TRUE on success.
3192 **************************************************************************/
3193 bool entry_set_name(struct entry
*pentry
, const char *name
)
3195 struct section
*psection
;
3196 struct section_file
*secfile
;
3198 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3199 psection
= pentry
->psection
;
3200 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= psection
, FALSE
);
3201 secfile
= psection
->secfile
;
3202 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= secfile
, FALSE
);
3204 if (NULL
== name
|| '\0' == name
[0]) {
3205 SECFILE_LOG(secfile
, psection
, "No new name for entry \"%s\".",
3210 if (!is_secfile_entry_name_valid(name
)) {
3211 SECFILE_LOG(secfile
, psection
,
3212 "\"%s\" is not a valid entry name for entry \"%s\".",
3213 name
, pentry
->name
);
3217 if (!secfile
->allow_duplicates
) {
3218 struct entry
*pother
= section_entry_by_name(psection
, name
);
3220 if (NULL
!= pother
&& pother
!= pentry
) {
3221 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3226 /* Remove from hash table the old path. */
3227 secfile_hash_delete(secfile
, pentry
);
3229 /* Really rename the entry. */
3231 pentry
->name
= fc_strdup(name
);
3233 /* Insert into hash table the new path. */
3234 secfile_hash_insert(secfile
, pentry
);
3238 /**************************************************************************
3239 Returns the comment associated to this entry.
3240 **************************************************************************/
3241 const char *entry_comment(const struct entry
*pentry
)
3243 return (NULL
!= pentry
? pentry
->comment
: NULL
);
3246 /**************************************************************************
3247 Sets a comment for the entry. Pass NULL to remove the current one.
3248 **************************************************************************/
3249 void entry_set_comment(struct entry
*pentry
, const char *comment
)
3251 if (NULL
== pentry
) {
3255 if (NULL
!= pentry
->comment
) {
3256 free(pentry
->comment
);
3259 pentry
->comment
= (NULL
!= comment
? fc_strdup(comment
) : NULL
);
3262 /**************************************************************************
3263 Returns TRUE if this entry has been used.
3264 **************************************************************************/
3265 static inline bool entry_used(const struct entry
*pentry
)
3267 return (0 < pentry
->used
);
3270 /**************************************************************************
3271 Increase the used count.
3272 **************************************************************************/
3273 static inline void entry_use(struct entry
*pentry
)
3278 /**************************************************************************
3279 Gets an boolean value. Returns TRUE on success.
3280 On old saved files, 0 and 1 can also be considered as bool.
3281 **************************************************************************/
3282 bool entry_bool_get(const struct entry
*pentry
, bool *value
)
3284 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3286 if (ENTRY_INT
== pentry
->type
3287 && (pentry
->integer
.value
== 0
3288 || pentry
->integer
.value
== 1)
3289 && NULL
!= pentry
->psection
3290 && NULL
!= pentry
->psection
->secfile
3291 && pentry
->psection
->secfile
->allow_digital_boolean
) {
3292 *value
= (0 != pentry
->integer
.value
);
3296 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3297 ENTRY_BOOL
== pentry
->type
, FALSE
);
3299 if (NULL
!= value
) {
3300 *value
= pentry
->boolean
.value
;
3305 /**************************************************************************
3306 Sets an boolean value. Returns TRUE on success.
3307 **************************************************************************/
3308 bool entry_bool_set(struct entry
*pentry
, bool value
)
3310 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3311 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3312 ENTRY_BOOL
== pentry
->type
, FALSE
);
3314 pentry
->boolean
.value
= value
;
3318 /**************************************************************************
3319 Gets an floating value. Returns TRUE on success.
3320 **************************************************************************/
3321 bool entry_float_get(const struct entry
*pentry
, float *value
)
3323 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3324 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3325 ENTRY_FLOAT
== pentry
->type
, FALSE
);
3327 if (NULL
!= value
) {
3328 *value
= pentry
->floating
.value
;
3334 /**************************************************************************
3335 Sets an floating value. Returns TRUE on success.
3336 **************************************************************************/
3337 bool entry_float_set(struct entry
*pentry
, float value
)
3339 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3340 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3341 ENTRY_FLOAT
== pentry
->type
, FALSE
);
3343 pentry
->floating
.value
= value
;
3348 /**************************************************************************
3349 Gets an integer value. Returns TRUE on success.
3350 **************************************************************************/
3351 bool entry_int_get(const struct entry
*pentry
, int *value
)
3353 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3354 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3355 ENTRY_INT
== pentry
->type
, FALSE
);
3357 if (NULL
!= value
) {
3358 *value
= pentry
->integer
.value
;
3363 /**************************************************************************
3364 Sets an integer value. Returns TRUE on success.
3365 **************************************************************************/
3366 bool entry_int_set(struct entry
*pentry
, int value
)
3368 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3369 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3370 ENTRY_INT
== pentry
->type
, FALSE
);
3372 pentry
->integer
.value
= value
;
3376 /**************************************************************************
3377 Gets an string value. Returns TRUE on success.
3378 **************************************************************************/
3379 bool entry_str_get(const struct entry
*pentry
, const char **value
)
3381 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3382 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3383 ENTRY_STR
== pentry
->type
, FALSE
);
3385 if (NULL
!= value
) {
3386 *value
= pentry
->string
.value
;
3391 /**************************************************************************
3392 Sets an string value. Returns TRUE on success.
3393 **************************************************************************/
3394 bool entry_str_set(struct entry
*pentry
, const char *value
)
3396 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3397 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3398 ENTRY_STR
== pentry
->type
, FALSE
);
3400 free(pentry
->string
.value
);
3401 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3405 /**************************************************************************
3406 Returns if the string would be escaped.
3407 **************************************************************************/
3408 bool entry_str_escaped(const struct entry
*pentry
)
3410 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3411 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3412 ENTRY_STR
== pentry
->type
, FALSE
);
3414 return pentry
->string
.escaped
;
3417 /**************************************************************************
3418 Sets if the string would be escaped. Returns TRUE on success.
3419 **************************************************************************/
3420 bool entry_str_set_escaped(struct entry
*pentry
, bool escaped
)
3422 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3423 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3424 ENTRY_STR
== pentry
->type
, FALSE
);
3426 pentry
->string
.escaped
= escaped
;
3430 /**************************************************************************
3431 Sets if the string should get gettext marking. Returns TRUE on success.
3432 **************************************************************************/
3433 bool entry_str_set_gt_marking(struct entry
*pentry
, bool gt_marking
)
3435 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3436 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3437 ENTRY_STR
== pentry
->type
, FALSE
);
3439 pentry
->string
.gt_marking
= gt_marking
;
3444 /**************************************************************************
3445 Push an entry into a file stream.
3446 **************************************************************************/
3447 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
)
3449 static char buf
[8192];
3453 switch (pentry
->type
) {
3455 fz_fprintf(fs
, "%s", pentry
->boolean
.value
? "TRUE" : "FALSE");
3458 fz_fprintf(fs
, "%d", pentry
->integer
.value
);
3461 snprintf(buf
, sizeof(buf
), "%f", pentry
->floating
.value
);
3462 for (i
= 0; buf
[i
] != '\0' ; i
++) {
3463 if (buf
[i
] == '.') {
3469 /* There's no '.' so it would seem like a integer value when loaded.
3470 * Force it not to look like an integer by adding ".0" */
3471 fz_fprintf(fs
, "%s.0", buf
);
3473 fz_fprintf(fs
, "%s", buf
);
3477 if (pentry
->string
.escaped
) {
3478 make_escapes(pentry
->string
.value
, buf
, sizeof(buf
));
3479 if (pentry
->string
.gt_marking
) {
3480 fz_fprintf(fs
, "_(\"%s\")", buf
);
3482 fz_fprintf(fs
, "\"%s\"", buf
);
3485 fz_fprintf(fs
, "$%s$", pentry
->string
.value
);
3488 case ENTRY_FILEREFERENCE
:
3489 fz_fprintf(fs
, "*%s*", pentry
->string
.value
);
3494 /**************************************************************************
3495 Creates a new entry from the token.
3496 **************************************************************************/
3497 static void entry_from_inf_token(struct section
*psection
, const char *name
,
3498 const char *tok
, struct inputfile
*inf
)
3500 if (!entry_from_token(psection
, name
, tok
)) {
3501 log_error("%s", inf_log_str(inf
, "Entry value not recognized: %s", tok
));