"Expected data but not found", /* SILC_CONFIG_EEXPECTED */
"Expected '='", /* SILC_CONFIG_EEXPECTEDEQUAL */
"Unexpected data", /* SILC_CONFIG_EUNEXPECTED */
- "Missing needed fields", /* SILC_CONFIG_EMISSFIELDS */
+ "Missing mandatory fields", /* SILC_CONFIG_EMISSFIELDS */
"Missing ';'", /* SILC_CONFIG_EMISSCOLON */
};
silc_free(ent);
}
-/* Registers a new option in the specified entity */
+/* Registers a new option in the specified entity.
+ * Returns TRUE on success, FALSE if already registered. */
-void silc_config_register(SilcConfigEntity ent, const char *name,
+bool silc_config_register(SilcConfigEntity ent, const char *name,
SilcConfigType type, SilcConfigCallback cb,
const SilcConfigTable *subtable, void *context)
{
SILC_CONFIG_DEBUG(("Register new option=\"%s\" type=%u cb=0x%08x context=0x%08x",
name, type, (uint32) cb, (uint32) context));
- if (!ent || !name)
- return;
/* if we are registering a block, make sure there is a specified sub-table */
- if ((type == SILC_CONFIG_ARG_BLOCK) && !subtable)
- return;
- /* refuse special tag */
+ if (!ent || !name || ((type == SILC_CONFIG_ARG_BLOCK) && !subtable))
+ return FALSE;
+
+ /* don't register a reserved tag */
if (!strcasecmp(name, "include"))
- return;
+ return FALSE;
+
+ /* check if an option was previously registered */
if (silc_config_find_option(ent, name)) {
- fprintf(stderr, "Internal Error: Option double registered\n");
- abort();
+ SILC_LOG_DEBUG(("Error: Can't register \"%s\" twice.", name));
+ return FALSE;
}
/* allocate and append the new option */
newopt->subtable = subtable;
newopt->context = context;
+ /* append this option to the list */
if (!ent->opts)
ent->opts = newopt;
else {
for (tmp = ent->opts; tmp->next; tmp = tmp->next);
tmp->next = newopt;
}
+ return TRUE;
}
/* Register a new option table in the specified config entity */
-void silc_config_register_table(SilcConfigEntity ent,
+bool silc_config_register_table(SilcConfigEntity ent,
const SilcConfigTable table[], void *context)
{
int i;
- if (!ent || !table) return;
+ if (!ent || !table)
+ return FALSE;
SILC_CONFIG_DEBUG(("Registering table"));
- /* FIXME: some potability checks needed */
+ /* XXX FIXME: some potability checks needed - really? */
for (i = 0; table[i].name; i++) {
- silc_config_register(ent, table[i].name, table[i].type,
- table[i].callback, table[i].subtable, context);
+ if (!silc_config_register(ent, table[i].name, table[i].type,
+ table[i].callback, table[i].subtable, context))
+ return FALSE;
}
+ return TRUE;
}
/* ... */
/* now call block clean-up callback (if any) */
if (thisopt->cb) {
- SILC_CONFIG_DEBUG(("Now calling clean-up callback (if any)"));
- thisopt->cb(thisopt->type, thisopt->name, file->line,
- NULL, thisopt->context);
+ int ret;
+ SILC_CONFIG_DEBUG(("Now calling clean-up callback"));
+ ret = thisopt->cb(thisopt->type, thisopt->name, file->line, NULL,
+ thisopt->context);
+ if (ret) {
+ SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
+ return ret;
+ }
}
/* Do we want ';' to be mandatory after close brace? */
if (*(*p)++ != ';')
SILC_CONFIG_EEXPECTED, /* Expected data but not found */
SILC_CONFIG_EEXPECTEDEQUAL, /* Expected '=' */
SILC_CONFIG_EUNEXPECTED, /* Unexpected data */
- SILC_CONFIG_EMISSFIELDS, /* Missing needed fields */
+ SILC_CONFIG_EMISSFIELDS, /* Missing mandatory fields */
SILC_CONFIG_EMISSCOLON, /* Missing ';' */
};
/***/
*
* SYNOPSIS
*
- * void silc_config_register(SilcConfigEntity ent, const char *name,
+ * bool silc_config_register(SilcConfigEntity ent, const char *name,
* SilcConfigType type, SilcConfigCallback cb,
* const SilcConfigTable *subtable,
* void *context);
* will be called with the *val pointer pointing to an internally
* allocated storage of type described by `type'.
* If `type' is SILC_CONFIG_ARG_BLOCK, then `subtable' must be a valid
- * pointer to a SilcConfigTable array specified the options in the
+ * pointer to a SilcConfigTable array specifying the options in the
* sub-block.
+ * If the option `name' was already registered in this sub-block or it
+ * matches the reserved word "Include", then this function returns FALSE,
+ * otherwise it returns TRUE.
*
* SEE ALSO
* silc_config_register_table
*
***/
-void silc_config_register(SilcConfigEntity ent, const char *name,
+bool silc_config_register(SilcConfigEntity ent, const char *name,
SilcConfigType type, SilcConfigCallback cb,
const SilcConfigTable *subtable, void *context);
*
* SYNOPSIS
*
- * void silc_config_register_table(SilcConfigEntity ent,
+ * bool silc_config_register_table(SilcConfigEntity ent,
* const SilcConfigTable table[],
* void *context);
*
* all with the same context `context'.
* The `table' array must be terminated with an entry with the name field
* set to NULL.
+ * If the table contains invalid data this function returns FALSE, otherwise
+ * it returns TRUE. If a calling to this function failed, you must destroy
+ * and recreate the entity before retrying, as it's impossible to detect
+ * the point at the function stopped the registering process.
*
* SEE ALSO
* SilcConfigTable
*
***/
-void silc_config_register_table(SilcConfigEntity ent,
+bool silc_config_register_table(SilcConfigEntity ent,
const SilcConfigTable table[], void *context);
/****f* silcutil/SilcConfigAPI/silc_config_main