Skip to content

Commit

Permalink
Add support for handling unknown options
Browse files Browse the repository at this point in the history
Unknown options can be any of the basic types. Lists won't work.
The purpose is to provide some future proofing of config files.
For example, if a new parameter is added to a program, the new
config files won't necessarily fail when run against old versions
of the program.

Signed-off-by: Frank Hunleth <fhunleth@troodon-software.com>
  • Loading branch information
fhunleth authored and troglobit committed Oct 18, 2015
1 parent f292179 commit 0255c50
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
8 changes: 6 additions & 2 deletions src/confuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,8 +884,12 @@ static int cfg_parse_internal(cfg_t *cfg, int level,
return STATE_ERROR;
}
opt = cfg_getopt(cfg, cfg_yylval);
if(opt == 0)
return STATE_ERROR;
if(opt == 0) {
if(cfg->flags & CFGF_IGNORE_UNKNOWN)
opt = cfg_getopt(cfg, "__unknown");
if(opt == 0)
return STATE_ERROR;
}
if(opt->type == CFGT_SEC)
{
if(is_set(CFGF_TITLE, opt->flags))
Expand Down
8 changes: 7 additions & 1 deletion src/confuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef enum cfg_type_t cfg_type_t;

#define CFGF_RESET 64
#define CFGF_DEFINIT 128
#define CFGF_IGNORE_UNKNOWN 256 /**< ignore unknown options in configuration files */

/** Return codes from cfg_parse(). */
#define CFG_SUCCESS 0
Expand Down Expand Up @@ -544,10 +545,15 @@ extern const char __export confuse_author[];
*
* The options must no longer be defined in the same scope as where the cfg_xxx
* functions are used (since version 2.3).
*
* CFG_IGNORE_UNKNOWN can be specified to use the "__unknown" option
* whenever an unknown option is parsed. Be sure to define an "__unknown"
* option in each scope that unknown parameters are allowed.
*
* @param opts An arrary of options
* @param flags One or more flags (bitwise or'ed together). Currently only
* CFGF_NOCASE is available. Use 0 if no flags are needed.
* CFGF_NOCASE and CFGF_IGNORE_UNKNOWN are available. Use 0 if no flags are
* needed.
*
* @return A configuration context structure. This pointer is passed
* to almost all other functions as the first parameter.
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ TESTS += quote_before_print
TESTS += include
TESTS += searchpath
TESTS += env
TESTS += ignore_parm

check_PROGRAMS = $(TESTS)

Expand Down
64 changes: 64 additions & 0 deletions tests/ignore_parm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* Test handling of parameters that should be ignored.
*/

#include <string.h>
#include <stdlib.h>
#include "check_confuse.h"

cfg_opt_t section_opts[] =
{
CFG_STR("section_parameter", NULL, CFGF_NONE),
CFG_STR("__unknown", NULL, CFGF_NONE),
CFG_END()
};

cfg_opt_t opts[] =
{
CFG_STR("parameter", NULL, CFGF_NONE),
CFG_STR("__unknown", NULL, CFGF_NONE),
CFG_SEC("section", section_opts, CFGF_TITLE | CFGF_MULTI),
CFG_END()
};

static int
testconfig(const char *buf)
{
cfg_t *cfg = cfg_init(opts, CFGF_IGNORE_UNKNOWN);
if (!cfg)
return 0;

if (cfg_parse_buf(cfg, buf) != CFG_SUCCESS)
return 0;

cfg_free(cfg);
return 1;
}

int
main(void)
{
/* Sanity check cases that don't need to ignore parameters. */
fail_unless(testconfig("parameter=5"));
fail_unless(testconfig("parameter=5\n"
"section mysection {\n"
"section_parameter=1\n"
"}"));

/* Ignore each type (no lists) */
fail_unless(testconfig("unknown_int=1"));
fail_unless(testconfig("unknown_string=\"hello\""));
fail_unless(testconfig("unknown_float=1.1"));
fail_unless(testconfig("unknown_bool=true"));

/* Ignore multiple parameters */
fail_unless(testconfig("unknown_one=1\n"
"unknown_two=2\n"
"unknown_three=3\n"));

/* Test ignore parameters in a section */
fail_unless(testconfig("section mysection {\n"
"unknown_section_parameter=1\n"
"}"));
return 0;
}

0 comments on commit 0255c50

Please sign in to comment.