Exemple #1
0
DLLIMPORT int cfg_opt_setmulti(cfg_t *cfg, cfg_opt_t *opt, unsigned int nvalues, char **values)
{
	cfg_opt_t old;
	unsigned int i;

	if (!opt || !nvalues)
		return -1;

	old = *opt;
	opt->nvalues = 0;
	opt->values = 0;

	for (i = 0; i < nvalues; i++) {
		if (cfg_setopt(cfg, opt, values[i]))
			continue;
		/* ouch, revert */
		cfg_free_value(opt);
		opt->nvalues = old.nvalues;
		opt->values = old.values;
		return -1;
	}

	cfg_free_value(&old);
	return 0;
}
Exemple #2
0
static int cfg_parse_internal(cfg_t *cfg, int level,
                              int force_state, cfg_opt_t *force_opt)
{
    int state = 0;
    char *opttitle = 0;
    cfg_opt_t *opt = 0;
    cfg_value_t *val = 0;
    cfg_opt_t funcopt = CFG_STR(0, 0, 0);
    int num_values = 0; /* number of values found for a list option */
    int rc;

    if(force_state != -1)
        state = force_state;
    if(force_opt)
        opt = force_opt;

    while(1)
    {
        int tok = cfg_yylex(cfg);

        if(tok == 0)
        {
            /* lexer.l should have called cfg_error */
            return STATE_ERROR;
        }

        if(tok == EOF)
        {
            if(state != 0)
            {
                cfg_error(cfg, _("premature end of file"));
                return STATE_ERROR;
            }
            return STATE_EOF;
        }

        switch(state)
        {
            case 0: /* expecting an option name */
                if(tok == '}')
                {
                    if(level == 0)
                    {
                        cfg_error(cfg, _("unexpected closing brace"));
                        return STATE_ERROR;
                    }
                    return STATE_EOF;
                }
                if(tok != CFGT_STR)
                {
                    cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval);
                    return STATE_ERROR;
                }
                opt = cfg_getopt(cfg, cfg_yylval);
                if(opt == 0)
                    return STATE_ERROR;
                if(opt->type == CFGT_SEC)
                {
                    if(is_set(CFGF_TITLE, opt->flags))
                        state = 6;
                    else
                        state = 5;
                }
                else if(opt->type == CFGT_FUNC)
                {
                    state = 7;
                }
                else
                    state = 1;
                break;

            case 1: /* expecting an equal sign or plus-equal sign */
                if(tok == '+')
                {
                    if(!is_set(CFGF_LIST, opt->flags))
                    {
                        cfg_error(cfg,
                                  _("attempt to append to non-list option '%s'"),
                                  opt->name);
                        return STATE_ERROR;
                    }
                    /* Even if the reset flag was set by
                     * cfg_init_defaults, appending to the defaults
                     * should be ok.
                     */
                    opt->flags &= ~CFGF_RESET;
                }
                else if(tok == '=')
                {
                    /* set the (temporary) reset flag to clear the old
                     * values, since we obviously didn't want to append */
                    opt->flags |= CFGF_RESET;
                }
                else
                {
                    cfg_error(cfg, _("missing equal sign after option '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                if(is_set(CFGF_LIST, opt->flags))
                {
                    state = 3;
                    num_values = 0;
                } else
                    state = 2;
                break;

            case 2: /* expecting an option value */
                if(tok == '}' && is_set(CFGF_LIST, opt->flags))
                {
                    state = 0;
                    if(num_values == 0 && is_set(CFGF_RESET, opt->flags))
                        /* Reset flags was set, and the empty list was
                         * specified. Free all old values. */
                        cfg_free_value(opt);
                    break;
                }

                if(tok != CFGT_STR)
                {
                    cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval);
                    return STATE_ERROR;
                }

                if(cfg_setopt(cfg, opt, cfg_yylval) == 0)
                    return STATE_ERROR;
                if(opt->validcb && (*opt->validcb)(cfg, opt) != 0)
                    return STATE_ERROR;
                if(is_set(CFGF_LIST, opt->flags))
                {
                    state = 4;
                    ++num_values;
                }
                else
                    state = 0;
                break;

            case 3: /* expecting an opening brace for a list option */
                if(tok != '{')
                {
                    cfg_error(cfg, _("missing opening brace for option '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                state = 2;
                break;

            case 4: /* expecting a separator for a list option, or
                     * closing (list) brace */
                if(tok == ',')
                    state = 2;
                else if(tok == '}')
                {
                    state = 0;
                    if(opt->validcb && (*opt->validcb)(cfg, opt) != 0)
                        return STATE_ERROR;
                }
                else
                {
                    cfg_error(cfg, _("unexpected token '%s'"), cfg_yylval);
                    return STATE_ERROR;
                }
                break;

            case 5: /* expecting an opening brace for a section */
                if(tok != '{')
                {
                    cfg_error(cfg, _("missing opening brace for section '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }

                val = cfg_setopt(cfg, opt, opttitle);
                opttitle = 0;
                if(!val)
                    return STATE_ERROR;

                val->section->line = cfg->line;
                rc = cfg_parse_internal(val->section, level+1,-1,0);
                cfg->line = val->section->line;
                if(rc != STATE_EOF)
                    return STATE_ERROR;
                if(opt->validcb && (*opt->validcb)(cfg, opt) != 0)
                    return STATE_ERROR;
                state = 0;
                break;

            case 6: /* expecting a title for a section */
                if(tok != CFGT_STR)
                {
                    cfg_error(cfg, _("missing title for section '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                else
                    opttitle = strdup(cfg_yylval);
                state = 5;
                break;

            case 7: /* expecting an opening parenthesis for a function */
                if(tok != '(')
                {
                    cfg_error(cfg, _("missing parenthesis for function '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                state = 8;
                break;

            case 8: /* expecting a function parameter or a closing paren */
                if(tok == ')')
                {
                    int ret = call_function(cfg, opt, &funcopt);
                    if(ret != 0)
                        return STATE_ERROR;
                    state = 0;
                }
                else if(tok == CFGT_STR)
                {
                    val = cfg_addval(&funcopt);
                    val->string = strdup(cfg_yylval);
                    state = 9;
                }
                else
                {
                    cfg_error(cfg, _("syntax error in call of function '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                break;

            case 9: /* expecting a comma in a function or a closing paren */
                if(tok == ')')
                {
                    int ret = call_function(cfg, opt, &funcopt);
                    if(ret != 0)
                        return STATE_ERROR;
                    state = 0;
                }
                else if(tok == ',')
                    state = 8;
                else
                {
                    cfg_error(cfg, _("syntax error in call of function '%s'"),
                              opt->name);
                    return STATE_ERROR;
                }
                break;

            default:
                /* missing state, internal error, abort */
                assert(0);
        }
    }

    return STATE_EOF;
}
Exemple #3
0
static void cfg_init_defaults(cfg_t *cfg)
{
    int i;

    for(i = 0; cfg->opts[i].name; i++)
    {
        /* libConfuse doesn't handle default values for "simple" options */
        if(cfg->opts[i].simple_value || is_set(CFGF_NODEFAULT, cfg->opts[i].flags))
            continue;

        if(cfg->opts[i].type != CFGT_SEC)
        {
            cfg->opts[i].flags |= CFGF_DEFINIT;

            if(is_set(CFGF_LIST, cfg->opts[i].flags) ||
               cfg->opts[i].def.parsed)
            {
                int xstate, ret;

                /* If it's a list, but no default value was given,
                 * keep the option uninitialized.
                 */
                if(cfg->opts[i].def.parsed == 0 ||
                   cfg->opts[i].def.parsed[0] == 0)
                    continue;

                /* setup scanning from the string specified for the
                 * "default" value, force the correct state and option
                 */

                if(is_set(CFGF_LIST, cfg->opts[i].flags))
                    /* lists must be surrounded by {braces} */
                    xstate = 3;
                else if(cfg->opts[i].type == CFGT_FUNC)
                    xstate = 0;
                else
                    xstate = 2;

                cfg_scan_string_begin(cfg->opts[i].def.parsed);
                do
                {
                    ret = cfg_parse_internal(cfg, 1, xstate, &cfg->opts[i]);
                    xstate = -1;
                } while(ret == STATE_CONTINUE);
                cfg_scan_string_end();
                if(ret == STATE_ERROR)
                {
                    /*
                     * If there was an error parsing the default string,
                     * the initialization of the default value could be
                     * inconsistent or empty. What to do? It's a
                     * programming error and not an end user input
                     * error. Lets print a message and abort...
                     */
                    fprintf(stderr, "Parse error in default value '%s'"
                            " for option '%s'\n",
                            cfg->opts[i].def.parsed, cfg->opts[i].name);
                    fprintf(stderr, "Check your initialization macros and the"
                            " libConfuse documentation\n");
                    abort();
                }
            }
            else
            {
                switch(cfg->opts[i].type)
                {
                    case CFGT_INT:
                        cfg_opt_setnint(&cfg->opts[i],
                                        cfg->opts[i].def.number, 0);
                        break;
                    case CFGT_FLOAT:
                        cfg_opt_setnfloat(&cfg->opts[i],
                                          cfg->opts[i].def.fpnumber, 0);
                        break;
                    case CFGT_BOOL:
                        cfg_opt_setnbool(&cfg->opts[i],
                                         cfg->opts[i].def.boolean, 0);
                        break;
                    case CFGT_STR:
                        cfg_opt_setnstr(&cfg->opts[i],
                                        cfg->opts[i].def.string, 0);
                        break;
                    case CFGT_FUNC:
                    case CFGT_PTR:
                        break;
                    default:
                        cfg_error(cfg,
                                  "internal error in cfg_init_defaults(%s)",
                                  cfg->opts[i].name);
                        break;
                }
            }

            /* The default value should only be returned if no value
             * is given in the configuration file, so we set the RESET
             * flag here. When/If cfg_setopt() is called, the value(s)
             * will be freed and the flag unset.
             */
            cfg->opts[i].flags |= CFGF_RESET;
        } /* end if cfg->opts[i].type != CFGT_SEC */
        else if(!is_set(CFGF_MULTI, cfg->opts[i].flags))
        {
            cfg_setopt(cfg, &cfg->opts[i], 0);
            cfg->opts[i].flags |= CFGF_DEFINIT;
        }
    }
}