1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /**************************************************************************
15 the idea with this file is to create something similar to the ms-windows
17 however the interface is nice. ie:
18 secfile_lookup_str(file, "player%d.unit%d.name", plrno, unitno);
19 ***************************************************************************/
21 /**************************************************************************
22 Description of the file format:
23 (This is based on a format by the original authors, with
24 various incremental extensions. --dwp)
26 - Whitespace lines are ignored, as are lines where the first
27 non-whitespace character is ';' (comment lines).
28 Optionally '#' can also be used for comments.
32 includes the named file at that point. (The '*' must be the
33 first character on the line.) The file is found by looking in
34 FREECIV_DATA_PATH. Non-infinite recursive includes are allowed.
36 - A line with "[name]" labels the start of a section with
37 that name; one of these must be the first non-comment line in
38 the file. Any spaces within the brackets are included in the
39 name, but this feature (?) should probably not be used...
41 - Within a section, lines have one of the following forms:
42 subname = "stringvalue"
47 for a value with given name and string, negative integer, and
48 positive integer values, respectively. These entries are
49 referenced in the following functions as "sectionname.subname".
50 The section name should not contain any dots ('.'); the subname
51 can, but they have no particular significance. There can be
52 optional whitespace before and/or after the equals sign.
53 You can put a newline after (but not before) the equals sign.
55 Backslash is an escape character in strings (double-quoted strings
56 only, not names); recognised escapes are \n, \\, and \".
57 (Any other \<char> is just treated as <char>.)
59 - Gettext markings: You can surround strings like so:
60 foo = _("stringvalue")
61 The registry just ignores these extra markings, but this is
62 useful for marking strings for translations via gettext tools.
64 - Multiline strings: Strings can have embeded newlines, eg:
69 This is equivalent to:
70 foo = _("\nThis is a string\nover multiple lines\n")
71 Note that if you missplace the trailing doublequote you can
72 easily end up with strange errors reading the file...
74 - Strings read from a file: A file can be read as a string value:
77 - Vector format: An entry can have multiple values separated
80 These are accessed by names "foo", "foo,1" and "foo,2"
81 (with section prefix as above). So the above is equivalent to:
85 As in the example, in principle you can mix integers and strings,
86 but the calling program will probably require elements to be the
87 same type. Note that the first element of a vector is not "foo,0",
88 in order that the name of the first element is the same whether or
89 not there are subsequent elements. However as a convenience, if
90 you try to lookup "foo,0" then you get back "foo". (So you should
91 never have "foo,0" as a real name in the datafile.)
93 - Tabular format: The lines:
94 foo = { "bar", "baz", "bax"
97 "hmm", 314, 99, 33, 11
99 are equivalent to the following:
110 The first line specifies the base name and the column names, and the
111 subsequent lines have data. Again it is possible to mix string and
112 integer values in a column, and have either more or less values
113 in a row than there are column headings, but the code which uses
114 this information (via the registry) may set more stringent conditions.
115 If a row has more entries than column headings, the last column is
116 treated as a vector (as above). You can optionally put a newline
117 after '=' and/or after '{'.
119 The equivalence above between the new and old formats is fairly
120 direct: internally, data is converted to the old format.
121 In principle it could be a good idea to represent the data
122 as a table (2-d array) internally, but the current method
123 seems sufficient and relatively simple...
125 There is a limited ability to save data in tabular:
126 So long as the section_file is constructed in an expected way,
127 tabular data (with no missing or extra values) can be saved
128 in tabular form. (See section_file_save().)
130 - Multiline vectors: if the last non-comment non-whitespace
131 character in a line is a comma, the line is considered to
132 continue on to the next line. Eg:
136 This is equivalent to the original "vector format" example above.
137 Such multi-lines can occur for column headings, vectors, or
138 table rows, again with some potential for strange errors...
140 ***************************************************************************/
142 /**************************************************************************
143 Hashing registry lookups: (by dwp)
144 - Have a hash table direct to entries, bypassing sections division.
145 - For convenience, store the key (the full section+entry name)
146 in the hash table (some memory overhead).
147 - The number of entries is fixed when the hash table is built.
149 **************************************************************************/
152 #include <fc_config.h>
161 #include "deprecations.h"
163 #include "inputfile.h"
167 #include "registry.h"
168 #include "section_file.h"
172 #include "registry_ini.h"
174 #define MAX_LEN_SECPATH 1024
176 /* Set to FALSE for old-style savefiles. */
177 #define SAVE_TABLES TRUE
179 #define SPECVEC_TAG astring
182 static inline bool entry_used(const struct entry
*pentry
);
183 static inline void entry_use(struct entry
*pentry
);
185 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
);
186 static void entry_from_inf_token(struct section
*psection
, const char *name
,
187 const char *tok
, struct inputfile
*file
);
189 static struct entry
*section_entry_filereference_new(struct section
*psection
,
190 const char *name
, const char *value
);
192 /***************************************************************************
193 Simplification of fileinfoname().
194 ***************************************************************************/
195 static const char *datafilename(const char *filename
)
197 return fileinfoname(get_data_dirs(), filename
);
200 /**************************************************************************
201 Ensure name is correct to use it as section or entry name.
202 **************************************************************************/
203 static bool is_secfile_entry_name_valid(const char *name
)
205 static const char *const allowed
= "_.,-[]";
207 while ('\0' != *name
) {
208 if (!fc_isalnum(*name
) && NULL
== strchr(allowed
, *name
)) {
216 /**************************************************************************
217 Insert an entry into the hash table. Returns TRUE on success.
218 **************************************************************************/
219 static bool secfile_hash_insert(struct section_file
*secfile
,
220 struct entry
*pentry
)
223 struct entry
*hentry
;
225 if (NULL
== secfile
->hash
.entries
) {
226 /* Consider as success if this secfile doesn't have built the entries
231 entry_path(pentry
, buf
, sizeof(buf
));
232 if (entry_hash_replace_full(secfile
->hash
.entries
, buf
, pentry
,
235 if (!secfile
->allow_duplicates
) {
236 SECFILE_LOG(secfile
, entry_section(hentry
),
237 "Tried to insert same value twice: %s", buf
);
245 /**************************************************************************
246 Delete an entry from the hash table. Returns TRUE on success.
247 **************************************************************************/
248 static bool secfile_hash_delete(struct section_file
*secfile
,
249 struct entry
*pentry
)
253 if (NULL
== secfile
->hash
.entries
) {
254 /* Consider as success if this secfile doesn't have built the entries
259 entry_path(pentry
, buf
, sizeof(buf
));
260 return entry_hash_remove(secfile
->hash
.entries
, buf
);
263 /**************************************************************************
264 Base function to load a section file. Note it closes the inputfile.
265 **************************************************************************/
266 static struct section_file
*secfile_from_input_file(struct inputfile
*inf
,
267 const char *filename
,
269 bool allow_duplicates
)
271 struct section_file
*secfile
;
272 struct section
*psection
= NULL
;
273 struct section
*single_section
= NULL
;
274 bool table_state
= FALSE
; /* TRUE when within tabular format. */
275 int table_lineno
= 0; /* Row number in tabular, 0 top data row. */
278 struct astring base_name
= ASTRING_INIT
; /* for table or single entry */
279 struct astring field_name
= ASTRING_INIT
;
280 struct astring_vector columns
; /* astrings for column headings */
281 bool found_my_section
= FALSE
;
288 /* Assign the real value later, to speed up the creation of new entries. */
289 secfile
= secfile_new(TRUE
);
291 secfile
->name
= fc_strdup(filename
);
293 secfile
->name
= NULL
;
296 astring_vector_init(&columns
);
299 log_verbose("Reading registry from \"%s\"", filename
);
301 log_verbose("Reading registry");
304 while (!inf_at_eof(inf
)) {
305 if (inf_token(inf
, INF_TOK_EOL
)) {
308 if (inf_at_eof(inf
)) {
309 /* may only realise at eof after trying to read eol above */
312 tok
= inf_token(inf
, INF_TOK_SECTION_NAME
);
314 if (found_my_section
) {
315 /* This shortcut will stop any further loading after the requested
316 * section has been loaded (i.e., at the start of a new section).
317 * This is needed to make the behavior useful, since the whole
318 * purpose is to short-cut further loading of the file. However
319 * normally a section may be split up, and that will no longer
320 * work here because it will be short-cut. */
321 SECFILE_LOG(secfile
, psection
, "%s",
322 inf_log_str(inf
, "Found requested section; finishing"));
326 SECFILE_LOG(secfile
, psection
, "%s",
327 inf_log_str(inf
, "New section during table"));
331 /* Check if we already have a section with this name.
332 (Could ignore this and have a duplicate sections internally,
333 but then secfile_get_secnames_prefix would return duplicates.)
334 Duplicate section in input are likely to be useful for includes.
336 psection
= secfile_section_by_name(secfile
, tok
);
338 if (!section
|| strcmp(tok
, section
) == 0) {
339 psection
= secfile_section_new(secfile
, tok
);
341 single_section
= psection
;
342 found_my_section
= TRUE
;
346 if (!inf_token(inf
, INF_TOK_EOL
)) {
347 SECFILE_LOG(secfile
, psection
, "%s",
348 inf_log_str(inf
, "Expected end of line"));
354 if (inf_token(inf
, INF_TOK_TABLE_END
)) {
356 SECFILE_LOG(secfile
, psection
, "%s",
357 inf_log_str(inf
, "Misplaced \"}\""));
361 if (!inf_token(inf
, INF_TOK_EOL
)) {
362 SECFILE_LOG(secfile
, psection
, "%s",
363 inf_log_str(inf
, "Expected end of line"));
373 int num_columns
= astring_vector_size(&columns
);
376 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
377 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
378 SECFILE_LOG(secfile
, psection
, "%s",
379 inf_log_str(inf
, "Expected value"));
384 if (i
< num_columns
) {
385 astr_set(&field_name
, "%s%d.%s", astr_str(&base_name
),
386 table_lineno
, astr_str(&columns
.p
[i
]));
388 astr_set(&field_name
, "%s%d.%s,%d", astr_str(&base_name
),
389 table_lineno
, astr_str(&columns
.p
[num_columns
- 1]),
390 (int) (i
- num_columns
+ 1));
392 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
393 } while (inf_token(inf
, INF_TOK_COMMA
));
395 if (!inf_token(inf
, INF_TOK_EOL
)) {
396 SECFILE_LOG(secfile
, psection
, "%s",
397 inf_log_str(inf
, "Expected end of line"));
405 if (!(tok
= inf_token(inf
, INF_TOK_ENTRY_NAME
))) {
406 SECFILE_LOG(secfile
, psection
, "%s",
407 inf_log_str(inf
, "Expected entry name"));
412 /* need to store tok before next calls: */
413 astr_set(&base_name
, "%s", tok
);
415 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
417 if (inf_token(inf
, INF_TOK_TABLE_START
)) {
421 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
422 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
423 SECFILE_LOG(secfile
, psection
, "%s",
424 inf_log_str(inf
, "Expected value"));
428 if (tok
[0] != '\"') {
429 SECFILE_LOG(secfile
, psection
, "%s",
430 inf_log_str(inf
, "Table column header non-string"));
434 { /* expand columns: */
436 n_prev
= astring_vector_size(&columns
);
437 for (j
= i
+ 1; j
< n_prev
; j
++) {
438 astr_free(&columns
.p
[j
]);
440 astring_vector_reserve(&columns
, i
+ 1);
441 for (j
= n_prev
; j
< i
+ 1; j
++) {
442 astr_init(&columns
.p
[j
]);
445 astr_set(&columns
.p
[i
], "%s", tok
+ 1);
447 } while (inf_token(inf
, INF_TOK_COMMA
));
449 if (!inf_token(inf
, INF_TOK_EOL
)) {
450 SECFILE_LOG(secfile
, psection
, "%s",
451 inf_log_str(inf
, "Expected end of line"));
459 /* ordinary value: */
463 inf_discard_tokens(inf
, INF_TOK_EOL
); /* allow newlines */
464 if (!(tok
= inf_token(inf
, INF_TOK_VALUE
))) {
465 SECFILE_LOG(secfile
, psection
, "%s",
466 inf_log_str(inf
, "Expected value"));
471 entry_from_inf_token(psection
, astr_str(&base_name
), tok
, inf
);
473 astr_set(&field_name
, "%s,%d", astr_str(&base_name
), i
);
474 entry_from_inf_token(psection
, astr_str(&field_name
), tok
, inf
);
476 } while (inf_token(inf
, INF_TOK_COMMA
));
477 if (!inf_token(inf
, INF_TOK_EOL
)) {
478 SECFILE_LOG(secfile
, psection
, "%s",
479 inf_log_str(inf
, "Expected end of line"));
486 SECFILE_LOG(secfile
, psection
,
487 "Finished registry before end of table");
493 astr_free(&base_name
);
494 astr_free(&field_name
);
495 for (i
= 0; i
< astring_vector_size(&columns
); i
++) {
496 astr_free(&columns
.p
[i
]);
498 astring_vector_free(&columns
);
500 if (section
!= NULL
) {
501 if (!found_my_section
) {
502 secfile_destroy(secfile
);
506 /* Build the entry hash table with single section information */
507 secfile
->allow_duplicates
= allow_duplicates
;
508 entry_list_iterate(section_entries(single_section
), pentry
) {
509 if (!secfile_hash_insert(secfile
, pentry
)) {
510 secfile_destroy(secfile
);
513 } entry_list_iterate_end
;
519 /* Build the entry hash table. */
520 secfile
->allow_duplicates
= allow_duplicates
;
521 secfile
->hash
.entries
= entry_hash_new_nentries(secfile
->num_entries
);
523 section_list_iterate(secfile
->sections
, hashing_section
) {
524 entry_list_iterate(section_entries(hashing_section
), pentry
) {
525 if (!secfile_hash_insert(secfile
, pentry
)) {
529 } entry_list_iterate_end
;
533 } section_list_iterate_end
;
536 secfile_destroy(secfile
);
543 /**************************************************************************
544 Create a section file from a file, read only one particular section.
545 Returns NULL on error.
546 **************************************************************************/
547 struct section_file
*secfile_load_section(const char *filename
,
549 bool allow_duplicates
)
551 char real_filename
[1024];
553 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
554 return secfile_from_input_file(inf_from_file(real_filename
, datafilename
),
555 filename
, section
, allow_duplicates
);
558 /**************************************************************************
559 Create a section file from a stream. Returns NULL on error.
560 **************************************************************************/
561 struct section_file
*secfile_from_stream(fz_FILE
*stream
,
562 bool allow_duplicates
)
564 return secfile_from_input_file(inf_from_stream(stream
, datafilename
),
565 NULL
, NULL
, allow_duplicates
);
568 /**************************************************************************
569 Returns TRUE iff the character is legal in a table entry name.
570 **************************************************************************/
571 static bool is_legal_table_entry_name(char c
, bool num
)
573 return (num
? fc_isalnum(c
) : fc_isalpha(c
)) || c
== '_';
576 /**************************************************************************
577 Save the previously filled in section_file to disk.
579 There is now limited ability to save in the new tabular format
580 (to give smaller savefiles).
581 The start of a table is detected by an entry with name of the form:
582 (alphabetical_component)(zero)(period)(alphanumeric_component)
583 Eg: u0.id, or c0.id, in the freeciv savefile.
584 The alphabetical component is taken as the "name" of the table,
585 and the component after the period as the first column name.
586 This should be followed by the other column values for u0,
587 and then subsequent u1, u2, etc, in strict order with no omissions,
588 and with all of the columns for all uN in the same order as for u0.
590 If compression_level is non-zero, then compress using zlib. (Should
591 only supply non-zero compression_level if already know that FREECIV_HAVE_LIBZ.)
592 Below simply specifies FZ_ZLIB method, since fz_fromFile() automatically
593 changes to FZ_PLAIN method when level == 0.
594 **************************************************************************/
595 bool secfile_save(const struct section_file
*secfile
, const char *filename
,
596 int compression_level
, enum fz_method compression_method
)
598 char real_filename
[1024];
599 char pentry_name
[128];
600 const char *col_entry_name
;
602 const struct entry_list_link
*ent_iter
, *save_iter
, *col_iter
;
603 struct entry
*pentry
, *col_pentry
;
606 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
608 if (NULL
== filename
) {
609 filename
= secfile
->name
;
612 interpret_tilde(real_filename
, sizeof(real_filename
), filename
);
613 fs
= fz_from_file(real_filename
, "w",
614 compression_method
, compression_level
);
617 SECFILE_LOG(secfile
, NULL
, _("Could not open %s for writing"), real_filename
);
622 section_list_iterate(secfile
->sections
, psection
) {
623 if (psection
->include
) {
624 for (ent_iter
= entry_list_head(section_entries(psection
));
625 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
626 ent_iter
= entry_list_link_next(ent_iter
)) {
628 fc_assert(!strcmp(entry_name(pentry
), "file"));
630 fz_fprintf(fs
, "*include ");
631 entry_to_file(pentry
, fs
);
632 fz_fprintf(fs
, "\n");
635 fz_fprintf(fs
, "\n[%s]\n", section_name(psection
));
637 /* Following doesn't use entry_list_iterate() because we want to do
638 * tricky things with the iterators...
640 for (ent_iter
= entry_list_head(section_entries(psection
));
641 ent_iter
&& (pentry
= entry_list_link_data(ent_iter
));
642 ent_iter
= entry_list_link_next(ent_iter
)) {
645 /* Tables: break out of this loop if this is a non-table
646 * entry (pentry and ent_iter unchanged) or after table (pentry
647 * and ent_iter suitably updated, pentry possibly NULL).
648 * After each table, loop again in case the next entry
652 char *c
, *first
, base
[64];
653 int offset
, irow
, icol
, ncol
;
655 /* Example: for first table name of "xyz0.blah":
656 * first points to the original string pentry->name
657 * base contains "xyz";
658 * offset = 5 (so first+offset gives "blah")
659 * note strlen(base) = offset - 2
666 sz_strlcpy(pentry_name
, entry_name(pentry
));
667 c
= first
= pentry_name
;
668 if (*c
== '\0' || !is_legal_table_entry_name(*c
, FALSE
)) {
671 for (; *c
!= '\0' && is_legal_table_entry_name(*c
, FALSE
); c
++) {
674 if (0 != strncmp(c
, "0.", 2)) {
678 if (*c
== '\0' || !is_legal_table_entry_name(*c
, TRUE
)) {
683 first
[offset
- 2] = '\0';
684 sz_strlcpy(base
, first
);
685 first
[offset
- 2] = '0';
686 fz_fprintf(fs
, "%s={", base
);
688 /* Save an iterator at this first entry, which we can later use
689 * to repeatedly iterate over column names:
691 save_iter
= ent_iter
;
693 /* write the column names, and calculate ncol: */
695 col_iter
= save_iter
;
696 for(; (col_pentry
= entry_list_link_data(col_iter
));
697 col_iter
= entry_list_link_next(col_iter
)) {
698 col_entry_name
= entry_name(col_pentry
);
699 if (strncmp(col_entry_name
, first
, offset
) != 0) {
702 fz_fprintf(fs
, "%s\"%s\"", (ncol
== 0 ? "" : ","),
703 col_entry_name
+ offset
);
706 fz_fprintf(fs
, "\n");
708 /* Iterate over rows and columns, incrementing ent_iter as we go,
709 * and writing values to the table. Have a separate iterator
710 * to the column names to check they all match.
713 col_iter
= save_iter
;
715 char expect
[128]; /* pentry->name we're expecting */
717 pentry
= entry_list_link_data(ent_iter
);
718 col_pentry
= entry_list_link_data(col_iter
);
720 fc_snprintf(expect
, sizeof(expect
), "%s%d.%s",
721 base
, irow
, entry_name(col_pentry
) + offset
);
723 /* break out of tabular if doesn't match: */
724 if ((!pentry
) || (strcmp(entry_name(pentry
), expect
) != 0)) {
726 /* If the second or later row of a table is missing some
727 * entries that the first row had, we drop out of the tabular
728 * format. This is inefficient so we print a warning message;
729 * the calling code probably needs to be fixed so that it can
730 * use the more efficient tabular format.
732 * FIXME: If the first row is missing some entries that the
733 * second or later row has, then we'll drop out of tabular
734 * format without an error message. */
735 log_error("In file %s, there is no entry in the registry for\n"
736 "%s.%s (or the entries are out of order). This means\n"
737 "a less efficient non-tabular format will be used.\n"
738 "To avoid this make sure all rows of a table are\n"
739 "filled out with an entry for every column.",
740 real_filename
, section_name(psection
), expect
);
741 /* TRANS: No full stop after the URL, could cause confusion. */
742 log_error(_("Please report this message at %s"), BUG_URL
);
743 fz_fprintf(fs
, "\n");
745 fz_fprintf(fs
, "}\n");
752 entry_to_file(pentry
, fs
);
754 ent_iter
= entry_list_link_next(ent_iter
);
755 col_iter
= entry_list_link_next(col_iter
);
759 fz_fprintf(fs
, "\n");
762 col_iter
= save_iter
;
774 col_entry_name
= entry_name(pentry
);
775 fz_fprintf(fs
, "%s=", col_entry_name
);
776 entry_to_file(pentry
, fs
);
778 /* Check for vector. */
780 col_iter
= entry_list_link_next(ent_iter
);
781 col_pentry
= entry_list_link_data(col_iter
);
782 if (NULL
== col_pentry
) {
785 fc_snprintf(pentry_name
, sizeof(pentry_name
),
786 "%s,%d", col_entry_name
, i
);
787 if (0 != strcmp(pentry_name
, entry_name(col_pentry
))) {
791 entry_to_file(col_pentry
, fs
);
795 comment
= entry_comment(pentry
);
797 fz_fprintf(fs
, "#%s\n", comment
);
799 fz_fprintf(fs
, "\n");
803 } section_list_iterate_end
;
805 if (0 != fz_ferror(fs
)) {
806 SECFILE_LOG(secfile
, NULL
, "Error before closing %s: %s",
807 real_filename
, fz_strerror(fs
));
811 if (0 != fz_fclose(fs
)) {
812 SECFILE_LOG(secfile
, NULL
, "Error closing %s", real_filename
);
819 /**************************************************************************
820 Print log messages for any entries in the file which have
821 not been looked up -- ie, unused or unrecognised entries.
822 To mark an entry as used without actually doing anything with it,
823 you could do something like:
824 section_file_lookup(&file, "foo.bar"); / * unused * /
825 **************************************************************************/
826 void secfile_check_unused(const struct section_file
*secfile
)
830 section_list_iterate(secfile_sections(secfile
), psection
) {
831 entry_list_iterate(section_entries(psection
), pentry
) {
832 if (!entry_used(pentry
)) {
833 if (!any
&& secfile
->name
) {
834 log_verbose("Unused entries in file %s:", secfile
->name
);
837 if (are_deprecation_warnings_enabled()) {
838 log_deprecation_always("%s: unused entry: %s.%s",
839 secfile
->name
!= NULL
? secfile
->name
: "nameless",
840 section_name(psection
), entry_name(pentry
));
842 #ifdef FREECIV_TESTMATIC
843 log_testmatic("%s: unused entry: %s.%s",
844 secfile
->name
!= NULL
? secfile
->name
: "nameless",
845 section_name(psection
), entry_name(pentry
));
846 #else /* FREECIV_TESTMATIC */
847 log_verbose(" unused entry: %s.%s",
848 section_name(psection
), entry_name(pentry
));
849 #endif /* FREECIV_TESTMATIC */
852 } entry_list_iterate_end
;
853 } section_list_iterate_end
;
856 /**************************************************************************
857 Return the filename the section file was loaded as, or "(anonymous)"
858 if this sectionfile was created rather than loaded from file.
859 The memory is managed internally, and should not be altered,
860 nor used after secfile_destroy() called for the section file.
861 **************************************************************************/
862 const char *secfile_name(const struct section_file
*secfile
)
864 if (NULL
== secfile
) {
866 } else if (secfile
->name
) {
867 return secfile
->name
;
869 return "(anonymous)";
873 /**************************************************************************
874 Seperates the section and entry names. Create the section if missing.
875 **************************************************************************/
876 static struct section
*secfile_insert_base(struct section_file
*secfile
,
878 const char **pent_name
)
880 char fullpath
[MAX_LEN_SECPATH
];
882 struct section
*psection
;
884 sz_strlcpy(fullpath
, path
);
886 ent_name
= strchr(fullpath
, '.');
888 SECFILE_LOG(secfile
, NULL
,
889 "Section and entry names must be separated by a dot.");
893 /* Separates section and entry names. */
895 *pent_name
= path
+ (ent_name
- fullpath
) + 1;
896 psection
= secfile_section_by_name(secfile
, fullpath
);
900 return secfile_section_new(secfile
, fullpath
);
904 /**************************************************************************
905 Insert a boolean entry.
906 **************************************************************************/
907 struct entry
*secfile_insert_bool_full(struct section_file
*secfile
,
908 bool value
, const char *comment
,
910 const char *path
, ...)
912 char fullpath
[MAX_LEN_SECPATH
];
913 const char *ent_name
;
914 struct section
*psection
;
915 struct entry
*pentry
= NULL
;
918 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
920 va_start(args
, path
);
921 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
924 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
930 pentry
= section_entry_by_name(psection
, ent_name
);
931 if (NULL
!= pentry
) {
932 if (ENTRY_BOOL
== entry_type(pentry
)) {
933 if (!entry_bool_set(pentry
, value
)) {
937 entry_destroy(pentry
);
943 if (NULL
== pentry
) {
944 pentry
= section_entry_bool_new(psection
, ent_name
, value
);
947 if (NULL
!= pentry
&& NULL
!= comment
) {
948 entry_set_comment(pentry
, comment
);
954 /**************************************************************************
955 Insert 'dim' boolean entries at 'path,0', 'path,1' etc. Returns
956 the number of entries inserted or replaced.
957 **************************************************************************/
958 size_t secfile_insert_bool_vec_full(struct section_file
*secfile
,
959 const bool *values
, size_t dim
,
960 const char *comment
, bool allow_replace
,
961 const char *path
, ...)
963 char fullpath
[MAX_LEN_SECPATH
];
967 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
969 va_start(args
, path
);
970 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
973 /* NB: 'path,0' is actually 'path'. See comment in the head
976 && NULL
!= secfile_insert_bool_full(secfile
, values
[0], comment
,
977 allow_replace
, "%s", fullpath
)) {
980 for (i
= 1; i
< dim
; i
++) {
981 if (NULL
!= secfile_insert_bool_full(secfile
, values
[i
], comment
,
982 allow_replace
, "%s,%d",
983 fullpath
, (int) i
)) {
991 /**************************************************************************
992 Insert a integer entry.
993 **************************************************************************/
994 struct entry
*secfile_insert_int_full(struct section_file
*secfile
,
995 int value
, const char *comment
,
997 const char *path
, ...)
999 char fullpath
[MAX_LEN_SECPATH
];
1000 const char *ent_name
;
1001 struct section
*psection
;
1002 struct entry
*pentry
= NULL
;
1005 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1007 va_start(args
, path
);
1008 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1011 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1016 if (allow_replace
) {
1017 pentry
= section_entry_by_name(psection
, ent_name
);
1018 if (NULL
!= pentry
) {
1019 if (ENTRY_INT
== entry_type(pentry
)) {
1020 if (!entry_int_set(pentry
, value
)) {
1024 entry_destroy(pentry
);
1030 if (NULL
== pentry
) {
1031 pentry
= section_entry_int_new(psection
, ent_name
, value
);
1034 if (NULL
!= pentry
&& NULL
!= comment
) {
1035 entry_set_comment(pentry
, comment
);
1041 /**************************************************************************
1042 Insert 'dim' integer entries at 'path,0', 'path,1' etc. Returns
1043 the number of entries inserted or replaced.
1044 **************************************************************************/
1045 size_t secfile_insert_int_vec_full(struct section_file
*secfile
,
1046 const int *values
, size_t dim
,
1047 const char *comment
, bool allow_replace
,
1048 const char *path
, ...)
1050 char fullpath
[MAX_LEN_SECPATH
];
1054 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1056 va_start(args
, path
);
1057 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1060 /* NB: 'path,0' is actually 'path'. See comment in the head
1063 && NULL
!= secfile_insert_int_full(secfile
, values
[0], comment
,
1064 allow_replace
, "%s", fullpath
)) {
1067 for (i
= 1; i
< dim
; i
++) {
1068 if (NULL
!= secfile_insert_int_full(secfile
, values
[i
], comment
,
1069 allow_replace
, "%s,%d",
1070 fullpath
, (int) i
)) {
1078 /**************************************************************************
1079 Insert a floating entry.
1080 **************************************************************************/
1081 struct entry
*secfile_insert_float_full(struct section_file
*secfile
,
1082 float value
, const char *comment
,
1084 const char *path
, ...)
1086 char fullpath
[MAX_LEN_SECPATH
];
1087 const char *ent_name
;
1088 struct section
*psection
;
1089 struct entry
*pentry
= NULL
;
1092 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1094 va_start(args
, path
);
1095 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1098 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1103 if (allow_replace
) {
1104 pentry
= section_entry_by_name(psection
, ent_name
);
1105 if (NULL
!= pentry
) {
1106 if (ENTRY_FLOAT
== entry_type(pentry
)) {
1107 if (!entry_float_set(pentry
, value
)) {
1111 entry_destroy(pentry
);
1117 if (NULL
== pentry
) {
1118 pentry
= section_entry_float_new(psection
, ent_name
, value
);
1121 if (NULL
!= pentry
&& NULL
!= comment
) {
1122 entry_set_comment(pentry
, comment
);
1128 /**************************************************************************
1129 Insert a include entry.
1130 **************************************************************************/
1131 struct section
*secfile_insert_include(struct section_file
*secfile
,
1132 const char *filename
)
1134 struct section
*psection
;
1137 fc_snprintf(buffer
, sizeof(buffer
), "include_%u", secfile
->num_includes
++);
1139 fc_assert_ret_val(secfile_section_by_name(secfile
, filename
) == NULL
, NULL
);
1141 /* Create include section. */
1142 psection
= secfile_section_new(secfile
, buffer
);
1143 psection
->include
= TRUE
;
1145 /* Then add string entry "file" to it. */
1146 secfile_insert_str_full(secfile
, filename
, NULL
, FALSE
, FALSE
, TRUE
, "%s.file", buffer
);
1151 /**************************************************************************
1152 Insert a string entry.
1153 **************************************************************************/
1154 struct entry
*secfile_insert_str_full(struct section_file
*secfile
,
1156 const char *comment
,
1160 const char *path
, ...)
1162 char fullpath
[MAX_LEN_SECPATH
];
1163 const char *ent_name
;
1164 struct section
*psection
;
1165 struct entry
*pentry
= NULL
;
1168 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1170 va_start(args
, path
);
1171 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1174 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1179 if (psection
->include
&& !include
) {
1180 log_error("Tried to insert normal entry to include section");
1184 if (allow_replace
) {
1185 pentry
= section_entry_by_name(psection
, ent_name
);
1186 if (NULL
!= pentry
) {
1187 if (ENTRY_STR
== entry_type(pentry
)) {
1188 if (!entry_str_set(pentry
, str
)) {
1192 entry_destroy(pentry
);
1198 if (NULL
== pentry
) {
1199 pentry
= section_entry_str_new(psection
, ent_name
, str
, !no_escape
);
1202 if (NULL
!= pentry
&& NULL
!= comment
) {
1203 entry_set_comment(pentry
, comment
);
1209 /**************************************************************************
1210 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1211 the number of entries inserted or replaced.
1212 **************************************************************************/
1213 size_t secfile_insert_str_vec_full(struct section_file
*secfile
,
1214 const char *const *strings
, size_t dim
,
1215 const char *comment
, bool allow_replace
,
1216 bool no_escape
, const char *path
, ...)
1218 char fullpath
[MAX_LEN_SECPATH
];
1222 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1224 va_start(args
, path
);
1225 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1228 /* NB: 'path,0' is actually 'path'. See comment in the head
1231 && NULL
!= secfile_insert_str_full(secfile
, strings
[0], comment
,
1232 allow_replace
, no_escape
, FALSE
,
1236 for (i
= 1; i
< dim
; i
++) {
1237 if (NULL
!= secfile_insert_str_full(secfile
, strings
[i
], comment
,
1238 allow_replace
, no_escape
, FALSE
,
1239 "%s,%d", fullpath
, (int) i
)) {
1247 /****************************************************************************
1248 Insert a read-from-a-file string entry
1249 ****************************************************************************/
1250 struct entry
*secfile_insert_filereference(struct section_file
*secfile
,
1251 char *filename
, char *path
, ...)
1253 char fullpath
[MAX_LEN_SECPATH
];
1254 const char *ent_name
;
1255 struct section
*psection
;
1256 struct entry
*pentry
= NULL
;
1259 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1261 va_start(args
, path
);
1262 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1265 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1270 if (psection
->include
) {
1271 log_error("Tried to insert normal entry to include section");
1275 if (NULL
== pentry
) {
1276 pentry
= section_entry_filereference_new(psection
, ent_name
, filename
);
1282 /****************************************************************************
1283 Insert a enumerator entry.
1284 ****************************************************************************/
1285 struct entry
*secfile_insert_plain_enum_full(struct section_file
*secfile
,
1287 secfile_enum_name_fn_t name_fn
,
1288 const char *comment
,
1290 const char *path
, ...)
1292 char fullpath
[MAX_LEN_SECPATH
];
1294 const char *ent_name
;
1295 struct section
*psection
;
1296 struct entry
*pentry
= NULL
;
1299 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1300 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1301 str
= name_fn(enumerator
);
1302 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= str
, NULL
);
1304 va_start(args
, path
);
1305 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1308 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1313 if (allow_replace
) {
1314 pentry
= section_entry_by_name(psection
, ent_name
);
1315 if (NULL
!= pentry
) {
1316 if (ENTRY_STR
== entry_type(pentry
)) {
1317 if (!entry_str_set(pentry
, str
)) {
1321 entry_destroy(pentry
);
1327 if (NULL
== pentry
) {
1328 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1331 if (NULL
!= pentry
&& NULL
!= comment
) {
1332 entry_set_comment(pentry
, comment
);
1338 /****************************************************************************
1339 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1340 the number of entries inserted or replaced.
1341 ****************************************************************************/
1342 size_t secfile_insert_plain_enum_vec_full(struct section_file
*secfile
,
1343 const int *enumurators
, size_t dim
,
1344 secfile_enum_name_fn_t name_fn
,
1345 const char *comment
,
1347 const char *path
, ...)
1349 char fullpath
[MAX_LEN_SECPATH
];
1353 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1354 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1356 va_start(args
, path
);
1357 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1360 /* NB: 'path,0' is actually 'path'. See comment in the head
1363 && NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[0],
1365 allow_replace
, "%s",
1369 for (i
= 1; i
< dim
; i
++) {
1370 if (NULL
!= secfile_insert_plain_enum_full(secfile
, enumurators
[i
],
1372 allow_replace
, "%s,%d",
1373 fullpath
, (int) i
)) {
1381 /****************************************************************************
1382 Insert a bitwise value entry.
1383 ****************************************************************************/
1384 struct entry
*secfile_insert_bitwise_enum_full(struct section_file
*secfile
,
1386 secfile_enum_name_fn_t
1388 secfile_enum_iter_fn_t
1390 secfile_enum_iter_fn_t
1392 secfile_enum_next_fn_t
1394 const char *comment
,
1396 const char *path
, ...)
1398 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1399 const char *ent_name
;
1400 struct section
*psection
;
1401 struct entry
*pentry
= NULL
;
1405 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1406 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1407 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, NULL
);
1408 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, NULL
);
1409 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, NULL
);
1411 /* Compute a string containing all the values separated by '|'. */
1412 str
[0] = '\0'; /* Insert at least an empty string. */
1413 if (0 != bitwise_val
) {
1414 for (i
= begin_fn(); i
!= end_fn(); i
= next_fn(i
)) {
1415 if (i
& bitwise_val
) {
1416 if ('\0' == str
[0]) {
1417 sz_strlcpy(str
, name_fn(i
));
1419 cat_snprintf(str
, sizeof(str
), "|%s", name_fn(i
));
1425 va_start(args
, path
);
1426 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1429 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1434 if (allow_replace
) {
1435 pentry
= section_entry_by_name(psection
, ent_name
);
1436 if (NULL
!= pentry
) {
1437 if (ENTRY_STR
== entry_type(pentry
)) {
1438 if (!entry_str_set(pentry
, str
)) {
1442 entry_destroy(pentry
);
1448 if (NULL
== pentry
) {
1449 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1452 if (NULL
!= pentry
&& NULL
!= comment
) {
1453 entry_set_comment(pentry
, comment
);
1459 /****************************************************************************
1460 Insert 'dim' string entries at 'path,0', 'path,1' etc. Returns
1461 the number of entries inserted or replaced.
1462 ****************************************************************************/
1463 size_t secfile_insert_bitwise_enum_vec_full(struct section_file
*secfile
,
1464 const int *bitwise_vals
,
1466 secfile_enum_name_fn_t name_fn
,
1467 secfile_enum_iter_fn_t begin_fn
,
1468 secfile_enum_iter_fn_t end_fn
,
1469 secfile_enum_next_fn_t next_fn
,
1470 const char *comment
,
1472 const char *path
, ...)
1474 char fullpath
[MAX_LEN_SECPATH
];
1478 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1479 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1480 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= begin_fn
, 0);
1481 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= end_fn
, 0);
1482 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= next_fn
, 0);
1484 va_start(args
, path
);
1485 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1488 /* NB: 'path,0' is actually 'path'. See comment in the head
1491 && NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[0],
1492 name_fn
, begin_fn
, end_fn
,
1494 allow_replace
, "%s",
1498 for (i
= 1; i
< dim
; i
++) {
1499 if (NULL
!= secfile_insert_bitwise_enum_full(secfile
, bitwise_vals
[i
],
1500 name_fn
, begin_fn
, end_fn
,
1502 allow_replace
, "%s,%d",
1503 fullpath
, (int) i
)) {
1511 /****************************************************************************
1512 Insert an enumerator value entry that we only have a name accessor
1514 ****************************************************************************/
1515 struct entry
*secfile_insert_enum_data_full(struct section_file
*secfile
,
1516 int value
, bool bitwise
,
1517 secfile_enum_name_data_fn_t name_fn
,
1518 secfile_data_t data
,
1519 const char *comment
,
1521 const char *path
, ...)
1523 char fullpath
[MAX_LEN_SECPATH
], str
[MAX_LEN_SECPATH
];
1524 const char *ent_name
, *val_name
;
1525 struct section
*psection
;
1526 struct entry
*pentry
= NULL
;
1530 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1531 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
1534 /* Compute a string containing all the values separated by '|'. */
1535 str
[0] = '\0'; /* Insert at least an empty string. */
1537 for (i
= 0; (val_name
= name_fn(data
, i
)); i
++) {
1538 if ((1 << i
) & value
) {
1539 if ('\0' == str
[0]) {
1540 sz_strlcpy(str
, val_name
);
1542 cat_snprintf(str
, sizeof(str
), "|%s", val_name
);
1548 if (!(val_name
= name_fn(data
, value
))) {
1549 SECFILE_LOG(secfile
, NULL
, "Value %d not supported.", value
);
1552 sz_strlcpy(str
, val_name
);
1555 va_start(args
, path
);
1556 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1559 psection
= secfile_insert_base(secfile
, fullpath
, &ent_name
);
1564 if (allow_replace
) {
1565 pentry
= section_entry_by_name(psection
, ent_name
);
1566 if (NULL
!= pentry
) {
1567 if (ENTRY_STR
== entry_type(pentry
)) {
1568 if (!entry_str_set(pentry
, str
)) {
1572 entry_destroy(pentry
);
1578 if (NULL
== pentry
) {
1579 pentry
= section_entry_str_new(psection
, ent_name
, str
, TRUE
);
1582 if (NULL
!= pentry
&& NULL
!= comment
) {
1583 entry_set_comment(pentry
, comment
);
1589 /****************************************************************************
1590 Insert 'dim' entries at 'path,0', 'path,1' etc. Returns the number of
1591 entries inserted or replaced.
1592 ****************************************************************************/
1593 size_t secfile_insert_enum_vec_data_full(struct section_file
*secfile
,
1594 const int *values
, size_t dim
,
1596 secfile_enum_name_data_fn_t name_fn
,
1597 secfile_data_t data
,
1598 const char *comment
,
1600 const char *path
, ...)
1602 char fullpath
[MAX_LEN_SECPATH
];
1606 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, 0);
1607 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, 0);
1609 va_start(args
, path
);
1610 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1613 /* NB: 'path,0' is actually 'path'. See comment in the head
1616 && NULL
!= secfile_insert_enum_data_full(secfile
, values
[0], bitwise
,
1617 name_fn
, data
, comment
,
1618 allow_replace
, "%s",
1622 for (i
= 1; i
< dim
; i
++) {
1623 if (NULL
!= secfile_insert_enum_data_full(secfile
, values
[i
], bitwise
,
1624 name_fn
, data
, comment
,
1625 allow_replace
, "%s,%d",
1626 fullpath
, (int) i
)) {
1634 /****************************************************************************
1635 Returns the entry by the name or NULL if not matched.
1636 ****************************************************************************/
1637 struct entry
*secfile_entry_by_path(const struct section_file
*secfile
,
1640 char fullpath
[MAX_LEN_SECPATH
];
1643 struct section
*psection
;
1645 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1647 sz_strlcpy(fullpath
, path
);
1649 /* treat "sec.foo,0" as "sec.foo": */
1650 len
= strlen(fullpath
);
1651 if (len
> 2 && fullpath
[len
- 2] == ',' && fullpath
[len
- 1] == '0') {
1652 fullpath
[len
- 2] = '\0';
1655 if (NULL
!= secfile
->hash
.entries
) {
1656 struct entry
*pentry
;
1658 if (entry_hash_lookup(secfile
->hash
.entries
, fullpath
, &pentry
)) {
1664 /* I dont like strtok.
1666 ent_name
= strchr(fullpath
, '.');
1671 /* Separates section and entry names. */
1673 psection
= secfile_section_by_name(secfile
, fullpath
);
1675 return section_entry_by_name(psection
, ent_name
);
1681 /**************************************************************************
1683 **************************************************************************/
1684 bool secfile_entry_delete(struct section_file
*secfile
,
1685 const char *path
, ...)
1687 char fullpath
[MAX_LEN_SECPATH
];
1689 struct entry
*pentry
;
1691 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1693 va_start(args
, path
);
1694 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1697 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1698 SECFILE_LOG(secfile
, NULL
, "Path %s does not exists.", fullpath
);
1702 entry_destroy(pentry
);
1707 /**************************************************************************
1708 Returns the entry at "fullpath" or NULL if not matched.
1709 **************************************************************************/
1710 struct entry
*secfile_entry_lookup(const struct section_file
*secfile
,
1711 const char *path
, ...)
1713 char fullpath
[MAX_LEN_SECPATH
];
1716 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1718 va_start(args
, path
);
1719 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1722 return secfile_entry_by_path(secfile
, fullpath
);
1725 /**************************************************************************
1726 Lookup a boolean value in the secfile. Returns TRUE on success.
1727 **************************************************************************/
1728 bool secfile_lookup_bool(const struct section_file
*secfile
, bool *bval
,
1729 const char *path
, ...)
1731 char fullpath
[MAX_LEN_SECPATH
];
1732 const struct entry
*pentry
;
1735 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1737 va_start(args
, path
);
1738 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1741 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1742 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1746 return entry_bool_get(pentry
, bval
);
1749 /**************************************************************************
1750 Lookup a boolean value in the secfile. On failure, use the default
1752 **************************************************************************/
1753 bool secfile_lookup_bool_default(const struct section_file
*secfile
,
1754 bool def
, const char *path
, ...)
1756 char fullpath
[MAX_LEN_SECPATH
];
1757 const struct entry
*pentry
;
1761 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1763 va_start(args
, path
);
1764 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1767 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1771 if (entry_bool_get(pentry
, &bval
)) {
1778 /**************************************************************************
1779 Lookup a boolean vector in the secfile. Returns NULL on error. This
1780 vector is not owned by the registry module, and should be free by the
1782 **************************************************************************/
1783 bool *secfile_lookup_bool_vec(const struct section_file
*secfile
,
1784 size_t *dim
, const char *path
, ...)
1786 char fullpath
[MAX_LEN_SECPATH
];
1791 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1792 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
1794 va_start(args
, path
);
1795 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1799 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
1805 /* Doesn't exist. */
1806 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1810 vec
= fc_malloc(i
* sizeof(bool));
1811 for(i
= 0; i
< *dim
; i
++) {
1812 if (!secfile_lookup_bool(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
1813 SECFILE_LOG(secfile
, NULL
,
1814 "An error occurred when looking up to \"%s,%d\" entry.",
1825 /**************************************************************************
1826 Lookup a integer value in the secfile. Returns TRUE on success.
1827 **************************************************************************/
1828 bool secfile_lookup_int(const struct section_file
*secfile
, int *ival
,
1829 const char *path
, ...)
1831 char fullpath
[MAX_LEN_SECPATH
];
1832 const struct entry
*pentry
;
1835 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1837 va_start(args
, path
);
1838 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1841 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1842 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1846 return entry_int_get(pentry
, ival
);
1849 /**************************************************************************
1850 Lookup a integer value in the secfile. On failure, use the default
1852 **************************************************************************/
1853 int secfile_lookup_int_default(const struct section_file
*secfile
, int def
,
1854 const char *path
, ...)
1856 char fullpath
[MAX_LEN_SECPATH
];
1857 const struct entry
*pentry
;
1861 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
1863 va_start(args
, path
);
1864 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1867 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1871 if (entry_int_get(pentry
, &ival
)) {
1878 /**************************************************************************
1879 Lookup a integer value in the secfile. The value will be arranged to
1880 match the interval [minval, maxval]. On failure, use the default
1882 **************************************************************************/
1883 int secfile_lookup_int_def_min_max(const struct section_file
*secfile
,
1884 int defval
, int minval
, int maxval
,
1885 const char *path
, ...)
1887 char fullpath
[MAX_LEN_SECPATH
];
1888 const struct entry
*pentry
;
1892 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
1894 va_start(args
, path
);
1895 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1898 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1902 if (!entry_int_get(pentry
, &value
)) {
1906 if (value
< minval
) {
1907 SECFILE_LOG(secfile
, entry_section(pentry
),
1908 "\"%s\" should be in the interval [%d, %d] but is %d;"
1909 "using the minimal value.",
1910 fullpath
, minval
, maxval
, value
);
1914 if (value
> maxval
) {
1915 SECFILE_LOG(secfile
, entry_section(pentry
),
1916 "\"%s\" should be in the interval [%d, %d] but is %d;"
1917 "using the maximal value.",
1918 fullpath
, minval
, maxval
, value
);
1925 /**************************************************************************
1926 Lookup a integer vector in the secfile. Returns NULL on error. This
1927 vector is not owned by the registry module, and should be free by the
1929 **************************************************************************/
1930 int *secfile_lookup_int_vec(const struct section_file
*secfile
,
1931 size_t *dim
, const char *path
, ...)
1933 char fullpath
[MAX_LEN_SECPATH
];
1938 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
1939 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
1941 va_start(args
, path
);
1942 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1946 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
1952 /* Doesn't exist. */
1953 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1957 vec
= fc_malloc(i
* sizeof(int));
1958 for(i
= 0; i
< *dim
; i
++) {
1959 if (!secfile_lookup_int(secfile
, vec
+ i
, "%s,%d", fullpath
, (int) i
)) {
1960 SECFILE_LOG(secfile
, NULL
,
1961 "An error occurred when looking up to \"%s,%d\" entry.",
1972 /**************************************************************************
1973 Lookup a floating point value in the secfile. Returns TRUE on success.
1974 **************************************************************************/
1975 bool secfile_lookup_float(const struct section_file
*secfile
, float *fval
,
1976 const char *path
, ...)
1978 char fullpath
[MAX_LEN_SECPATH
];
1979 const struct entry
*pentry
;
1982 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
1984 va_start(args
, path
);
1985 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
1988 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
1989 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
1993 return entry_float_get(pentry
, fval
);
1996 /**************************************************************************
1997 Lookup a floating point value in the secfile. On failure, use the default
1999 **************************************************************************/
2000 float secfile_lookup_float_default(const struct section_file
*secfile
,
2001 float def
, const char *path
, ...)
2003 char fullpath
[MAX_LEN_SECPATH
];
2004 const struct entry
*pentry
;
2008 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2010 va_start(args
, path
);
2011 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2014 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2018 if (entry_float_get(pentry
, &fval
)) {
2025 /**************************************************************************
2026 Lookup a string value in the secfile. Returns NULL on error.
2027 **************************************************************************/
2028 const char *secfile_lookup_str(const struct section_file
*secfile
,
2029 const char *path
, ...)
2031 char fullpath
[MAX_LEN_SECPATH
];
2032 const struct entry
*pentry
;
2036 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2038 va_start(args
, path
);
2039 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2042 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2043 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2047 if (entry_str_get(pentry
, &str
)) {
2054 /**************************************************************************
2055 Lookup a string value in the secfile. On failure, use the default
2057 **************************************************************************/
2058 const char *secfile_lookup_str_default(const struct section_file
*secfile
,
2060 const char *path
, ...)
2062 char fullpath
[MAX_LEN_SECPATH
];
2063 const struct entry
*pentry
;
2067 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, def
);
2069 va_start(args
, path
);
2070 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2073 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2077 if (entry_str_get(pentry
, &str
)) {
2084 /**************************************************************************
2085 Lookup a string vector in the secfile. Returns NULL on error. This
2086 vector is not owned by the registry module, and should be free by the
2087 user, but the string pointers stored inside the vector shouldn't be
2089 **************************************************************************/
2090 const char **secfile_lookup_str_vec(const struct section_file
*secfile
,
2091 size_t *dim
, const char *path
, ...)
2093 char fullpath
[MAX_LEN_SECPATH
];
2098 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2099 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2101 va_start(args
, path
);
2102 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2106 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2112 /* Doesn't exist. */
2113 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2117 vec
= fc_malloc(i
* sizeof(const char *));
2118 for(i
= 0; i
< *dim
; i
++) {
2119 if (!(vec
[i
] = secfile_lookup_str(secfile
, "%s,%d",
2120 fullpath
, (int) i
))) {
2121 SECFILE_LOG(secfile
, NULL
,
2122 "An error occurred when looking up to \"%s,%d\" entry.",
2133 /****************************************************************************
2134 Lookup an enumerator value in the secfile. Returns FALSE on error.
2135 ****************************************************************************/
2136 bool secfile_lookup_plain_enum_full(const struct section_file
*secfile
,
2138 secfile_enum_is_valid_fn_t is_valid_fn
,
2139 secfile_enum_by_name_fn_t by_name_fn
,
2140 const char *path
, ...)
2142 char fullpath
[MAX_LEN_SECPATH
];
2143 const struct entry
*pentry
;
2147 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2148 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2149 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2150 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2152 va_start(args
, path
);
2153 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2156 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2157 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2161 if (!entry_str_get(pentry
, &str
)) {
2165 *penumerator
= by_name_fn(str
, strcmp
);
2166 if (is_valid_fn(*penumerator
)) {
2170 SECFILE_LOG(secfile
, entry_section(pentry
),
2171 "Entry \"%s\": no match for \"%s\".",
2172 entry_name(pentry
), str
);
2176 /****************************************************************************
2177 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2178 ****************************************************************************/
2179 int secfile_lookup_plain_enum_default_full(const struct section_file
2180 *secfile
, int defval
,
2181 secfile_enum_is_valid_fn_t
2183 secfile_enum_by_name_fn_t
2185 const char *path
, ...)
2187 char fullpath
[MAX_LEN_SECPATH
];
2188 const struct entry
*pentry
;
2193 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2194 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2195 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2197 va_start(args
, path
);
2198 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2201 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2205 if (!entry_str_get(pentry
, &str
)) {
2209 val
= by_name_fn(str
, strcmp
);
2210 if (is_valid_fn(val
)) {
2217 /**************************************************************************
2218 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2219 vector is not owned by the registry module, and should be free by the
2221 **************************************************************************/
2222 int *secfile_lookup_plain_enum_vec_full(const struct section_file
*secfile
,
2224 secfile_enum_is_valid_fn_t
2226 secfile_enum_by_name_fn_t
2228 const char *path
, ...)
2230 char fullpath
[MAX_LEN_SECPATH
];
2235 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2236 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2237 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2238 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2240 va_start(args
, path
);
2241 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2245 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2251 /* Doesn't exist. */
2252 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2256 vec
= fc_malloc(i
* sizeof(int));
2257 for(i
= 0; i
< *dim
; i
++) {
2258 if (!secfile_lookup_plain_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2259 by_name_fn
, "%s,%d",
2260 fullpath
, (int) i
)) {
2261 SECFILE_LOG(secfile
, NULL
,
2262 "An error occurred when looking up to \"%s,%d\" entry.",
2273 /****************************************************************************
2274 Lookup a bitwise enumerator value in the secfile. Returns FALSE on error.
2275 ****************************************************************************/
2276 bool secfile_lookup_bitwise_enum_full(const struct section_file
*secfile
,
2278 secfile_enum_is_valid_fn_t is_valid_fn
,
2279 secfile_enum_by_name_fn_t by_name_fn
,
2280 const char *path
, ...)
2282 char fullpath
[MAX_LEN_SECPATH
];
2283 const struct entry
*pentry
;
2284 const char *str
, *p
;
2285 char val_name
[MAX_LEN_SECPATH
];
2289 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2290 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= penumerator
, FALSE
);
2291 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, FALSE
);
2292 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, FALSE
);
2294 va_start(args
, path
);
2295 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2298 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2299 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2303 if (!entry_str_get(pentry
, &str
)) {
2308 if ('\0' == str
[0]) {
2309 /* Empty string = no value. */
2313 /* Value names are separated by '|'. */
2315 p
= strchr(str
, '|');
2318 fc_strlcpy(val_name
, str
, p
- str
);
2320 /* Last segment, full copy. */
2321 sz_strlcpy(val_name
, str
);
2323 remove_leading_trailing_spaces(val_name
);
2324 val
= by_name_fn(val_name
, strcmp
);
2325 if (!is_valid_fn(val
)) {
2326 SECFILE_LOG(secfile
, entry_section(pentry
),
2327 "Entry \"%s\": no match for \"%s\".",
2328 entry_name(pentry
), val_name
);
2331 *penumerator
|= val
;
2333 } while (NULL
!= p
);
2338 /****************************************************************************
2339 Lookup an enumerator value in the secfile. Returns 'defval' on error.
2340 ****************************************************************************/
2341 int secfile_lookup_bitwise_enum_default_full(const struct section_file
2342 *secfile
, int defval
,
2343 secfile_enum_is_valid_fn_t
2345 secfile_enum_by_name_fn_t
2347 const char *path
, ...)
2349 char fullpath
[MAX_LEN_SECPATH
];
2350 const struct entry
*pentry
;
2351 const char *str
, *p
;
2352 char val_name
[MAX_LEN_SECPATH
];
2356 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2357 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, defval
);
2358 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, defval
);
2360 va_start(args
, path
);
2361 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2364 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2368 if (!entry_str_get(pentry
, &str
)) {
2372 if ('\0' == str
[0]) {
2373 /* Empty string = no value. */
2377 /* Value names are separated by '|'. */
2380 p
= strchr(str
, '|');
2383 fc_strlcpy(val_name
, str
, p
- str
);
2385 /* Last segment, full copy. */
2386 sz_strlcpy(val_name
, str
);
2388 remove_leading_trailing_spaces(val_name
);
2389 val
= by_name_fn(val_name
, strcmp
);
2390 if (!is_valid_fn(val
)) {
2395 } while (NULL
!= p
);
2400 /**************************************************************************
2401 Lookup a enumerator vector in the secfile. Returns NULL on error. This
2402 vector is not owned by the registry module, and should be free by the
2404 **************************************************************************/
2405 int *secfile_lookup_bitwise_enum_vec_full(const struct section_file
*secfile
,
2407 secfile_enum_is_valid_fn_t
2409 secfile_enum_by_name_fn_t
2411 const char *path
, ...)
2413 char fullpath
[MAX_LEN_SECPATH
];
2418 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2419 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2420 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= is_valid_fn
, NULL
);
2421 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= by_name_fn
, NULL
);
2423 va_start(args
, path
);
2424 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2428 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2434 /* Doesn't exist. */
2435 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2439 vec
= fc_malloc(i
* sizeof(int));
2440 for(i
= 0; i
< *dim
; i
++) {
2441 if (!secfile_lookup_bitwise_enum_full(secfile
, vec
+ i
, is_valid_fn
,
2442 by_name_fn
, "%s,%d",
2443 fullpath
, (int) i
)) {
2444 SECFILE_LOG(secfile
, NULL
,
2445 "An error occurred when looking up to \"%s,%d\" entry.",
2456 /****************************************************************************
2457 Lookup a value saved as string in the secfile. Returns FALSE on error.
2458 ****************************************************************************/
2459 bool secfile_lookup_enum_data(const struct section_file
*secfile
,
2460 int *pvalue
, bool bitwise
,
2461 secfile_enum_name_data_fn_t name_fn
,
2462 secfile_data_t data
, const char *path
, ...)
2464 char fullpath
[MAX_LEN_SECPATH
];
2465 const struct entry
*pentry
;
2466 const char *str
, *p
, *name
;
2467 char val_name
[MAX_LEN_SECPATH
];
2471 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, FALSE
);
2472 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= pvalue
, FALSE
);
2473 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, FALSE
);
2475 va_start(args
, path
);
2476 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2479 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2480 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2484 if (!entry_str_get(pentry
, &str
)) {
2490 if ('\0' == str
[0]) {
2491 /* Empty string = no value. */
2495 /* Value names are separated by '|'. */
2497 p
= strchr(str
, '|');
2500 fc_strlcpy(val_name
, str
, p
- str
);
2502 /* Last segment, full copy. */
2503 sz_strlcpy(val_name
, str
);
2505 remove_leading_trailing_spaces(val_name
);
2506 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2507 if (0 == fc_strcasecmp(name
, val_name
)) {
2512 SECFILE_LOG(secfile
, entry_section(pentry
),
2513 "Entry \"%s\": no match for \"%s\".",
2514 entry_name(pentry
), val_name
);
2517 *pvalue
|= 1 << val
;
2519 } while (NULL
!= p
);
2521 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2522 if (0 == fc_strcasecmp(name
, str
)) {
2528 SECFILE_LOG(secfile
, entry_section(pentry
),
2529 "Entry \"%s\": no match for \"%s\".",
2530 entry_name(pentry
), str
);
2538 /****************************************************************************
2539 Lookup a value saved as string in the secfile. Returns 'defval' on error.
2540 ****************************************************************************/
2541 int secfile_lookup_enum_default_data(const struct section_file
*secfile
,
2542 int defval
, bool bitwise
,
2543 secfile_enum_name_data_fn_t name_fn
,
2544 secfile_data_t data
,
2545 const char *path
, ...)
2547 char fullpath
[MAX_LEN_SECPATH
];
2548 const struct entry
*pentry
;
2549 const char *str
, *p
, *name
;
2550 char val_name
[MAX_LEN_SECPATH
];
2554 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, defval
);
2555 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, defval
);
2557 va_start(args
, path
);
2558 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2561 if (!(pentry
= secfile_entry_by_path(secfile
, fullpath
))) {
2562 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2566 if (!entry_str_get(pentry
, &str
)) {
2572 if ('\0' == str
[0]) {
2573 /* Empty string = no value. */
2577 /* Value names are separated by '|'. */
2579 p
= strchr(str
, '|');
2582 fc_strlcpy(val_name
, str
, p
- str
);
2584 /* Last segment, full copy. */
2585 sz_strlcpy(val_name
, str
);
2587 remove_leading_trailing_spaces(val_name
);
2588 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2589 if (0 == strcmp(name
, val_name
)) {
2594 SECFILE_LOG(secfile
, entry_section(pentry
),
2595 "Entry \"%s\": no match for \"%s\".",
2596 entry_name(pentry
), val_name
);
2601 } while (NULL
!= p
);
2603 for (val
= 0; (name
= name_fn(data
, val
)); val
++) {
2604 if (0 == strcmp(name
, str
)) {
2610 SECFILE_LOG(secfile
, entry_section(pentry
),
2611 "Entry \"%s\": no match for \"%s\".",
2612 entry_name(pentry
), str
);
2620 /****************************************************************************
2621 Lookup a vector in the secfile. Returns NULL on error. This vector
2622 is not owned by the registry module, and should be free by the user.
2623 ****************************************************************************/
2624 int *secfile_lookup_enum_vec_data(const struct section_file
*secfile
,
2625 size_t *dim
, bool bitwise
,
2626 secfile_enum_name_data_fn_t name_fn
,
2627 secfile_data_t data
, const char *path
, ...)
2629 char fullpath
[MAX_LEN_SECPATH
];
2634 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2635 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= dim
, NULL
);
2636 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= name_fn
, NULL
);
2638 va_start(args
, path
);
2639 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2643 while (NULL
!= secfile_entry_lookup(secfile
, "%s,%d", fullpath
, (int) i
)) {
2649 /* Doesn't exist. */
2650 SECFILE_LOG(secfile
, NULL
, "\"%s\" entry doesn't exist.", fullpath
);
2654 vec
= fc_malloc(i
* sizeof(int));
2655 for (i
= 0; i
< *dim
; i
++) {
2656 if (!secfile_lookup_enum_data(secfile
, vec
+ i
, bitwise
, name_fn
, data
,
2657 "%s,%d", fullpath
, (int) i
)) {
2658 SECFILE_LOG(secfile
, NULL
,
2659 "An error occurred when looking up to \"%s,%d\" entry.",
2670 /****************************************************************************
2671 Returns the first section matching the name.
2672 ****************************************************************************/
2673 struct section
*secfile_section_by_name(const struct section_file
*secfile
,
2676 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2678 section_list_iterate(secfile
->sections
, psection
) {
2679 if (0 == strcmp(section_name(psection
), name
)) {
2682 } section_list_iterate_end
;
2687 /**************************************************************************
2688 Find a section by path.
2689 **************************************************************************/
2690 struct section
*secfile_section_lookup(const struct section_file
*secfile
,
2691 const char *path
, ...)
2693 char fullpath
[MAX_LEN_SECPATH
];
2696 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2698 va_start(args
, path
);
2699 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2702 return secfile_section_by_name(secfile
, fullpath
);
2705 /**************************************************************************
2706 Returns the list of sections. This list is owned by the registry module
2707 and shouldn't be modified and destroyed.
2708 **************************************************************************/
2709 const struct section_list
*
2710 secfile_sections(const struct section_file
*secfile
)
2712 return (NULL
!= secfile
? secfile
->sections
: NULL
);
2715 /**************************************************************************
2716 Returns the list of sections which match the name prefix. Returns NULL
2717 if no section was found. This list is not owned by the registry module
2718 and the user must destroy it when he finished to work with it.
2719 **************************************************************************/
2720 struct section_list
*
2721 secfile_sections_by_name_prefix(const struct section_file
*secfile
,
2724 struct section_list
*matches
= NULL
;
2727 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2728 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= prefix
, NULL
);
2730 len
= strlen(prefix
);
2735 section_list_iterate(secfile
->sections
, psection
) {
2736 if (0 == strncmp(section_name(psection
), prefix
, len
)) {
2737 if (NULL
== matches
) {
2738 matches
= section_list_new();
2740 section_list_append(matches
, psection
);
2742 } section_list_iterate_end
;
2747 /**************************************************************************
2748 Create a new section in the secfile.
2749 **************************************************************************/
2750 struct section
*secfile_section_new(struct section_file
*secfile
,
2753 struct section
*psection
;
2755 SECFILE_RETURN_VAL_IF_FAIL(secfile
, NULL
, NULL
!= secfile
, NULL
);
2757 if (NULL
== name
|| '\0' == name
[0]) {
2758 SECFILE_LOG(secfile
, NULL
, "Cannot create a section without name.");
2762 if (!is_secfile_entry_name_valid(name
)) {
2763 SECFILE_LOG(secfile
, NULL
, "\"%s\" is not a valid section name.",
2768 if (NULL
!= secfile_section_by_name(secfile
, name
)) {
2769 /* We cannot duplicate sections in any case! Not even if one is
2770 * include -section and the other not. */
2771 SECFILE_LOG(secfile
, NULL
, "Section \"%s\" already exists.", name
);
2775 psection
= fc_malloc(sizeof(struct section
));
2776 psection
->include
= FALSE
;
2777 psection
->name
= fc_strdup(name
);
2778 psection
->entries
= entry_list_new_full(entry_destroy
);
2780 /* Append to secfile. */
2781 psection
->secfile
= secfile
;
2782 section_list_append(secfile
->sections
, psection
);
2784 if (NULL
!= secfile
->hash
.sections
) {
2785 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2791 /**************************************************************************
2792 Remove this section from the secfile.
2793 **************************************************************************/
2794 void section_destroy(struct section
*psection
)
2796 struct section_file
*secfile
;
2798 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2800 section_clear_all(psection
);
2802 if ((secfile
= psection
->secfile
)) {
2803 /* Detach from secfile. */
2804 if (section_list_remove(secfile
->sections
, psection
)) {
2805 /* This has called section_destroy() already then. */
2808 if (NULL
!= secfile
->hash
.sections
) {
2809 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2813 entry_list_destroy(psection
->entries
);
2814 free(psection
->name
);
2818 /**************************************************************************
2820 **************************************************************************/
2821 void section_clear_all(struct section
*psection
)
2823 SECFILE_RETURN_IF_FAIL(NULL
, psection
, NULL
!= psection
);
2825 /* This include the removing of the hash datas. */
2826 entry_list_clear(psection
->entries
);
2828 if (0 < entry_list_size(psection
->entries
)) {
2829 SECFILE_LOG(psection
->secfile
, psection
,
2830 "After clearing all, %d entries are still remaining.",
2831 entry_list_size(psection
->entries
));
2835 /**************************************************************************
2836 Change the section name. Returns TRUE on success.
2837 **************************************************************************/
2838 bool section_set_name(struct section
*psection
, const char *name
)
2840 struct section_file
*secfile
;
2841 struct section
*pother
;
2843 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, FALSE
);
2844 secfile
= psection
->secfile
;
2845 SECFILE_RETURN_VAL_IF_FAIL(secfile
, psection
, NULL
!= secfile
, FALSE
);
2847 if (NULL
== name
|| '\0' == name
[0]) {
2848 SECFILE_LOG(secfile
, psection
, "No new name for section \"%s\".",
2853 if (!is_secfile_entry_name_valid(name
)) {
2854 SECFILE_LOG(secfile
, psection
,
2855 "\"%s\" is not a valid section name for section \"%s\".",
2856 name
, psection
->name
);
2860 if ((pother
= secfile_section_by_name(secfile
, name
))
2861 && pother
!= psection
) {
2862 /* We cannot duplicate sections in any case! */
2863 SECFILE_LOG(secfile
, psection
, "Section \"%s\" already exists.", name
);
2867 /* Remove old references in the hash tables. */
2868 if (NULL
!= secfile
->hash
.sections
) {
2869 section_hash_remove(secfile
->hash
.sections
, psection
->name
);
2871 if (NULL
!= secfile
->hash
.entries
) {
2872 entry_list_iterate(psection
->entries
, pentry
) {
2873 secfile_hash_delete(secfile
, pentry
);
2874 } entry_list_iterate_end
;
2877 /* Really rename. */
2878 free(psection
->name
);
2879 psection
->name
= fc_strdup(name
);
2881 /* Reinsert new references into the hash tables. */
2882 if (NULL
!= secfile
->hash
.sections
) {
2883 section_hash_insert(secfile
->hash
.sections
, psection
->name
, psection
);
2885 if (NULL
!= secfile
->hash
.entries
) {
2886 entry_list_iterate(psection
->entries
, pentry
) {
2887 secfile_hash_insert(secfile
, pentry
);
2888 } entry_list_iterate_end
;
2894 /**************************************************************************
2895 Returns a list containing all the entries. This list is owned by the
2896 secfile, so don't modify or destroy it.
2897 **************************************************************************/
2898 const struct entry_list
*section_entries(const struct section
*psection
)
2900 return (NULL
!= psection
? psection
->entries
: NULL
);
2903 /**************************************************************************
2904 Returns the the first entry matching the name.
2905 **************************************************************************/
2906 struct entry
*section_entry_by_name(const struct section
*psection
,
2909 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2911 entry_list_iterate(psection
->entries
, pentry
) {
2912 if (0 == strcmp(entry_name(pentry
), name
)) {
2916 } entry_list_iterate_end
;
2921 /**************************************************************************
2922 Returns the entry matching the path.
2923 **************************************************************************/
2924 struct entry
*section_entry_lookup(const struct section
*psection
,
2925 const char *path
, ...)
2927 char fullpath
[MAX_LEN_SECPATH
];
2928 struct entry
*pentry
;
2931 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2933 va_start(args
, path
);
2934 fc_vsnprintf(fullpath
, sizeof(fullpath
), path
, args
);
2937 if ((pentry
= section_entry_by_name(psection
, fullpath
))) {
2941 /* Try with full path. */
2942 if ((pentry
= secfile_entry_by_path(psection
->secfile
, fullpath
))
2943 && psection
== entry_section(pentry
)) {
2944 /* Unsure this is really owned by this section. */
2952 /* An 'entry' is a string, integer, boolean or string vector;
2953 * See enum entry_type in registry.h.
2956 struct section
*psection
; /* Parent section. */
2957 char *name
; /* Name, not including section prefix. */
2958 enum entry_type type
; /* The type of the entry. */
2959 int used
; /* Number of times entry looked up. */
2960 char *comment
; /* Comment, may be NULL. */
2977 char *value
; /* Malloced string. */
2978 bool escaped
; /* " or $. Usually TRUE */
2979 bool gt_marking
; /* Save with gettext marking. */
2984 /**************************************************************************
2985 Returns a new entry.
2986 **************************************************************************/
2987 static struct entry
*entry_new(struct section
*psection
, const char *name
)
2989 struct section_file
*secfile
;
2990 struct entry
*pentry
;
2992 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= psection
, NULL
);
2994 secfile
= psection
->secfile
;
2995 if (NULL
== name
|| '\0' == name
[0]) {
2996 SECFILE_LOG(secfile
, psection
, "Cannot create an entry without name.");
3000 if (!is_secfile_entry_name_valid(name
)) {
3001 SECFILE_LOG(secfile
, psection
, "\"%s\" is not a valid entry name.",
3006 if (!secfile
->allow_duplicates
3007 && NULL
!= section_entry_by_name(psection
, name
)) {
3008 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3012 pentry
= fc_malloc(sizeof(struct entry
));
3013 pentry
->name
= fc_strdup(name
);
3014 pentry
->type
= -1; /* Invalid case. */
3016 pentry
->comment
= NULL
;
3018 /* Append to section. */
3019 pentry
->psection
= psection
;
3020 entry_list_append(psection
->entries
, pentry
);
3022 /* Notify secfile. */
3023 secfile
->num_entries
++;
3024 secfile_hash_insert(secfile
, pentry
);
3029 /**************************************************************************
3030 Returns a new entry of type ENTRY_INT.
3031 **************************************************************************/
3032 struct entry
*section_entry_int_new(struct section
*psection
,
3033 const char *name
, int value
)
3035 struct entry
*pentry
= entry_new(psection
, name
);
3037 if (NULL
!= pentry
) {
3038 pentry
->type
= ENTRY_INT
;
3039 pentry
->integer
.value
= value
;
3045 /**************************************************************************
3046 Returns a new entry of type ENTRY_BOOL.
3047 **************************************************************************/
3048 struct entry
*section_entry_bool_new(struct section
*psection
,
3049 const char *name
, bool value
)
3051 struct entry
*pentry
= entry_new(psection
, name
);
3053 if (NULL
!= pentry
) {
3054 pentry
->type
= ENTRY_BOOL
;
3055 pentry
->boolean
.value
= value
;
3061 /**************************************************************************
3062 Returns a new entry of type ENTRY_FLOAT.
3063 **************************************************************************/
3064 struct entry
*section_entry_float_new(struct section
*psection
,
3065 const char *name
, float value
)
3067 struct entry
*pentry
= entry_new(psection
, name
);
3069 if (NULL
!= pentry
) {
3070 pentry
->type
= ENTRY_FLOAT
;
3071 pentry
->floating
.value
= value
;
3077 /**************************************************************************
3078 Returns a new entry of type ENTRY_STR.
3079 **************************************************************************/
3080 struct entry
*section_entry_str_new(struct section
*psection
,
3081 const char *name
, const char *value
,
3084 struct entry
*pentry
= entry_new(psection
, name
);
3086 if (NULL
!= pentry
) {
3087 pentry
->type
= ENTRY_STR
;
3088 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3089 pentry
->string
.escaped
= escaped
;
3090 pentry
->string
.gt_marking
= FALSE
;
3096 /**************************************************************************
3097 Returns a new entry of type ENTRY_FILEREFERENCE.
3098 **************************************************************************/
3099 static struct entry
*section_entry_filereference_new(struct section
*psection
,
3100 const char *name
, const char *value
)
3102 struct entry
*pentry
= entry_new(psection
, name
);
3104 if (NULL
!= pentry
) {
3105 pentry
->type
= ENTRY_FILEREFERENCE
;
3106 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3112 /**************************************************************************
3113 Entry structure destructor.
3114 **************************************************************************/
3115 void entry_destroy(struct entry
*pentry
)
3117 struct section_file
*secfile
;
3118 struct section
*psection
;
3120 if (NULL
== pentry
) {
3124 if ((psection
= pentry
->psection
)) {
3125 /* Detach from section. */
3126 if (entry_list_remove(psection
->entries
, pentry
)) {
3127 /* This has called entry_destroy() already then. */
3130 if ((secfile
= psection
->secfile
)) {
3131 /* Detach from secfile. */
3132 secfile
->num_entries
--;
3133 secfile_hash_delete(secfile
, pentry
);
3137 /* Specific type free. */
3138 switch (pentry
->type
) {
3145 case ENTRY_FILEREFERENCE
:
3146 free(pentry
->string
.value
);
3152 if (NULL
!= pentry
->comment
) {
3153 free(pentry
->comment
);
3158 /**************************************************************************
3159 Returns the parent section of this entry.
3160 **************************************************************************/
3161 struct section
*entry_section(const struct entry
*pentry
)
3163 return (NULL
!= pentry
? pentry
->psection
: NULL
);
3166 /**************************************************************************
3167 Returns the type of this entry or -1 or error.
3168 **************************************************************************/
3169 enum entry_type
entry_type(const struct entry
*pentry
)
3171 return (NULL
!= pentry
? pentry
->type
: -1);
3174 /**************************************************************************
3175 Build the entry path. Returns like snprintf().
3176 **************************************************************************/
3177 int entry_path(const struct entry
*pentry
, char *buf
, size_t buf_len
)
3179 return fc_snprintf(buf
, buf_len
, "%s.%s",
3180 section_name(entry_section(pentry
)),
3181 entry_name(pentry
));
3184 /**************************************************************************
3185 Returns the name of this entry.
3186 **************************************************************************/
3187 const char *entry_name(const struct entry
*pentry
)
3189 return (NULL
!= pentry
? pentry
->name
: NULL
);
3192 /**************************************************************************
3193 Sets the name of the entry. Returns TRUE on success.
3194 **************************************************************************/
3195 bool entry_set_name(struct entry
*pentry
, const char *name
)
3197 struct section
*psection
;
3198 struct section_file
*secfile
;
3200 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3201 psection
= pentry
->psection
;
3202 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= psection
, FALSE
);
3203 secfile
= psection
->secfile
;
3204 SECFILE_RETURN_VAL_IF_FAIL(NULL
, psection
, NULL
!= secfile
, FALSE
);
3206 if (NULL
== name
|| '\0' == name
[0]) {
3207 SECFILE_LOG(secfile
, psection
, "No new name for entry \"%s\".",
3212 if (!is_secfile_entry_name_valid(name
)) {
3213 SECFILE_LOG(secfile
, psection
,
3214 "\"%s\" is not a valid entry name for entry \"%s\".",
3215 name
, pentry
->name
);
3219 if (!secfile
->allow_duplicates
) {
3220 struct entry
*pother
= section_entry_by_name(psection
, name
);
3222 if (NULL
!= pother
&& pother
!= pentry
) {
3223 SECFILE_LOG(secfile
, psection
, "Entry \"%s\" already exists.", name
);
3228 /* Remove from hash table the old path. */
3229 secfile_hash_delete(secfile
, pentry
);
3231 /* Really rename the entry. */
3233 pentry
->name
= fc_strdup(name
);
3235 /* Insert into hash table the new path. */
3236 secfile_hash_insert(secfile
, pentry
);
3240 /**************************************************************************
3241 Returns the comment associated to this entry.
3242 **************************************************************************/
3243 const char *entry_comment(const struct entry
*pentry
)
3245 return (NULL
!= pentry
? pentry
->comment
: NULL
);
3248 /**************************************************************************
3249 Sets a comment for the entry. Pass NULL to remove the current one.
3250 **************************************************************************/
3251 void entry_set_comment(struct entry
*pentry
, const char *comment
)
3253 if (NULL
== pentry
) {
3257 if (NULL
!= pentry
->comment
) {
3258 free(pentry
->comment
);
3261 pentry
->comment
= (NULL
!= comment
? fc_strdup(comment
) : NULL
);
3264 /**************************************************************************
3265 Returns TRUE if this entry has been used.
3266 **************************************************************************/
3267 static inline bool entry_used(const struct entry
*pentry
)
3269 return (0 < pentry
->used
);
3272 /**************************************************************************
3273 Increase the used count.
3274 **************************************************************************/
3275 static inline void entry_use(struct entry
*pentry
)
3280 /**************************************************************************
3281 Gets an boolean value. Returns TRUE on success.
3282 On old saved files, 0 and 1 can also be considered as bool.
3283 **************************************************************************/
3284 bool entry_bool_get(const struct entry
*pentry
, bool *value
)
3286 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3288 if (ENTRY_INT
== pentry
->type
3289 && (pentry
->integer
.value
== 0
3290 || pentry
->integer
.value
== 1)
3291 && NULL
!= pentry
->psection
3292 && NULL
!= pentry
->psection
->secfile
3293 && pentry
->psection
->secfile
->allow_digital_boolean
) {
3294 *value
= (0 != pentry
->integer
.value
);
3298 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3299 ENTRY_BOOL
== pentry
->type
, FALSE
);
3301 if (NULL
!= value
) {
3302 *value
= pentry
->boolean
.value
;
3307 /**************************************************************************
3308 Sets an boolean value. Returns TRUE on success.
3309 **************************************************************************/
3310 bool entry_bool_set(struct entry
*pentry
, bool value
)
3312 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3313 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3314 ENTRY_BOOL
== pentry
->type
, FALSE
);
3316 pentry
->boolean
.value
= value
;
3320 /**************************************************************************
3321 Gets an floating value. Returns TRUE on success.
3322 **************************************************************************/
3323 bool entry_float_get(const struct entry
*pentry
, float *value
)
3325 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3326 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3327 ENTRY_FLOAT
== pentry
->type
, FALSE
);
3329 if (NULL
!= value
) {
3330 *value
= pentry
->floating
.value
;
3336 /**************************************************************************
3337 Sets an floating value. Returns TRUE on success.
3338 **************************************************************************/
3339 bool entry_float_set(struct entry
*pentry
, float value
)
3341 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3342 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3343 ENTRY_FLOAT
== pentry
->type
, FALSE
);
3345 pentry
->floating
.value
= value
;
3350 /**************************************************************************
3351 Gets an integer value. Returns TRUE on success.
3352 **************************************************************************/
3353 bool entry_int_get(const struct entry
*pentry
, int *value
)
3355 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3356 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3357 ENTRY_INT
== pentry
->type
, FALSE
);
3359 if (NULL
!= value
) {
3360 *value
= pentry
->integer
.value
;
3365 /**************************************************************************
3366 Sets an integer value. Returns TRUE on success.
3367 **************************************************************************/
3368 bool entry_int_set(struct entry
*pentry
, int value
)
3370 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3371 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3372 ENTRY_INT
== pentry
->type
, FALSE
);
3374 pentry
->integer
.value
= value
;
3378 /**************************************************************************
3379 Gets an string value. Returns TRUE on success.
3380 **************************************************************************/
3381 bool entry_str_get(const struct entry
*pentry
, const char **value
)
3383 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3384 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3385 ENTRY_STR
== pentry
->type
, FALSE
);
3387 if (NULL
!= value
) {
3388 *value
= pentry
->string
.value
;
3393 /**************************************************************************
3394 Sets an string value. Returns TRUE on success.
3395 **************************************************************************/
3396 bool entry_str_set(struct entry
*pentry
, const char *value
)
3398 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3399 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3400 ENTRY_STR
== pentry
->type
, FALSE
);
3402 free(pentry
->string
.value
);
3403 pentry
->string
.value
= fc_strdup(NULL
!= value
? value
: "");
3407 /**************************************************************************
3408 Returns if the string would be escaped.
3409 **************************************************************************/
3410 bool entry_str_escaped(const struct entry
*pentry
)
3412 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3413 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3414 ENTRY_STR
== pentry
->type
, FALSE
);
3416 return pentry
->string
.escaped
;
3419 /**************************************************************************
3420 Sets if the string would be escaped. Returns TRUE on success.
3421 **************************************************************************/
3422 bool entry_str_set_escaped(struct entry
*pentry
, bool escaped
)
3424 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3425 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3426 ENTRY_STR
== pentry
->type
, FALSE
);
3428 pentry
->string
.escaped
= escaped
;
3432 /**************************************************************************
3433 Sets if the string should get gettext marking. Returns TRUE on success.
3434 **************************************************************************/
3435 bool entry_str_set_gt_marking(struct entry
*pentry
, bool gt_marking
)
3437 SECFILE_RETURN_VAL_IF_FAIL(NULL
, NULL
, NULL
!= pentry
, FALSE
);
3438 SECFILE_RETURN_VAL_IF_FAIL(pentry
->psection
->secfile
, pentry
->psection
,
3439 ENTRY_STR
== pentry
->type
, FALSE
);
3441 pentry
->string
.gt_marking
= gt_marking
;
3446 /**************************************************************************
3447 Push an entry into a file stream.
3448 **************************************************************************/
3449 static void entry_to_file(const struct entry
*pentry
, fz_FILE
*fs
)
3451 static char buf
[8192];
3455 switch (pentry
->type
) {
3457 fz_fprintf(fs
, "%s", pentry
->boolean
.value
? "TRUE" : "FALSE");
3460 fz_fprintf(fs
, "%d", pentry
->integer
.value
);
3463 snprintf(buf
, sizeof(buf
), "%f", pentry
->floating
.value
);
3464 for (i
= 0; buf
[i
] != '\0' ; i
++) {
3465 if (buf
[i
] == '.') {
3471 /* There's no '.' so it would seem like a integer value when loaded.
3472 * Force it not to look like an integer by adding ".0" */
3473 fz_fprintf(fs
, "%s.0", buf
);
3475 fz_fprintf(fs
, "%s", buf
);
3479 if (pentry
->string
.escaped
) {
3480 make_escapes(pentry
->string
.value
, buf
, sizeof(buf
));
3481 if (pentry
->string
.gt_marking
) {
3482 fz_fprintf(fs
, "_(\"%s\")", buf
);
3484 fz_fprintf(fs
, "\"%s\"", buf
);
3487 fz_fprintf(fs
, "$%s$", pentry
->string
.value
);
3490 case ENTRY_FILEREFERENCE
:
3491 fz_fprintf(fs
, "*%s*", pentry
->string
.value
);
3496 /**************************************************************************
3497 Creates a new entry from the token.
3498 **************************************************************************/
3499 static void entry_from_inf_token(struct section
*psection
, const char *name
,
3500 const char *tok
, struct inputfile
*inf
)
3502 if (!entry_from_token(psection
, name
, tok
)) {
3503 log_error("%s", inf_log_str(inf
, "Entry value not recognized: %s", tok
));