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>
162 #include "deprecations.h"
164 #include "inputfile.h"
168 #include "registry.h"
169 #include "section_file.h"
173 #include "registry_ini.h"
175 #define MAX_LEN_SECPATH 1024
177 /* Set to FALSE for old-style savefiles. */
178 #define SAVE_TABLES TRUE
180 #define SPECVEC_TAG astring
183 static inline bool entry_used(const struct entry
*pentry
);
184 static inline void entry_use(struct entry
*pentry
);
186 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
);
187 static void entry_from_inf_token(struct section
*psection
, const char *name
,
188 const char *tok
, struct inputfile
*file
);
190 /* An 'entry' is a string, integer, boolean or string vector;
191 * See enum entry_type in registry.h.
194 struct section
*psection
; /* Parent section. */
195 char *name
; /* Name, not including section prefix. */
196 enum entry_type type
; /* The type of the entry. */
197 int used
; /* Number of times entry looked up. */
198 char *comment
; /* Comment, may be NULL. */
215 char *value
; /* Malloced string. */
216 bool escaped
; /* " or $. Usually TRUE */
217 bool raw
; /* Do not add anything. */
218 bool gt_marking
; /* Save with gettext marking. */
223 static struct entry
*section_entry_filereference_new(struct section
*psection
,
224 const char *name
, const char *value
);
226 /***************************************************************************
227 Simplification of fileinfoname().
228 ***************************************************************************/
229 static const char *datafilename(const char *filename
)
231 return fileinfoname(get_data_dirs(), filename
);
234 /**************************************************************************
235 Ensure name is correct to use it as section or entry name.
236 **************************************************************************/
237 static bool is_secfile_entry_name_valid(const char *name
)
239 static const char *const allowed
= "_.,-[]";
241 while ('\0' != *name
) {
242 if (!fc_isalnum(*name
) && NULL
== strchr(allowed
, *name
)) {
250 /**************************************************************************
251 Insert an entry into the hash table. Returns TRUE on success.
252 **************************************************************************/
253 static bool secfile_hash_insert(struct section_file
*secfile
,
254 struct entry
*pentry
)
257 struct entry
*hentry
;
259 if (NULL
== secfile
->hash
.entries
) {
260 /* Consider as success if this secfile doesn't have built the entries
265 entry_path(pentry
, buf
, sizeof(buf
));
266 if (entry_hash_replace_full(secfile
->hash
.entries
, buf
, pentry
,
269 if (!secfile
->allow_duplicates
) {
270 SECFILE_LOG(secfile
, entry_section(hentry
),
271 "Tried to insert same value twice: %s", buf
);
279 /**************************************************************************
280 Delete an entry from the hash table. Returns TRUE on success.
281 **************************************************************************/
282 static bool secfile_hash_delete(struct section_file
*secfile
,
283 struct entry
*pentry
)
287 if (NULL
== secfile
->hash
.entries
) {
288 /* Consider as success if this secfile doesn't have built the entries
293 entry_path(pentry
, buf
, sizeof(buf
));
294 return entry_hash_remove(secfile
->hash
.entries
, buf
);
297 /**************************************************************************
298 Base function to load a section file. Note it closes the inputfile.
299 **************************************************************************/
300 static struct section_file
*secfile_from_input_file(struct inputfile
*inf
,
301 const char *filename
,
303 bool allow_duplicates
)
305 struct section_file
*secfile
;
306 struct section
*psection
= NULL
;
307 struct section
*single_section
= NULL
;
308 bool table_state
= FALSE
; /* TRUE when within tabular format. */
309 int table_lineno
= 0; /* Row number in tabular, 0 top data row. */
312 struct astring base_name
= ASTRING_INIT
; /* for table or single entry */
313 struct astring field_name
= ASTRING_INIT
;
314 struct astring_vector columns
; /* astrings for column headings */
315 bool found_my_section
= FALSE
;
322 /* Assign the real value later, to speed up the creation of new entries. */
323 secfile
= secfile_new(TRUE
);
325 secfile
->name
= fc_strdup(filename
);
327 secfile
->name
= NULL
;
330 astring_vector_init(&columns
);
333 log_verbose("Reading registry from \"%s\"", filename
);
335 log_verbose("Reading registry");
338 while (!inf_at_eof(inf
)) {
339 if (inf_token(inf
, INF_TOK_EOL
)) {
342 if (inf_at_eof(inf
)) {
343 /* may only realise at eof after trying to read eol above */
346 tok
= inf_token(inf
, INF_TOK_SECTION_NAME
);
348 if (found_my_section
) {
349 /* This shortcut will stop any further loading after the requested
350 * section has been loaded (i.e., at the start of a new section).
351 * This is needed to make the behavior useful, since the whole
352 * purpose is to short-cut further loading of the file. However
353 * normally a section may be split up, and that will no longer
354 * work here because it will be short-cut. */
355 SECFILE_LOG(secfile
, psection
, "%s",
356 inf_log_str(inf
, "Found requested section; finishing"));
360 SECFILE_LOG(secfile
, psection
, "%s",
361 inf_log_str(inf
, "New section during table"));
365 /* Check if we already have a section with this name.
366 (Could ignore this and have a duplicate sections internally,
367 but then secfile_get_secnames_prefix would return duplicates.)
368 Duplicate section in input are likely to be useful for includes.
370 psection
= secfile_section_by_name(secfile
, tok
);
372 if (!section
|| strcmp(tok
, section
) == 0) {
373 psection
= secfile_section_new(secfile
, tok
);
375 single_section
= psection
;
376 found_my_section
= TRUE
;
380 if (!inf_token(inf
, INF_TOK_EOL
)) {
381 SECFILE_LOG(secfile
, psection
, "%s",
382 inf_log_str(inf
, "Expected end of line"));
388 if (inf_token(inf
, INF_TOK_TABLE_END
)) {
390 SECFILE_LOG(secfile
, psection
, "%s",
391 inf_log_str(inf
, "Misplaced \"}\""));
395 if (!inf_token(inf
, INF_TOK_EOL
)) {
396 SECFILE_LOG(secfile
, psection
, "%s",
397 inf_log_str(inf
, "Expected end of line"));
407 int num_columns
= astring_vector_size(&columns
);
410 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
411 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
412 SECFILE_LOG(secfile
, psection
, "%s",
413 inf_log_str(inf
, "Expected value"));
418 if (i
< num_columns
) {
419 astr_set(&field_name
, "%s%d.%s", astr_str(&base_name
),
420 table_lineno
, astr_str(&columns
.p
[i
]));
422 astr_set(&field_name
, "%s%d.%s,%d", astr_str(&base_name
),
423 table_lineno
, astr_str(&columns
.p
[num_columns
- 1]),
424 (int) (i
- num_columns
+ 1));
426 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
427 } while (inf_token(inf
, INF_TOK_COMMA
));
429 if (!inf_token(inf
, INF_TOK_EOL
)) {
430 SECFILE_LOG(secfile
, psection
, "%s",
431 inf_log_str(inf
, "Expected end of line"));
439 if (!(tok
= inf_token(inf
, INF_TOK_ENTRY_NAME
))) {
440 SECFILE_LOG(secfile
, psection
, "%s",
441 inf_log_str(inf
, "Expected entry name"));
446 /* need to store tok before next calls: */
447 astr_set(&base_name
, "%s", tok
);
449 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
451 if (inf_token(inf
, INF_TOK_TABLE_START
)) {
455 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
456 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
457 SECFILE_LOG(secfile
, psection
, "%s",
458 inf_log_str(inf
, "Expected value"));
462 if (tok
[0] != '\"') {
463 SECFILE_LOG(secfile
, psection
, "%s",
464 inf_log_str(inf
, "Table column header non-string"));
468 { /* expand columns: */
470 n_prev
= astring_vector_size(&columns
);
471 for (j
= i
+ 1; j
< n_prev
; j
++) {
472 astr_free(&columns
.p
[j
]);
474 astring_vector_reserve(&columns
, i
+ 1);
475 for (j
= n_prev
; j
< i
+ 1; j
++) {
476 astr_init(&columns
.p
[j
]);
479 astr_set(&columns
.p
[i
], "%s", tok
+ 1);
481 } while (inf_token(inf
, INF_TOK_COMMA
));
483 if (!inf_token(inf
, INF_TOK_EOL
)) {
484 SECFILE_LOG(secfile
, psection
, "%s",
485 inf_log_str(inf
, "Expected end of line"));
493 /* ordinary value: */
497 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
498 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
499 SECFILE_LOG(secfile
, psection
, "%s",
500 inf_log_str(inf
, "Expected value"));
505 entry_from_inf_token(psection
, astr_str(&base_name
), tok
, inf
);
507 astr_set(&field_name
, "%s,%d", astr_str(&base_name
), i
);
508 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
510 } while (inf_token(inf
, INF_TOK_COMMA
));
511 if (!inf_token(inf
, INF_TOK_EOL
)) {
512 SECFILE_LOG(secfile
, psection
, "%s",
513 inf_log_str(inf
, "Expected end of line"));
520 SECFILE_LOG(secfile
, psection
,
521 "Finished registry before end of table");
527 astr_free(&base_name
);
528 astr_free(&field_name
);
529 for (i
= 0; i
< astring_vector_size(&columns
); i
++) {
530 astr_free(&columns
.p
[i
]);
532 astring_vector_free(&columns
);
534 if (section
!= NULL
) {
535 if (!found_my_section
) {
536 secfile_destroy(secfile
);
540 /* Build the entry hash table with single section information */
541 secfile
->allow_duplicates
= allow_duplicates
;
542 entry_list_iterate(section_entries(single_section
), pentry
) {
543 if (!secfile_hash_insert(secfile
, pentry
)) {
544 secfile_destroy(secfile
);
547 } entry_list_iterate_end
;
553 /* Build the entry hash table. */
554 secfile
->allow_duplicates
= allow_duplicates
;
555 secfile
->hash
.entries
= entry_hash_new_nentries(secfile
->num_entries
);
557 section_list_iterate(secfile
->sections
, hashing_section
) {
558 entry_list_iterate(section_entries(hashing_section
), pentry
) {
559 if (!secfile_hash_insert(secfile
, pentry
)) {
563 } entry_list_iterate_end
;
567 } section_list_iterate_end
;
570 secfile_destroy(secfile
);
577 /**************************************************************************
578 Create a section file from a file, read only one particular section.
579 Returns NULL on error.
580 **************************************************************************/
581 struct section_file
*secfile_load_section(const char *filename
,
583 bool allow_duplicates
)
585 char real_filename
[1024];
587 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
588 return secfile_from_input_file(inf_from_file(real_filename
, datafilename
),
589 filename
, section
, allow_duplicates
);
592 /**************************************************************************
593 Create a section file from a stream. Returns NULL on error.
594 **************************************************************************/
595 struct section_file
*secfile_from_stream(fz_FILE
*stream
,
596 bool allow_duplicates
)
598 return secfile_from_input_file(inf_from_stream(stream
, datafilename
),
599 NULL
, NULL
, allow_duplicates
);
602 /**************************************************************************
603 Returns TRUE iff the character is legal in a table entry name.
604 **************************************************************************/
605 static bool is_legal_table_entry_name(char c
, bool num
)
607 return (num
? fc_isalnum(c
) : fc_isalpha(c
)) || c
== '_';
610 /**************************************************************************
611 Save the previously filled in section_file to disk.
613 There is now limited ability to save in the new tabular format
614 (to give smaller savefiles).
615 The start of a table is detected by an entry with name of the form:
616 (alphabetical_component)(zero)(period)(alphanumeric_component)
617 Eg: u0.id, or c0.id, in the freeciv savefile.
618 The alphabetical component is taken as the "name" of the table,
619 and the component after the period as the first column name.
620 This should be followed by the other column values for u0,
621 and then subsequent u1, u2, etc, in strict order with no omissions,
622 and with all of the columns for all uN in the same order as for u0.
624 If compression_level is non-zero, then compress using zlib. (Should
625 only supply non-zero compression_level if already know that FREECIV_HAVE_LIBZ.)
626 Below simply specifies FZ_ZLIB method, since fz_fromFile() automatically
627 changes to FZ_PLAIN method when level == 0.
628 **************************************************************************/
629 bool secfile_save(const struct section_file
*secfile
, const char *filename
,
630 int compression_level
, enum fz_method compression_method
)
632 char real_filename
[1024];
633 char pentry_name
[128];
634 const char *col_entry_name
;
636 const struct entry_list_link
*ent_iter
, *save_iter
, *col_iter
;
637 struct entry
*pentry
, *col_pentry
;
640 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
642 if (NULL
== filename
) {
643 filename
= secfile
->name
;
646 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
647 fs
= fz_from_file(real_filename
, "w",
648 compression_method
, compression_level
);
651 SECFILE_LOG(secfile
, NULL
, _("Could not open %s for writing"), real_filename
);
656 section_list_iterate(secfile
->sections
, psection
) {
657 if (psection
->special
== EST_INCLUDE
) {
658 for (ent_iter
= entry_list_head(section_entries(psection
));
659 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
660 ent_iter
= entry_list_link_next(ent_iter
)) {
662 fc_assert(!strcmp(entry_name(pentry
), "file"));
664 fz_fprintf(fs
, "*include ");
665 entry_to_file(pentry
, fs
);
666 fz_fprintf(fs
, "\n");
668 } else if (psection
->special
== EST_COMMENT
) {
669 for (ent_iter
= entry_list_head(section_entries(psection
));
670 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
671 ent_iter
= entry_list_link_next(ent_iter
)) {
673 fc_assert(!strcmp(entry_name(pentry
), "comment"));
675 entry_to_file(pentry
, fs
);
676 fz_fprintf(fs
, "\n");
679 fz_fprintf(fs
, "\n[%s]\n", section_name(psection
));
681 /* Following doesn't use entry_list_iterate() because we want to do
682 * tricky things with the iterators...
684 for (ent_iter
= entry_list_head(section_entries(psection
));
685 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
686 ent_iter
= entry_list_link_next(ent_iter
)) {
689 /* Tables: break out of this loop if this is a non-table
690 * entry (pentry and ent_iter unchanged) or after table (pentry
691 * and ent_iter suitably updated, pentry possibly NULL).
692 * After each table, loop again in case the next entry
696 char *c
, *first
, base
[64];
697 int offset
, irow
, icol
, ncol
;
699 /* Example: for first table name of "xyz0.blah":
700 * first points to the original string pentry->name
701 * base contains "xyz";
702 * offset = 5 (so first+offset gives "blah")
703 * note strlen(base) = offset - 2
710 sz_strlcpy(pentry_name
, entry_name(pentry
));
711 c
= first
= pentry_name
;
712 if (*c
== '\0' || !is_legal_table_entry_name(*c
, FALSE
)) {
715 for (; *c
!= '\0' && is_legal_table_entry_name(*c
, FALSE
); c
++) {
718 if (0 != strncmp(c
, "0.", 2)) {
722 if (*c
== '\0' || !is_legal_table_entry_name(*c
, TRUE
)) {
727 first
[offset
- 2] = '\0';
728 sz_strlcpy(base
, first
);
729 first
[offset
- 2] = '0';
730 fz_fprintf(fs
, "%s={", base
);
732 /* Save an iterator at this first entry, which we can later use
733 * to repeatedly iterate over column names:
735 save_iter
= ent_iter
;
737 /* write the column names, and calculate ncol: */
739 col_iter
= save_iter
;
740 for (; (col_pentry
= entry_list_link_data(col_iter
));
741 col_iter
= entry_list_link_next(col_iter
)) {
742 col_entry_name
= entry_name(col_pentry
);
743 if (strncmp(col_entry_name
, first
, offset
) != 0) {
746 fz_fprintf(fs
, "%s\"%s\"", (ncol
== 0 ? "" : ","),
747 col_entry_name
+ offset
);
750 fz_fprintf(fs
, "\n");
752 /* Iterate over rows and columns, incrementing ent_iter as we go,
753 * and writing values to the table. Have a separate iterator
754 * to the column names to check they all match.
757 col_iter
= save_iter
;
759 char expect
[128]; /* pentry->name we're expecting */
761 pentry
= entry_list_link_data(ent_iter
);
762 col_pentry
= entry_list_link_data(col_iter
);
764 fc_snprintf(expect
, sizeof(expect
), "%s%d.%s",
765 base
, irow
, entry_name(col_pentry
) + offset
);
767 /* break out of tabular if doesn't match: */
768 if ((!pentry
) || (strcmp(entry_name(pentry
), expect
) != 0)) {
770 /* If the second or later row of a table is missing some
771 * entries that the first row had, we drop out of the tabular
772 * format. This is inefficient so we print a warning message;
773 * the calling code probably needs to be fixed so that it can
774 * use the more efficient tabular format.
776 * FIXME: If the first row is missing some entries that the
777 * second or later row has, then we'll drop out of tabular
778 * format without an error message. */
779 bugreport_request("In file %s, there is no entry in the registry for\n"
780 "%s.%s (or the entries are out of order). This means\n"
781 "a less efficient non-tabular format will be used.\n"
782 "To avoid this make sure all rows of a table are\n"
783 "filled out with an entry for every column.",
784 real_filename
, section_name(psection
), expect
);
785 fz_fprintf(fs
, "\n");
787 fz_fprintf(fs
, "}\n");
794 entry_to_file(pentry
, fs
);
796 ent_iter
= entry_list_link_next(ent_iter
);
797 col_iter
= entry_list_link_next(col_iter
);
801 fz_fprintf(fs
, "\n");
804 col_iter
= save_iter
;
816 col_entry_name
= entry_name(pentry
);
817 fz_fprintf(fs
, "%s=", col_entry_name
);
818 entry_to_file(pentry
, fs
);
820 /* Check for vector. */
822 col_iter
= entry_list_link_next(ent_iter
);
823 col_pentry
= entry_list_link_data(col_iter
);
824 if (NULL
== col_pentry
) {
827 fc_snprintf(pentry_name
, sizeof(pentry_name
),
828 "%s,%d", col_entry_name
, i
);
829 if (0 != strcmp(pentry_name
, entry_name(col_pentry
))) {
833 entry_to_file(col_pentry
, fs
);
837 comment
= entry_comment(pentry
);
839 fz_fprintf(fs
, "#%s\n", comment
);
841 fz_fprintf(fs
, "\n");
845 } section_list_iterate_end
;
847 if (0 != fz_ferror(fs
)) {
848 SECFILE_LOG(secfile
, NULL
, "Error before closing %s: %s",
849 real_filename
, fz_strerror(fs
));
853 if (0 != fz_fclose(fs
)) {
854 SECFILE_LOG(secfile
, NULL
, "Error closing %s", real_filename
);
861 /**************************************************************************
862 Print log messages for any entries in the file which have
863 not been looked up -- ie, unused or unrecognised entries.
864 To mark an entry as used without actually doing anything with it,
865 you could do something like:
866 section_file_lookup(&file, "foo.bar"); / * unused * /
867 **************************************************************************/
868 void secfile_check_unused(const struct section_file
*secfile
)
872 section_list_iterate(secfile_sections(secfile
), psection
) {
873 entry_list_iterate(section_entries(psection
), pentry
) {
874 if (!entry_used(pentry
)) {
875 if (!any
&& secfile
->name
) {
876 log_verbose("Unused entries in file %s:", secfile
->name
);
879 if (are_deprecation_warnings_enabled()) {
880 log_deprecation_always("%s: unused entry: %s.%s",
881 secfile
->name
!= NULL
? secfile
->name
: "nameless",
882 section_name(psection
), entry_name(pentry
));
884 #ifdef FREECIV_TESTMATIC
885 log_testmatic("%s: unused entry: %s.%s",
886 secfile
->name
!= NULL
? secfile
->name
: "nameless",
887 section_name(psection
), entry_name(pentry
));
888 #else /* FREECIV_TESTMATIC */
889 log_verbose(" unused entry: %s.%s",
890 section_name(psection
), entry_name(pentry
));
891 #endif /* FREECIV_TESTMATIC */
894 } entry_list_iterate_end
;
895 } section_list_iterate_end
;
898 /**************************************************************************
899 Return the filename the section file was loaded as, or "(anonymous)"
900 if this sectionfile was created rather than loaded from file.
901 The memory is managed internally, and should not be altered,
902 nor used after secfile_destroy() called for the section file.
903 **************************************************************************/
904 const char *secfile_name(const struct section_file
*secfile
)
906 if (NULL
== secfile
) {
908 } else if (secfile
->name
) {
909 return secfile
->name
;
911 return "(anonymous)";
915 /**************************************************************************
916 Seperates the section and entry names. Create the section if missing.
917 **************************************************************************/
918 static struct section
*secfile_insert_base(struct section_file
*secfile
,
920 const char **pent_name
)
922 char fullpath
[MAX_LEN_SECPATH
];
924 struct section
*psection
;
926 sz_strlcpy(fullpath
, path
);
928 ent_name
= strchr(fullpath
, '.');
930 SECFILE_LOG(secfile
, NULL
,
931 "Section and entry names must be separated by a dot.");
935 /* Separates section and entry names. */
937 *pent_name
= path
+ (ent_name
- fullpath
) + 1;
938 psection
= secfile_section_by_name(secfile
, fullpath
);
942 return secfile_section_new(secfile
, fullpath
);
946 /**************************************************************************
947 Insert a boolean entry.
948 **************************************************************************/
949 struct entry
*secfile_insert_bool_full(struct section_file
*secfile
,
950 bool value
, const char *comment
,
952 const char *path
, ...)
954 char fullpath
[MAX_LEN_SECPATH
];
955 const char *ent_name
;
956 struct section
*psection
;
957 struct entry
*pentry
= NULL
;
960 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
962 va_start(args
, path
);
963 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
966 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
972 pentry
= section_entry_by_name(psection
, ent_name
);
973 if (NULL
!= pentry
) {
974 if (ENTRY_BOOL
== entry_type(pentry
)) {
975 if (!entry_bool_set(pentry
, value
)) {
979 entry_destroy(pentry
);
985 if (NULL
== pentry
) {
986 pentry
= section_entry_bool_new(psection
, ent_name
, value
);
989 if (NULL
!= pentry
&& NULL
!= comment
) {
990 entry_set_comment(pentry
, comment
);
996 /**************************************************************************
997 Insert 'dim' boolean entries at 'path,0', 'path,1' etc. Returns
998 the number of entries inserted or replaced.
999 **************************************************************************/
1000 size_t secfile_insert_bool_vec_full(struct section_file
*secfile
,
1001 const bool *values
, size_t dim
,
1002 const char *comment
, bool allow_replace
,
1003 const char *path
, ...)
1005 char fullpath
[MAX_LEN_SECPATH
];
1009 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1011 va_start(args
, path
);
1012 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1015 /* NB: 'path,0' is actually 'path'. See comment in the head
1018 && NULL
!= secfile_insert_bool_full(secfile
, values
[0], comment
,
1019 allow_replace
, "%s", fullpath
)) {
1022 for (i
= 1; i
< dim
; i
++) {
1023 if (NULL
!= secfile_insert_bool_full(secfile
, values
[i
], comment
,
1024 allow_replace
, "%s,%d",
1025 fullpath
, (int) i
)) {
1033 /**************************************************************************
1034 Insert a integer entry.
1035 **************************************************************************/
1036 struct entry
*secfile_insert_int_full(struct section_file
*secfile
,
1037 int value
, const char *comment
,
1039 const char *path
, ...)
1041 char fullpath
[MAX_LEN_SECPATH
];
1042 const char *ent_name
;
1043 struct section
*psection
;
1044 struct entry
*pentry
= NULL
;
1047 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1049 va_start(args
, path
);
1050 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1053 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1058 if (allow_replace
) {
1059 pentry
= section_entry_by_name(psection
, ent_name
);
1060 if (NULL
!= pentry
) {
1061 if (ENTRY_INT
== entry_type(pentry
)) {
1062 if (!entry_int_set(pentry
, value
)) {
1066 entry_destroy(pentry
);
1072 if (NULL
== pentry
) {
1073 pentry
= section_entry_int_new(psection
, ent_name
, value
);
1076 if (NULL
!= pentry
&& NULL
!= comment
) {
1077 entry_set_comment(pentry
, comment
);
1083 /**************************************************************************
1084 Insert 'dim' integer entries at 'path,0', 'path,1' etc. Returns
1085 the number of entries inserted or replaced.
1086 **************************************************************************/
1087 size_t secfile_insert_int_vec_full(struct section_file
*secfile
,
1088 const int *values
, size_t dim
,
1089 const char *comment
, bool allow_replace
,
1090 const char *path
, ...)
1092 char fullpath
[MAX_LEN_SECPATH
];
1096 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1098 va_start(args
, path
);
1099 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1102 /* NB: 'path,0' is actually 'path'. See comment in the head
1105 && NULL
!= secfile_insert_int_full(secfile
, values
[0], comment
,
1106 allow_replace
, "%s", fullpath
)) {
1109 for (i
= 1; i
< dim
; i
++) {
1110 if (NULL
!= secfile_insert_int_full(secfile
, values
[i
], comment
,
1111 allow_replace
, "%s,%d",
1112 fullpath
, (int) i
)) {
1120 /**************************************************************************
1121 Insert a floating entry.
1122 **************************************************************************/
1123 struct entry
*secfile_insert_float_full(struct section_file
*secfile
,
1124 float value
, const char *comment
,
1126 const char *path
, ...)
1128 char fullpath
[MAX_LEN_SECPATH
];
1129 const char *ent_name
;
1130 struct section
*psection
;
1131 struct entry
*pentry
= NULL
;
1134 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1136 va_start(args
, path
);
1137 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1140 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1145 if (allow_replace
) {
1146 pentry
= section_entry_by_name(psection
, ent_name
);
1147 if (NULL
!= pentry
) {
1148 if (ENTRY_FLOAT
== entry_type(pentry
)) {
1149 if (!entry_float_set(pentry
, value
)) {
1153 entry_destroy(pentry
);
1159 if (NULL
== pentry
) {
1160 pentry
= section_entry_float_new(psection
, ent_name
, value
);
1163 if (NULL
!= pentry
&& NULL
!= comment
) {
1164 entry_set_comment(pentry
, comment
);
1170 /**************************************************************************
1171 Insert a include entry.
1172 **************************************************************************/
1173 struct section
*secfile_insert_include(struct section_file
*secfile
,
1174 const char *filename
)
1176 struct section
*psection
;
1179 fc_snprintf(buffer
, sizeof(buffer
), "include_%u", secfile
->num_includes
++);
1181 fc_assert_ret_val(secfile_section_by_name(secfile
, buffer
) == NULL
, NULL
);
1183 /* Create include section. */
1184 psection
= secfile_section_new(secfile
, buffer
);
1185 psection
->special
= EST_INCLUDE
;
1187 /* Then add string entry "file" to it. */
1188 secfile_insert_str_full(secfile
, filename
, NULL
, FALSE
, FALSE
,
1189 EST_INCLUDE
, "%s.file", buffer
);
1194 /**************************************************************************
1195 Insert a long comment entry.
1196 **************************************************************************/
1197 struct section
*secfile_insert_long_comment(struct section_file
*secfile
,
1198 const char *comment
)
1200 struct section
*psection
;
1203 fc_snprintf(buffer
, sizeof(buffer
), "long_comment_%u", secfile
->num_long_comments
++);
1205 fc_assert_ret_val(secfile_section_by_name(secfile
, buffer
) == NULL
, NULL
);
1207 /* Create long comment section. */
1208 psection
= secfile_section_new(secfile
, buffer
);
1209 psection
->special
= EST_COMMENT
;
1211 /* Then add string entry "comment" to it. */
1212 secfile_insert_str_full(secfile
, comment
, NULL
, FALSE
, TRUE
,
1213 EST_COMMENT
, "%s.comment", buffer
);
1218 /**************************************************************************
1219 Insert a string entry.
1220 **************************************************************************/
1221 struct entry
*secfile_insert_str_full(struct section_file
*secfile
,
1223 const char *comment
,
1226 enum entry_special_type stype
,
1227 const char *path
, ...)
1229 char fullpath
[MAX_LEN_SECPATH
];
1230 const char *ent_name
;
1231 struct section
*psection
;
1232 struct entry
*pentry
= NULL
;
1235 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1237 va_start(args
, path
);
1238 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1241 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1246 if (psection
->special
!= stype
) {
1247 log_error("Tried to insert wrong type of entry to section");
1251 if (allow_replace
) {
1252 pentry
= section_entry_by_name(psection
, ent_name
);
1253 if (NULL
!= pentry
) {
1254 if (ENTRY_STR
== entry_type(pentry
)) {
1255 if (!entry_str_set(pentry
, str
)) {
1259 entry_destroy(pentry
);
1265 if (NULL
== pentry
) {
1266 pentry
= section_entry_str_new(psection
, ent_name
, str
, !no_escape
);
1269 if (NULL
!= pentry
&& NULL
!= comment
) {
1270 entry_set_comment(pentry
, comment
);
1273 if (stype
== EST_COMMENT
) {
1274 pentry
->string
.raw
= TRUE
;
1280 /**************************************************************************
1281 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1282 the number of entries inserted or replaced.
1283 **************************************************************************/
1284 size_t secfile_insert_str_vec_full(struct section_file
*secfile
,
1285 const char *const *strings
, size_t dim
,
1286 const char *comment
, bool allow_replace
,
1287 bool no_escape
, const char *path
, ...)
1289 char fullpath
[MAX_LEN_SECPATH
];
1293 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1295 va_start(args
, path
);
1296 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1299 /* NB: 'path,0' is actually 'path'. See comment in the head
1302 && NULL
!= secfile_insert_str_full(secfile
, strings
[0], comment
,
1303 allow_replace
, no_escape
, FALSE
,
1307 for (i
= 1; i
< dim
; i
++) {
1308 if (NULL
!= secfile_insert_str_full(secfile
, strings
[i
], comment
,
1309 allow_replace
, no_escape
, FALSE
,
1310 "%s,%d", fullpath
, (int) i
)) {
1318 /****************************************************************************
1319 Insert a read-from-a-file string entry
1320 ****************************************************************************/
1321 struct entry
*secfile_insert_filereference(struct section_file
*secfile
,
1322 char *filename
, char *path
, ...)
1324 char fullpath
[MAX_LEN_SECPATH
];
1325 const char *ent_name
;
1326 struct section
*psection
;
1327 struct entry
*pentry
= NULL
;
1330 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1332 va_start(args
, path
);
1333 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1336 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1341 if (psection
->special
!= EST_NORMAL
) {
1342 log_error("Tried to insert normal entry to different kind of section");
1346 if (NULL
== pentry
) {
1347 pentry
= section_entry_filereference_new(psection
, ent_name
, filename
);
1353 /****************************************************************************
1354 Insert a enumerator entry.
1355 ****************************************************************************/
1356 struct entry
*secfile_insert_plain_enum_full(struct section_file
*secfile
,
1358 secfile_enum_name_fn_t name_fn
,
1359 const char *comment
,
1361 const char *path
, ...)
1363 char fullpath
[MAX_LEN_SECPATH
];
1365 const char *ent_name
;
1366 struct section
*psection
;
1367 struct entry
*pentry
= NULL
;
1370 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1371 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1372 str
= name_fn(enumerator
);
1373 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= str
, NULL
);
1375 va_start(args
, path
);
1376 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1379 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1384 if (allow_replace
) {
1385 pentry
= section_entry_by_name(psection
, ent_name
);
1386 if (NULL
!= pentry
) {
1387 if (ENTRY_STR
== entry_type(pentry
)) {
1388 if (!entry_str_set(pentry
, str
)) {
1392 entry_destroy(pentry
);
1398 if (NULL
== pentry
) {
1399 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1402 if (NULL
!= pentry
&& NULL
!= comment
) {
1403 entry_set_comment(pentry
, comment
);
1409 /****************************************************************************
1410 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1411 the number of entries inserted or replaced.
1412 ****************************************************************************/
1413 size_t secfile_insert_plain_enum_vec_full(struct section_file
*secfile
,
1414 const int *enumurators
, size_t dim
,
1415 secfile_enum_name_fn_t name_fn
,
1416 const char *comment
,
1418 const char *path
, ...)
1420 char fullpath
[MAX_LEN_SECPATH
];
1424 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1425 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1427 va_start(args
, path
);
1428 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1431 /* NB: 'path,0' is actually 'path'. See comment in the head
1434 && NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[0],
1436 allow_replace
, "%s",
1440 for (i
= 1; i
< dim
; i
++) {
1441 if (NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[i
],
1443 allow_replace
, "%s,%d",
1444 fullpath
, (int) i
)) {
1452 /****************************************************************************
1453 Insert a bitwise value entry.
1454 ****************************************************************************/
1455 struct entry
*secfile_insert_bitwise_enum_full(struct section_file
*secfile
,
1457 secfile_enum_name_fn_t
1459 secfile_enum_iter_fn_t
1461 secfile_enum_iter_fn_t
1463 secfile_enum_next_fn_t
1465 const char *comment
,
1467 const char *path
, ...)
1469 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1470 const char *ent_name
;
1471 struct section
*psection
;
1472 struct entry
*pentry
= NULL
;
1476 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1477 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1478 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, NULL
);
1479 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, NULL
);
1480 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, NULL
);
1482 /* Compute a string containing all the values separated by '|'. */
1483 str
[0] = '\0'; /* Insert at least an empty string. */
1484 if (0 != bitwise_val
) {
1485 for (i
= begin_fn(); i
!= end_fn(); i
= next_fn(i
)) {
1486 if (i
& bitwise_val
) {
1487 if ('\0' == str
[0]) {
1488 sz_strlcpy(str
, name_fn(i
));
1490 cat_snprintf(str
, sizeof(str
), "|%s", name_fn(i
));
1496 va_start(args
, path
);
1497 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1500 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1505 if (allow_replace
) {
1506 pentry
= section_entry_by_name(psection
, ent_name
);
1507 if (NULL
!= pentry
) {
1508 if (ENTRY_STR
== entry_type(pentry
)) {
1509 if (!entry_str_set(pentry
, str
)) {
1513 entry_destroy(pentry
);
1519 if (NULL
== pentry
) {
1520 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1523 if (NULL
!= pentry
&& NULL
!= comment
) {
1524 entry_set_comment(pentry
, comment
);
1530 /****************************************************************************
1531 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1532 the number of entries inserted or replaced.
1533 ****************************************************************************/
1534 size_t secfile_insert_bitwise_enum_vec_full(struct section_file
*secfile
,
1535 const int *bitwise_vals
,
1537 secfile_enum_name_fn_t name_fn
,
1538 secfile_enum_iter_fn_t begin_fn
,
1539 secfile_enum_iter_fn_t end_fn
,
1540 secfile_enum_next_fn_t next_fn
,
1541 const char *comment
,
1543 const char *path
, ...)
1545 char fullpath
[MAX_LEN_SECPATH
];
1549 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1550 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1551 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, 0);
1552 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, 0);
1553 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, 0);
1555 va_start(args
, path
);
1556 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1559 /* NB: 'path,0' is actually 'path'. See comment in the head
1562 && NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[0],
1563 name_fn
, begin_fn
, end_fn
,
1565 allow_replace
, "%s",
1569 for (i
= 1; i
< dim
; i
++) {
1570 if (NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[i
],
1571 name_fn
, begin_fn
, end_fn
,
1573 allow_replace
, "%s,%d",
1574 fullpath
, (int) i
)) {
1582 /****************************************************************************
1583 Insert an enumerator value entry that we only have a name accessor
1585 ****************************************************************************/
1586 struct entry
*secfile_insert_enum_data_full(struct section_file
*secfile
,
1587 int value
, bool bitwise
,
1588 secfile_enum_name_data_fn_t name_fn
,
1589 secfile_data_t data
,
1590 const char *comment
,
1592 const char *path
, ...)
1594 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1595 const char *ent_name
, *val_name
;
1596 struct section
*psection
;
1597 struct entry
*pentry
= NULL
;
1601 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1602 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1605 /* Compute a string containing all the values separated by '|'. */
1606 str
[0] = '\0'; /* Insert at least an empty string. */
1608 for (i
= 0; (val_name
= name_fn(data
, i
)); i
++) {
1609 if ((1 << i
) & value
) {
1610 if ('\0' == str
[0]) {
1611 sz_strlcpy(str
, val_name
);
1613 cat_snprintf(str
, sizeof(str
), "|%s", val_name
);
1619 if (!(val_name
= name_fn(data
, value
))) {
1620 SECFILE_LOG(secfile
, NULL
, "Value %d not supported.", value
);
1623 sz_strlcpy(str
, val_name
);
1626 va_start(args
, path
);
1627 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1630 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1635 if (allow_replace
) {
1636 pentry
= section_entry_by_name(psection
, ent_name
);
1637 if (NULL
!= pentry
) {
1638 if (ENTRY_STR
== entry_type(pentry
)) {
1639 if (!entry_str_set(pentry
, str
)) {
1643 entry_destroy(pentry
);
1649 if (NULL
== pentry
) {
1650 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1653 if (NULL
!= pentry
&& NULL
!= comment
) {
1654 entry_set_comment(pentry
, comment
);
1660 /****************************************************************************
1661 Insert 'dim' entries at 'path,0', 'path,1' etc. Returns the number of
1662 entries inserted or replaced.
1663 ****************************************************************************/
1664 size_t secfile_insert_enum_vec_data_full(struct section_file
*secfile
,
1665 const int *values
, size_t dim
,
1667 secfile_enum_name_data_fn_t name_fn
,
1668 secfile_data_t data
,
1669 const char *comment
,
1671 const char *path
, ...)
1673 char fullpath
[MAX_LEN_SECPATH
];
1677 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1678 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1680 va_start(args
, path
);
1681 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1684 /* NB: 'path,0' is actually 'path'. See comment in the head
1687 && NULL
!= secfile_insert_enum_data_full(secfile
, values
[0], bitwise
,
1688 name_fn
, data
, comment
,
1689 allow_replace
, "%s",
1693 for (i
= 1; i
< dim
; i
++) {
1694 if (NULL
!= secfile_insert_enum_data_full(secfile
, values
[i
], bitwise
,
1695 name_fn
, data
, comment
,
1696 allow_replace
, "%s,%d",
1697 fullpath
, (int) i
)) {
1705 /****************************************************************************
1706 Returns the entry by the name or NULL if not matched.
1707 ****************************************************************************/
1708 struct entry
*secfile_entry_by_path(const struct section_file
*secfile
,
1711 char fullpath
[MAX_LEN_SECPATH
];
1714 struct section
*psection
;
1716 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1718 sz_strlcpy(fullpath
, path
);
1720 /* treat "sec.foo,0" as "sec.foo": */
1721 len
= strlen(fullpath
);
1722 if (len
> 2 && fullpath
[len
- 2] == ',' && fullpath
[len
- 1] == '0') {
1723 fullpath
[len
- 2] = '\0';
1726 if (NULL
!= secfile
->hash
.entries
) {
1727 struct entry
*pentry
;
1729 if (entry_hash_lookup(secfile
->hash
.entries
, fullpath
, &pentry
)) {
1735 /* I dont like strtok.
1737 ent_name
= strchr(fullpath
, '.');
1742 /* Separates section and entry names. */
1744 psection
= secfile_section_by_name(secfile
, fullpath
);
1746 return section_entry_by_name(psection
, ent_name
);
1752 /**************************************************************************
1754 **************************************************************************/
1755 bool secfile_entry_delete(struct section_file
*secfile
,
1756 const char *path
, ...)
1758 char fullpath
[MAX_LEN_SECPATH
];
1760 struct entry
*pentry
;
1762 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1764 va_start(args
, path
);
1765 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1768 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1769 SECFILE_LOG(secfile
, NULL
, "Path %s does not exists.", fullpath
);
1773 entry_destroy(pentry
);
1778 /**************************************************************************
1779 Returns the entry at "fullpath" or NULL if not matched.
1780 **************************************************************************/
1781 struct entry
*secfile_entry_lookup(const struct section_file
*secfile
,
1782 const char *path
, ...)
1784 char fullpath
[MAX_LEN_SECPATH
];
1787 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1789 va_start(args
, path
);
1790 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1793 return secfile_entry_by_path(secfile
, fullpath
);
1796 /**************************************************************************
1797 Lookup a boolean value in the secfile. Returns TRUE on success.
1798 **************************************************************************/
1799 bool secfile_lookup_bool(const struct section_file
*secfile
, bool *bval
,
1800 const char *path
, ...)
1802 char fullpath
[MAX_LEN_SECPATH
];
1803 const struct entry
*pentry
;
1806 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1808 va_start(args
, path
);
1809 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1812 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1813 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1817 return entry_bool_get(pentry
, bval
);
1820 /**************************************************************************
1821 Lookup a boolean value in the secfile. On failure, use the default
1823 **************************************************************************/
1824 bool secfile_lookup_bool_default(const struct section_file
*secfile
,
1825 bool def
, const char *path
, ...)
1827 char fullpath
[MAX_LEN_SECPATH
];
1828 const struct entry
*pentry
;
1832 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1834 va_start(args
, path
);
1835 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1838 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1842 if (entry_bool_get(pentry
, &bval
)) {
1849 /**************************************************************************
1850 Lookup a boolean vector in the secfile. Returns NULL on error. This
1851 vector is not owned by the registry module, and should be free by the
1853 **************************************************************************/
1854 bool *secfile_lookup_bool_vec(const struct section_file
*secfile
,
1855 size_t *dim
, const char *path
, ...)
1857 char fullpath
[MAX_LEN_SECPATH
];
1862 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1863 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
1865 va_start(args
, path
);
1866 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1870 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
1876 /* Doesn't exist. */
1877 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1881 vec
= fc_malloc(i
* sizeof(bool));
1882 for (i
= 0; i
< *dim
; i
++) {
1883 if (!secfile_lookup_bool(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
1884 SECFILE_LOG(secfile
, NULL
,
1885 "An error occurred when looking up to \"%s,%d\" entry.",
1896 /**************************************************************************
1897 Lookup a integer value in the secfile. Returns TRUE on success.
1898 **************************************************************************/
1899 bool secfile_lookup_int(const struct section_file
*secfile
, int *ival
,
1900 const char *path
, ...)
1902 char fullpath
[MAX_LEN_SECPATH
];
1903 const struct entry
*pentry
;
1906 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1908 va_start(args
, path
);
1909 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1912 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1913 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1917 return entry_int_get(pentry
, ival
);
1920 /**************************************************************************
1921 Lookup a integer value in the secfile. On failure, use the default
1923 **************************************************************************/
1924 int secfile_lookup_int_default(const struct section_file
*secfile
, int def
,
1925 const char *path
, ...)
1927 char fullpath
[MAX_LEN_SECPATH
];
1928 const struct entry
*pentry
;
1932 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1934 va_start(args
, path
);
1935 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1938 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1942 if (entry_int_get(pentry
, &ival
)) {
1949 /**************************************************************************
1950 Lookup a integer value in the secfile. The value will be arranged to
1951 match the interval [minval, maxval]. On failure, use the default
1953 **************************************************************************/
1954 int secfile_lookup_int_def_min_max(const struct section_file
*secfile
,
1955 int defval
, int minval
, int maxval
,
1956 const char *path
, ...)
1958 char fullpath
[MAX_LEN_SECPATH
];
1959 const struct entry
*pentry
;
1963 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
1965 va_start(args
, path
);
1966 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1969 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1973 if (!entry_int_get(pentry
, &value
)) {
1977 if (value
< minval
) {
1978 SECFILE_LOG(secfile
, entry_section(pentry
),
1979 "\"%s\" should be in the interval [%d, %d] but is %d;"
1980 "using the minimal value.",
1981 fullpath
, minval
, maxval
, value
);
1985 if (value
> maxval
) {
1986 SECFILE_LOG(secfile
, entry_section(pentry
),
1987 "\"%s\" should be in the interval [%d, %d] but is %d;"
1988 "using the maximal value.",
1989 fullpath
, minval
, maxval
, value
);
1996 /**************************************************************************
1997 Lookup a integer vector in the secfile. Returns NULL on error. This
1998 vector is not owned by the registry module, and should be free by the
2000 **************************************************************************/
2001 int *secfile_lookup_int_vec(const struct section_file
*secfile
,
2002 size_t *dim
, const char *path
, ...)
2004 char fullpath
[MAX_LEN_SECPATH
];
2009 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2010 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2012 va_start(args
, path
);
2013 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2017 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2023 /* Doesn't exist. */
2024 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2028 vec
= fc_malloc(i
* sizeof(int));
2029 for (i
= 0; i
< *dim
; i
++) {
2030 if (!secfile_lookup_int(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
2031 SECFILE_LOG(secfile
, NULL
,
2032 "An error occurred when looking up to \"%s,%d\" entry.",
2043 /**************************************************************************
2044 Lookup a floating point value in the secfile. Returns TRUE on success.
2045 **************************************************************************/
2046 bool secfile_lookup_float(const struct section_file
*secfile
, float *fval
,
2047 const char *path
, ...)
2049 char fullpath
[MAX_LEN_SECPATH
];
2050 const struct entry
*pentry
;
2053 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2055 va_start(args
, path
);
2056 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2059 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2060 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2064 return entry_float_get(pentry
, fval
);
2067 /**************************************************************************
2068 Lookup a floating point value in the secfile. On failure, use the default
2070 **************************************************************************/
2071 float secfile_lookup_float_default(const struct section_file
*secfile
,
2072 float def
, const char *path
, ...)
2074 char fullpath
[MAX_LEN_SECPATH
];
2075 const struct entry
*pentry
;
2079 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2081 va_start(args
, path
);
2082 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2085 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2089 if (entry_float_get(pentry
, &fval
)) {
2096 /**************************************************************************
2097 Lookup a string value in the secfile. Returns NULL on error.
2098 **************************************************************************/
2099 const char *secfile_lookup_str(const struct section_file
*secfile
,
2100 const char *path
, ...)
2102 char fullpath
[MAX_LEN_SECPATH
];
2103 const struct entry
*pentry
;
2107 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2109 va_start(args
, path
);
2110 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2113 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2114 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2118 if (entry_str_get(pentry
, &str
)) {
2125 /**************************************************************************
2126 Lookup a string value in the secfile. On failure, use the default
2128 **************************************************************************/
2129 const char *secfile_lookup_str_default(const struct section_file
*secfile
,
2131 const char *path
, ...)
2133 char fullpath
[MAX_LEN_SECPATH
];
2134 const struct entry
*pentry
;
2138 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2140 va_start(args
, path
);
2141 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2144 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2148 if (entry_str_get(pentry
, &str
)) {
2155 /**************************************************************************
2156 Lookup a string vector in the secfile. Returns NULL on error. This
2157 vector is not owned by the registry module, and should be free by the
2158 user, but the string pointers stored inside the vector shouldn't be
2160 **************************************************************************/
2161 const char **secfile_lookup_str_vec(const struct section_file
*secfile
,
2162 size_t *dim
, const char *path
, ...)
2164 char fullpath
[MAX_LEN_SECPATH
];
2169 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2170 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2172 va_start(args
, path
);
2173 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2177 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2183 /* Doesn't exist. */
2184 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2188 vec
= fc_malloc(i
* sizeof(const char *));
2189 for (i
= 0; i
< *dim
; i
++) {
2190 if (!(vec
[i
] = secfile_lookup_str(secfile
, "%s,%d",
2191 fullpath
, (int) i
))) {
2192 SECFILE_LOG(secfile
, NULL
,
2193 "An error occurred when looking up to \"%s,%d\" entry.",
2204 /****************************************************************************
2205 Lookup an enumerator value in the secfile. Returns FALSE on error.
2206 ****************************************************************************/
2207 bool secfile_lookup_plain_enum_full(const struct section_file
*secfile
,
2209 secfile_enum_is_valid_fn_t is_valid_fn
,
2210 secfile_enum_by_name_fn_t by_name_fn
,
2211 const char *path
, ...)
2213 char fullpath
[MAX_LEN_SECPATH
];
2214 const struct entry
*pentry
;
2218 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2219 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2220 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2221 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2223 va_start(args
, path
);
2224 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2227 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2228 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2232 if (!entry_str_get(pentry
, &str
)) {
2236 *penumerator
= by_name_fn(str
, strcmp
);
2237 if (is_valid_fn(*penumerator
)) {
2241 SECFILE_LOG(secfile
, entry_section(pentry
),
2242 "Entry \"%s\": no match for \"%s\".",
2243 entry_name(pentry
), str
);
2247 /****************************************************************************
2248 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2249 ****************************************************************************/
2250 int secfile_lookup_plain_enum_default_full(const struct section_file
2251 *secfile
, int defval
,
2252 secfile_enum_is_valid_fn_t
2254 secfile_enum_by_name_fn_t
2256 const char *path
, ...)
2258 char fullpath
[MAX_LEN_SECPATH
];
2259 const struct entry
*pentry
;
2264 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2265 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2266 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2268 va_start(args
, path
);
2269 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2272 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2276 if (!entry_str_get(pentry
, &str
)) {
2280 val
= by_name_fn(str
, strcmp
);
2281 if (is_valid_fn(val
)) {
2288 /**************************************************************************
2289 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2290 vector is not owned by the registry module, and should be free by the
2292 **************************************************************************/
2293 int *secfile_lookup_plain_enum_vec_full(const struct section_file
*secfile
,
2295 secfile_enum_is_valid_fn_t
2297 secfile_enum_by_name_fn_t
2299 const char *path
, ...)
2301 char fullpath
[MAX_LEN_SECPATH
];
2306 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2307 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2308 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2309 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2311 va_start(args
, path
);
2312 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2316 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2322 /* Doesn't exist. */
2323 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2327 vec
= fc_malloc(i
* sizeof(int));
2328 for (i
= 0; i
< *dim
; i
++) {
2329 if (!secfile_lookup_plain_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2330 by_name_fn
, "%s,%d",
2331 fullpath
, (int) i
)) {
2332 SECFILE_LOG(secfile
, NULL
,
2333 "An error occurred when looking up to \"%s,%d\" entry.",
2344 /****************************************************************************
2345 Lookup a bitwise enumerator value in the secfile. Returns FALSE on error.
2346 ****************************************************************************/
2347 bool secfile_lookup_bitwise_enum_full(const struct section_file
*secfile
,
2349 secfile_enum_is_valid_fn_t is_valid_fn
,
2350 secfile_enum_by_name_fn_t by_name_fn
,
2351 const char *path
, ...)
2353 char fullpath
[MAX_LEN_SECPATH
];
2354 const struct entry
*pentry
;
2355 const char *str
, *p
;
2356 char val_name
[MAX_LEN_SECPATH
];
2360 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2361 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2362 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2363 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2365 va_start(args
, path
);
2366 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2369 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2370 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2374 if (!entry_str_get(pentry
, &str
)) {
2379 if ('\0' == str
[0]) {
2380 /* Empty string = no value. */
2384 /* Value names are separated by '|'. */
2386 p
= strchr(str
, '|');
2389 fc_strlcpy(val_name
, str
, p
- str
);
2391 /* Last segment, full copy. */
2392 sz_strlcpy(val_name
, str
);
2394 remove_leading_trailing_spaces(val_name
);
2395 val
= by_name_fn(val_name
, strcmp
);
2396 if (!is_valid_fn(val
)) {
2397 SECFILE_LOG(secfile
, entry_section(pentry
),
2398 "Entry \"%s\": no match for \"%s\".",
2399 entry_name(pentry
), val_name
);
2402 *penumerator
|= val
;
2404 } while (NULL
!= p
);
2409 /****************************************************************************
2410 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2411 ****************************************************************************/
2412 int secfile_lookup_bitwise_enum_default_full(const struct section_file
2413 *secfile
, int defval
,
2414 secfile_enum_is_valid_fn_t
2416 secfile_enum_by_name_fn_t
2418 const char *path
, ...)
2420 char fullpath
[MAX_LEN_SECPATH
];
2421 const struct entry
*pentry
;
2422 const char *str
, *p
;
2423 char val_name
[MAX_LEN_SECPATH
];
2427 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2428 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2429 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2431 va_start(args
, path
);
2432 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2435 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2439 if (!entry_str_get(pentry
, &str
)) {
2443 if ('\0' == str
[0]) {
2444 /* Empty string = no value. */
2448 /* Value names are separated by '|'. */
2451 p
= strchr(str
, '|');
2454 fc_strlcpy(val_name
, str
, p
- str
);
2456 /* Last segment, full copy. */
2457 sz_strlcpy(val_name
, str
);
2459 remove_leading_trailing_spaces(val_name
);
2460 val
= by_name_fn(val_name
, strcmp
);
2461 if (!is_valid_fn(val
)) {
2466 } while (NULL
!= p
);
2471 /**************************************************************************
2472 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2473 vector is not owned by the registry module, and should be free by the
2475 **************************************************************************/
2476 int *secfile_lookup_bitwise_enum_vec_full(const struct section_file
*secfile
,
2478 secfile_enum_is_valid_fn_t
2480 secfile_enum_by_name_fn_t
2482 const char *path
, ...)
2484 char fullpath
[MAX_LEN_SECPATH
];
2489 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2490 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2491 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2492 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2494 va_start(args
, path
);
2495 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2499 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2505 /* Doesn't exist. */
2506 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2510 vec
= fc_malloc(i
* sizeof(int));
2511 for (i
= 0; i
< *dim
; i
++) {
2512 if (!secfile_lookup_bitwise_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2513 by_name_fn
, "%s,%d",
2514 fullpath
, (int) i
)) {
2515 SECFILE_LOG(secfile
, NULL
,
2516 "An error occurred when looking up to \"%s,%d\" entry.",
2528 /****************************************************************************
2529 Lookup a value saved as string in the secfile. Returns FALSE on error.
2530 ****************************************************************************/
2531 bool secfile_lookup_enum_data(const struct section_file
*secfile
,
2532 int *pvalue
, bool bitwise
,
2533 secfile_enum_name_data_fn_t name_fn
,
2534 secfile_data_t data
, const char *path
, ...)
2536 char fullpath
[MAX_LEN_SECPATH
];
2537 const struct entry
*pentry
;
2538 const char *str
, *p
, *name
;
2539 char val_name
[MAX_LEN_SECPATH
];
2543 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2544 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= pvalue
, FALSE
);
2545 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, FALSE
);
2547 va_start(args
, path
);
2548 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2551 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2552 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2556 if (!entry_str_get(pentry
, &str
)) {
2562 if ('\0' == str
[0]) {
2563 /* Empty string = no value. */
2567 /* Value names are separated by '|'. */
2569 p
= strchr(str
, '|');
2572 fc_strlcpy(val_name
, str
, p
- str
);
2574 /* Last segment, full copy. */
2575 sz_strlcpy(val_name
, str
);
2577 remove_leading_trailing_spaces(val_name
);
2578 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2579 if (0 == fc_strcasecmp(name
, val_name
)) {
2584 SECFILE_LOG(secfile
, entry_section(pentry
),
2585 "Entry \"%s\": no match for \"%s\".",
2586 entry_name(pentry
), val_name
);
2589 *pvalue
|= 1 << val
;
2591 } while (NULL
!= p
);
2593 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2594 if (0 == fc_strcasecmp(name
, str
)) {
2600 SECFILE_LOG(secfile
, entry_section(pentry
),
2601 "Entry \"%s\": no match for \"%s\".",
2602 entry_name(pentry
), str
);
2610 /****************************************************************************
2611 Lookup a value saved as string in the secfile. Returns 'defval' on error.
2612 ****************************************************************************/
2613 int secfile_lookup_enum_default_data(const struct section_file
*secfile
,
2614 int defval
, bool bitwise
,
2615 secfile_enum_name_data_fn_t name_fn
,
2616 secfile_data_t data
,
2617 const char *path
, ...)
2619 char fullpath
[MAX_LEN_SECPATH
];
2620 const struct entry
*pentry
;
2621 const char *str
, *p
, *name
;
2622 char val_name
[MAX_LEN_SECPATH
];
2626 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2627 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, defval
);
2629 va_start(args
, path
);
2630 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2633 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2634 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2638 if (!entry_str_get(pentry
, &str
)) {
2644 if ('\0' == str
[0]) {
2645 /* Empty string = no value. */
2649 /* Value names are separated by '|'. */
2651 p
= strchr(str
, '|');
2654 fc_strlcpy(val_name
, str
, p
- str
);
2656 /* Last segment, full copy. */
2657 sz_strlcpy(val_name
, str
);
2659 remove_leading_trailing_spaces(val_name
);
2660 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2661 if (0 == strcmp(name
, val_name
)) {
2666 SECFILE_LOG(secfile
, entry_section(pentry
),
2667 "Entry \"%s\": no match for \"%s\".",
2668 entry_name(pentry
), val_name
);
2673 } while (NULL
!= p
);
2675 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2676 if (0 == strcmp(name
, str
)) {
2682 SECFILE_LOG(secfile
, entry_section(pentry
),
2683 "Entry \"%s\": no match for \"%s\".",
2684 entry_name(pentry
), str
);
2692 /****************************************************************************
2693 Lookup a vector in the secfile. Returns NULL on error. This vector
2694 is not owned by the registry module, and should be free by the user.
2695 ****************************************************************************/
2696 int *secfile_lookup_enum_vec_data(const struct section_file
*secfile
,
2697 size_t *dim
, bool bitwise
,
2698 secfile_enum_name_data_fn_t name_fn
,
2699 secfile_data_t data
, const char *path
, ...)
2701 char fullpath
[MAX_LEN_SECPATH
];
2706 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2707 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2708 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
2710 va_start(args
, path
);
2711 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2715 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2721 /* Doesn't exist. */
2722 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2726 vec
= fc_malloc(i
* sizeof(int));
2727 for (i
= 0; i
< *dim
; i
++) {
2728 if (!secfile_lookup_enum_data(secfile
, vec
+ i
, bitwise
, name_fn
, data
,
2729 "%s,%d", fullpath
, (int) i
)) {
2730 SECFILE_LOG(secfile
, NULL
,
2731 "An error occurred when looking up to \"%s,%d\" entry.",
2742 /****************************************************************************
2743 Returns the first section matching the name.
2744 ****************************************************************************/
2745 struct section
*secfile_section_by_name(const struct section_file
*secfile
,
2748 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2750 section_list_iterate(secfile
->sections
, psection
) {
2751 if (0 == strcmp(section_name(psection
), name
)) {
2754 } section_list_iterate_end
;
2759 /**************************************************************************
2760 Find a section by path.
2761 **************************************************************************/
2762 struct section
*secfile_section_lookup(const struct section_file
*secfile
,
2763 const char *path
, ...)
2765 char fullpath
[MAX_LEN_SECPATH
];
2768 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2770 va_start(args
, path
);
2771 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2774 return secfile_section_by_name(secfile
, fullpath
);
2777 /**************************************************************************
2778 Returns the list of sections. This list is owned by the registry module
2779 and shouldn't be modified and destroyed.
2780 **************************************************************************/
2781 const struct section_list
*
2782 secfile_sections(const struct section_file
*secfile
)
2784 return (NULL
!= secfile
? secfile
->sections
: NULL
);
2787 /**************************************************************************
2788 Returns the list of sections which match the name prefix. Returns NULL
2789 if no section was found. This list is not owned by the registry module
2790 and the user must destroy it when he finished to work with it.
2791 **************************************************************************/
2792 struct section_list
*
2793 secfile_sections_by_name_prefix(const struct section_file
*secfile
,
2796 struct section_list
*matches
= NULL
;
2799 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2800 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= prefix
, NULL
);
2802 len
= strlen(prefix
);
2807 section_list_iterate(secfile
->sections
, psection
) {
2808 if (0 == strncmp(section_name(psection
), prefix
, len
)) {
2809 if (NULL
== matches
) {
2810 matches
= section_list_new();
2812 section_list_append(matches
, psection
);
2814 } section_list_iterate_end
;
2819 /**************************************************************************
2820 Create a new section in the secfile.
2821 **************************************************************************/
2822 struct section
*secfile_section_new(struct section_file
*secfile
,
2825 struct section
*psection
;
2827 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2829 if (NULL
== name
|| '\0' == name
[0]) {
2830 SECFILE_LOG(secfile
, NULL
, "Cannot create a section without name.");
2834 if (!is_secfile_entry_name_valid(name
)) {
2835 SECFILE_LOG(secfile
, NULL
, "\"%s\" is not a valid section name.",
2840 if (NULL
!= secfile_section_by_name(secfile
, name
)) {
2841 /* We cannot duplicate sections in any case! Not even if one is
2842 * include -section and the other not. */
2843 SECFILE_LOG(secfile
, NULL
, "Section \"%s\" already exists.", name
);
2847 psection
= fc_malloc(sizeof(struct section
));
2848 psection
->special
= EST_NORMAL
;
2849 psection
->name
= fc_strdup(name
);
2850 psection
->entries
= entry_list_new_full(entry_destroy
);
2852 /* Append to secfile. */
2853 psection
->secfile
= secfile
;
2854 section_list_append(secfile
->sections
, psection
);
2856 if (NULL
!= secfile
->hash
.sections
) {
2857 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2863 /**************************************************************************
2864 Remove this section from the secfile.
2865 **************************************************************************/
2866 void section_destroy(struct section
*psection
)
2868 struct section_file
*secfile
;
2870 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2872 section_clear_all(psection
);
2874 if ((secfile
= psection
->secfile
)) {
2875 /* Detach from secfile. */
2876 if (section_list_remove(secfile
->sections
, psection
)) {
2877 /* This has called section_destroy() already then. */
2880 if (NULL
!= secfile
->hash
.sections
) {
2881 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2885 entry_list_destroy(psection
->entries
);
2886 free(psection
->name
);
2890 /**************************************************************************
2892 **************************************************************************/
2893 void section_clear_all(struct section
*psection
)
2895 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2897 /* This include the removing of the hash datas. */
2898 entry_list_clear(psection
->entries
);
2900 if (0 < entry_list_size(psection
->entries
)) {
2901 SECFILE_LOG(psection
->secfile
, psection
,
2902 "After clearing all, %d entries are still remaining.",
2903 entry_list_size(psection
->entries
));
2907 /**************************************************************************
2908 Change the section name. Returns TRUE on success.
2909 **************************************************************************/
2910 bool section_set_name(struct section
*psection
, const char *name
)
2912 struct section_file
*secfile
;
2913 struct section
*pother
;
2915 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, FALSE
);
2916 secfile
= psection
->secfile
;
2917 SECFILE_RETURN_VAL_IF_FAIL(secfile
, psection
, NULL
!= secfile
, FALSE
);
2919 if (NULL
== name
|| '\0' == name
[0]) {
2920 SECFILE_LOG(secfile
, psection
, "No new name for section \"%s\".",
2925 if (!is_secfile_entry_name_valid(name
)) {
2926 SECFILE_LOG(secfile
, psection
,
2927 "\"%s\" is not a valid section name for section \"%s\".",
2928 name
, psection
->name
);
2932 if ((pother
= secfile_section_by_name(secfile
, name
))
2933 && pother
!= psection
) {
2934 /* We cannot duplicate sections in any case! */
2935 SECFILE_LOG(secfile
, psection
, "Section \"%s\" already exists.", name
);
2939 /* Remove old references in the hash tables. */
2940 if (NULL
!= secfile
->hash
.sections
) {
2941 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2943 if (NULL
!= secfile
->hash
.entries
) {
2944 entry_list_iterate(psection
->entries
, pentry
) {
2945 secfile_hash_delete(secfile
, pentry
);
2946 } entry_list_iterate_end
;
2949 /* Really rename. */
2950 free(psection
->name
);
2951 psection
->name
= fc_strdup(name
);
2953 /* Reinsert new references into the hash tables. */
2954 if (NULL
!= secfile
->hash
.sections
) {
2955 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2957 if (NULL
!= secfile
->hash
.entries
) {
2958 entry_list_iterate(psection
->entries
, pentry
) {
2959 secfile_hash_insert(secfile
, pentry
);
2960 } entry_list_iterate_end
;
2966 /**************************************************************************
2967 Returns a list containing all the entries. This list is owned by the
2968 secfile, so don't modify or destroy it.
2969 **************************************************************************/
2970 const struct entry_list
*section_entries(const struct section
*psection
)
2972 return (NULL
!= psection
? psection
->entries
: NULL
);
2975 /**************************************************************************
2976 Returns the the first entry matching the name.
2977 **************************************************************************/
2978 struct entry
*section_entry_by_name(const struct section
*psection
,
2981 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2983 entry_list_iterate(psection
->entries
, pentry
) {
2984 if (0 == strcmp(entry_name(pentry
), name
)) {
2988 } entry_list_iterate_end
;
2993 /**************************************************************************
2994 Returns the entry matching the path.
2995 **************************************************************************/
2996 struct entry
*section_entry_lookup(const struct section
*psection
,
2997 const char *path
, ...)
2999 char fullpath
[MAX_LEN_SECPATH
];
3000 struct entry
*pentry
;
3003 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
3005 va_start(args
, path
);
3006 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
3009 if ((pentry
= section_entry_by_name(psection
, fullpath
))) {
3013 /* Try with full path. */
3014 if ((pentry
= secfile_entry_by_path(psection
->secfile
, fullpath
))
3015 && psection
== entry_section(pentry
)) {
3016 /* Unsure this is really owned by this section. */
3023 /**************************************************************************
3024 Returns a new entry.
3025 **************************************************************************/
3026 static struct entry
*entry_new(struct section
*psection
, const char *name
)
3028 struct section_file
*secfile
;
3029 struct entry
*pentry
;
3031 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
3033 secfile
= psection
->secfile
;
3034 if (NULL
== name
|| '\0' == name
[0]) {
3035 SECFILE_LOG(secfile
, psection
, "Cannot create an entry without name.");
3039 if (!is_secfile_entry_name_valid(name
)) {
3040 SECFILE_LOG(secfile
, psection
, "\"%s\" is not a valid entry name.",
3045 if (!secfile
->allow_duplicates
3046 && NULL
!= section_entry_by_name(psection
, name
)) {
3047 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3051 pentry
= fc_malloc(sizeof(struct entry
));
3052 pentry
->name
= fc_strdup(name
);
3053 pentry
->type
= -1; /* Invalid case. */
3055 pentry
->comment
= NULL
;
3057 /* Append to section. */
3058 pentry
->psection
= psection
;
3059 entry_list_append(psection
->entries
, pentry
);
3061 /* Notify secfile. */
3062 secfile
->num_entries
++;
3063 secfile_hash_insert(secfile
, pentry
);
3068 /**************************************************************************
3069 Returns a new entry of type ENTRY_INT.
3070 **************************************************************************/
3071 struct entry
*section_entry_int_new(struct section
*psection
,
3072 const char *name
, int value
)
3074 struct entry
*pentry
= entry_new(psection
, name
);
3076 if (NULL
!= pentry
) {
3077 pentry
->type
= ENTRY_INT
;
3078 pentry
->integer
.value
= value
;
3084 /**************************************************************************
3085 Returns a new entry of type ENTRY_BOOL.
3086 **************************************************************************/
3087 struct entry
*section_entry_bool_new(struct section
*psection
,
3088 const char *name
, bool value
)
3090 struct entry
*pentry
= entry_new(psection
, name
);
3092 if (NULL
!= pentry
) {
3093 pentry
->type
= ENTRY_BOOL
;
3094 pentry
->boolean
.value
= value
;
3100 /**************************************************************************
3101 Returns a new entry of type ENTRY_FLOAT.
3102 **************************************************************************/
3103 struct entry
*section_entry_float_new(struct section
*psection
,
3104 const char *name
, float value
)
3106 struct entry
*pentry
= entry_new(psection
, name
);
3108 if (NULL
!= pentry
) {
3109 pentry
->type
= ENTRY_FLOAT
;
3110 pentry
->floating
.value
= value
;
3116 /**************************************************************************
3117 Returns a new entry of type ENTRY_STR.
3118 **************************************************************************/
3119 struct entry
*section_entry_str_new(struct section
*psection
,
3120 const char *name
, const char *value
,
3123 struct entry
*pentry
= entry_new(psection
, name
);
3125 if (NULL
!= pentry
) {
3126 pentry
->type
= ENTRY_STR
;
3127 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3128 pentry
->string
.escaped
= escaped
;
3129 pentry
->string
.raw
= FALSE
;
3130 pentry
->string
.gt_marking
= FALSE
;
3136 /**************************************************************************
3137 Returns a new entry of type ENTRY_FILEREFERENCE.
3138 **************************************************************************/
3139 static struct entry
*section_entry_filereference_new(struct section
*psection
,
3140 const char *name
, const char *value
)
3142 struct entry
*pentry
= entry_new(psection
, name
);
3144 if (NULL
!= pentry
) {
3145 pentry
->type
= ENTRY_FILEREFERENCE
;
3146 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3152 /**************************************************************************
3153 Entry structure destructor.
3154 **************************************************************************/
3155 void entry_destroy(struct entry
*pentry
)
3157 struct section_file
*secfile
;
3158 struct section
*psection
;
3160 if (NULL
== pentry
) {
3164 if ((psection
= pentry
->psection
)) {
3165 /* Detach from section. */
3166 if (entry_list_remove(psection
->entries
, pentry
)) {
3167 /* This has called entry_destroy() already then. */
3170 if ((secfile
= psection
->secfile
)) {
3171 /* Detach from secfile. */
3172 secfile
->num_entries
--;
3173 secfile_hash_delete(secfile
, pentry
);
3177 /* Specific type free. */
3178 switch (pentry
->type
) {
3185 case ENTRY_FILEREFERENCE
:
3186 free(pentry
->string
.value
);
3192 if (NULL
!= pentry
->comment
) {
3193 free(pentry
->comment
);
3198 /**************************************************************************
3199 Returns the parent section of this entry.
3200 **************************************************************************/
3201 struct section
*entry_section(const struct entry
*pentry
)
3203 return (NULL
!= pentry
? pentry
->psection
: NULL
);
3206 /**************************************************************************
3207 Returns the type of this entry or -1 or error.
3208 **************************************************************************/
3209 enum entry_type
entry_type(const struct entry
*pentry
)
3211 return (NULL
!= pentry
? pentry
->type
: -1);
3214 /**************************************************************************
3215 Build the entry path. Returns like snprintf().
3216 **************************************************************************/
3217 int entry_path(const struct entry
*pentry
, char *buf
, size_t buf_len
)
3219 return fc_snprintf(buf
, buf_len
, "%s.%s",
3220 section_name(entry_section(pentry
)),
3221 entry_name(pentry
));
3224 /**************************************************************************
3225 Returns the name of this entry.
3226 **************************************************************************/
3227 const char *entry_name(const struct entry
*pentry
)
3229 return (NULL
!= pentry
? pentry
->name
: NULL
);
3232 /**************************************************************************
3233 Sets the name of the entry. Returns TRUE on success.
3234 **************************************************************************/
3235 bool entry_set_name(struct entry
*pentry
, const char *name
)
3237 struct section
*psection
;
3238 struct section_file
*secfile
;
3240 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3241 psection
= pentry
->psection
;
3242 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= psection
, FALSE
);
3243 secfile
= psection
->secfile
;
3244 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= secfile
, FALSE
);
3246 if (NULL
== name
|| '\0' == name
[0]) {
3247 SECFILE_LOG(secfile
, psection
, "No new name for entry \"%s\".",
3252 if (!is_secfile_entry_name_valid(name
)) {
3253 SECFILE_LOG(secfile
, psection
,
3254 "\"%s\" is not a valid entry name for entry \"%s\".",
3255 name
, pentry
->name
);
3259 if (!secfile
->allow_duplicates
) {
3260 struct entry
*pother
= section_entry_by_name(psection
, name
);
3262 if (NULL
!= pother
&& pother
!= pentry
) {
3263 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3268 /* Remove from hash table the old path. */
3269 secfile_hash_delete(secfile
, pentry
);
3271 /* Really rename the entry. */
3273 pentry
->name
= fc_strdup(name
);
3275 /* Insert into hash table the new path. */
3276 secfile_hash_insert(secfile
, pentry
);
3280 /**************************************************************************
3281 Returns the comment associated to this entry.
3282 **************************************************************************/
3283 const char *entry_comment(const struct entry
*pentry
)
3285 return (NULL
!= pentry
? pentry
->comment
: NULL
);
3288 /**************************************************************************
3289 Sets a comment for the entry. Pass NULL to remove the current one.
3290 **************************************************************************/
3291 void entry_set_comment(struct entry
*pentry
, const char *comment
)
3293 if (NULL
== pentry
) {
3297 if (NULL
!= pentry
->comment
) {
3298 free(pentry
->comment
);
3301 pentry
->comment
= (NULL
!= comment
? fc_strdup(comment
) : NULL
);
3304 /**************************************************************************
3305 Returns TRUE if this entry has been used.
3306 **************************************************************************/
3307 static inline bool entry_used(const struct entry
*pentry
)
3309 return (0 < pentry
->used
);
3312 /**************************************************************************
3313 Increase the used count.
3314 **************************************************************************/
3315 static inline void entry_use(struct entry
*pentry
)
3320 /**************************************************************************
3321 Gets an boolean value. Returns TRUE on success.
3322 On old saved files, 0 and 1 can also be considered as bool.
3323 **************************************************************************/
3324 bool entry_bool_get(const struct entry
*pentry
, bool *value
)
3326 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3328 if (ENTRY_INT
== pentry
->type
3329 && (pentry
->integer
.value
== 0
3330 || pentry
->integer
.value
== 1)
3331 && NULL
!= pentry
->psection
3332 && NULL
!= pentry
->psection
->secfile
3333 && pentry
->psection
->secfile
->allow_digital_boolean
) {
3334 *value
= (0 != pentry
->integer
.value
);
3338 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3339 ENTRY_BOOL
== pentry
->type
, FALSE
);
3341 if (NULL
!= value
) {
3342 *value
= pentry
->boolean
.value
;
3347 /**************************************************************************
3348 Sets an boolean value. Returns TRUE on success.
3349 **************************************************************************/
3350 bool entry_bool_set(struct entry
*pentry
, bool value
)
3352 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3353 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3354 ENTRY_BOOL
== pentry
->type
, FALSE
);
3356 pentry
->boolean
.value
= value
;
3360 /**************************************************************************
3361 Gets an floating value. Returns TRUE on success.
3362 **************************************************************************/
3363 bool entry_float_get(const struct entry
*pentry
, float *value
)
3365 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3366 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3367 ENTRY_FLOAT
== pentry
->type
, FALSE
);
3369 if (NULL
!= value
) {
3370 *value
= pentry
->floating
.value
;
3376 /**************************************************************************
3377 Sets an floating value. Returns TRUE on success.
3378 **************************************************************************/
3379 bool entry_float_set(struct entry
*pentry
, float 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_FLOAT
== pentry
->type
, FALSE
);
3385 pentry
->floating
.value
= value
;
3390 /**************************************************************************
3391 Gets an integer value. Returns TRUE on success.
3392 **************************************************************************/
3393 bool entry_int_get(const struct entry
*pentry
, int *value
)
3395 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3396 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3397 ENTRY_INT
== pentry
->type
, FALSE
);
3399 if (NULL
!= value
) {
3400 *value
= pentry
->integer
.value
;
3405 /**************************************************************************
3406 Sets an integer value. Returns TRUE on success.
3407 **************************************************************************/
3408 bool entry_int_set(struct entry
*pentry
, int value
)
3410 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3411 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3412 ENTRY_INT
== pentry
->type
, FALSE
);
3414 pentry
->integer
.value
= value
;
3418 /**************************************************************************
3419 Gets an string value. Returns TRUE on success.
3420 **************************************************************************/
3421 bool entry_str_get(const struct entry
*pentry
, const char **value
)
3423 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3424 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3425 ENTRY_STR
== pentry
->type
, FALSE
);
3427 if (NULL
!= value
) {
3428 *value
= pentry
->string
.value
;
3433 /**************************************************************************
3434 Sets an string value. Returns TRUE on success.
3435 **************************************************************************/
3436 bool entry_str_set(struct entry
*pentry
, const char *value
)
3438 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3439 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3440 ENTRY_STR
== pentry
->type
, FALSE
);
3442 free(pentry
->string
.value
);
3443 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3447 /**************************************************************************
3448 Returns if the string would be escaped.
3449 **************************************************************************/
3450 bool entry_str_escaped(const struct entry
*pentry
)
3452 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3453 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3454 ENTRY_STR
== pentry
->type
, FALSE
);
3456 return pentry
->string
.escaped
;
3459 /**************************************************************************
3460 Sets if the string would be escaped. Returns TRUE on success.
3461 **************************************************************************/
3462 bool entry_str_set_escaped(struct entry
*pentry
, bool escaped
)
3464 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3465 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3466 ENTRY_STR
== pentry
->type
, FALSE
);
3468 pentry
->string
.escaped
= escaped
;
3472 /**************************************************************************
3473 Sets if the string should get gettext marking. Returns TRUE on success.
3474 **************************************************************************/
3475 bool entry_str_set_gt_marking(struct entry
*pentry
, bool gt_marking
)
3477 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3478 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3479 ENTRY_STR
== pentry
->type
, FALSE
);
3481 pentry
->string
.gt_marking
= gt_marking
;
3486 /**************************************************************************
3487 Push an entry into a file stream.
3488 **************************************************************************/
3489 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
)
3491 static char buf
[8192];
3495 switch (pentry
->type
) {
3497 fz_fprintf(fs
, "%s", pentry
->boolean
.value
? "TRUE" : "FALSE");
3500 fz_fprintf(fs
, "%d", pentry
->integer
.value
);
3503 snprintf(buf
, sizeof(buf
), "%f", pentry
->floating
.value
);
3504 for (i
= 0; buf
[i
] != '\0' ; i
++) {
3505 if (buf
[i
] == '.') {
3511 /* There's no '.' so it would seem like a integer value when loaded.
3512 * Force it not to look like an integer by adding ".0" */
3513 fz_fprintf(fs
, "%s.0", buf
);
3515 fz_fprintf(fs
, "%s", buf
);
3519 if (pentry
->string
.escaped
) {
3520 make_escapes(pentry
->string
.value
, buf
, sizeof(buf
));
3521 if (pentry
->string
.gt_marking
) {
3522 fz_fprintf(fs
, "_(\"%s\")", buf
);
3524 fz_fprintf(fs
, "\"%s\"", buf
);
3526 } else if (pentry
->string
.raw
) {
3527 fz_fprintf(fs
, "%s", pentry
->string
.value
);
3529 fz_fprintf(fs
, "$%s$", pentry
->string
.value
);
3532 case ENTRY_FILEREFERENCE
:
3533 fz_fprintf(fs
, "*%s*", pentry
->string
.value
);
3538 /**************************************************************************
3539 Creates a new entry from the token.
3540 **************************************************************************/
3541 static void entry_from_inf_token(struct section
*psection
, const char *name
,
3542 const char *tok
, struct inputfile
*inf
)
3544 if (!entry_from_token(psection
, name
, tok
)) {
3545 log_error("%s", inf_log_str(inf
, "Entry value not recognized: %s", tok
));