summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/options.c')
-rw-r--r--src/lib/util/options.c1440
1 files changed, 469 insertions, 971 deletions
diff --git a/src/lib/util/options.c b/src/lib/util/options.c
index 9c735d5f3bf..3b7fcfa200d 100644
--- a/src/lib/util/options.c
+++ b/src/lib/util/options.c
@@ -45,101 +45,11 @@
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-#define MAX_ENTRY_NAMES 4
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* forward references */
-typedef struct _options_data options_data;
-
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
-/* range parameter for minimum/maximum values */
-typedef union _options_range_parameter options_range_parameter;
-union _options_range_parameter
-{
- float f;
- int i;
-};
-
-
-/* hash table entries */
-typedef struct _options_hash_entry options_hash_entry;
-struct _options_hash_entry
-{
- options_hash_entry * next; /* link to the next entry */
- astring * name; /* name under the current link */
- options_data * data; /* link to associated options_data */
-};
-
-
-/* information about a single entry in the options */
-struct _options_data
-{
- options_hash_entry links[MAX_ENTRY_NAMES]; /* array of hash table entries (one per name) */
- options_data * next; /* link to the next data */
- UINT32 flags; /* flags from the entry */
- UINT32 seqid; /* sequence ID; bumped on each change */
- int error_reported; /* have we reported an error on this option yet? */
- int priority; /* priority of the data set */
- astring * data; /* data for this item */
- astring * defdata; /* default data for this item */
- const char * description; /* description for this item */
- options_range_type range_type; /* the type of range to apply to this item */
- options_range_parameter range_minimum; /* the minimum of the range */
- options_range_parameter range_maximum; /* the maximum of the range */
- void (*callback)(core_options *opts, const char *arg); /* callback to be invoked when parsing */
-};
-
-
-/* structure holding information about a collection of options */
-struct _core_options
-{
- void (*output[OPTMSG_COUNT])(const char *s);/* output callbacks */
-
- /* linked list, for sequential iteration */
- options_data * datalist; /* linked list for sequential iteration */
- options_data ** datalist_nextptr; /* pointer to pointer to tail entry */
-
- /* hashtable, for fast lookup */
- options_hash_entry * hashtable[101]; /* hash table for fast lookup */
-};
-
-
-/* information about an in-progress options enumeration */
-struct _options_enumerator
-{
- options_data * current;
-};
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static options_data *find_entry_data(core_options *opts, const char *string, int is_command_line);
-static void update_data(core_options *opts, options_data *data, const char *newdata, int priority);
-static int parse_option_name(core_options *opts, const char *srcstring, options_data *data);
-
-static void message(core_options *opts, options_message msgtype, const char *format, ...) ATTR_PRINTF(3,4);
-static UINT32 hash_value(core_options *opts, const char *str);
-static void output_printf(void (*output)(const char *s), const char *format, ...) ATTR_PRINTF(2,3);
-
-
-
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
-
-const char *const option_unadorned[MAX_UNADORNED_OPTIONS] =
+const char *const core_options::s_option_unadorned[MAX_UNADORNED_OPTIONS] =
{
"<UNADORNED0>",
"<UNADORNED1>",
@@ -161,448 +71,362 @@ const char *const option_unadorned[MAX_UNADORNED_OPTIONS] =
-/***************************************************************************
- OPTIONS COLLECTION MANAGEMENT
-***************************************************************************/
+//**************************************************************************
+// CORE OPTIONS ENTRY
+//**************************************************************************
-/*-------------------------------------------------
- options_create - creates a new instance of
- core options
--------------------------------------------------*/
+//-------------------------------------------------
+// entry - constructor
+//-------------------------------------------------
-core_options *options_create(void (*fail)(const char *message))
+core_options::entry::entry(const options_entry &entrylist)
+ : m_next(NULL),
+ m_flags(entrylist.flags),
+ m_seqid(0),
+ m_error_reported(false),
+ m_priority(OPTION_PRIORITY_DEFAULT),
+ m_description(entrylist.description)
{
- /* allocate memory for the option block */
- core_options *opts = (core_options *)malloc(sizeof(*opts));
- if (opts == NULL)
- goto error;
-
- /* and set up the structure */
- memset(opts, 0, sizeof(*opts));
- opts->datalist_nextptr = &opts->datalist;
- return opts;
-
-error:
- return NULL;
+ // copy in the name(s) as appropriate
+ if (entrylist.name != NULL)
+ {
+ // first extract any range
+ astring namestr(entrylist.name);
+ int lparen = namestr.chr(0, '(');
+ int dash = namestr.chr(lparen + 1, '-');
+ int rparen = namestr.chr(dash + 1, ')');
+ if (lparen != -1 && dash != -1 && rparen != -1)
+ {
+ m_minimum.cpysubstr(namestr, lparen + 1, dash - (lparen + 1)).trimspace();
+ m_maximum.cpysubstr(namestr, dash + 1, rparen - (dash + 1)).trimspace();
+ namestr.del(lparen, rparen + 1 - lparen);
+ }
+
+ // then chop up any semicolon-separated names
+ int semi;
+ int nameindex = 0;
+ while ((semi = namestr.chr(0, ';')) != -1 && nameindex < ARRAY_LENGTH(m_name))
+ {
+ m_name[nameindex++].cpysubstr(namestr, 0, semi);
+ namestr.del(0, semi + 1);
+ }
+
+ // finally add the last item
+ if (nameindex < ARRAY_LENGTH(m_name))
+ m_name[nameindex++] = namestr;
+ }
+
+ // set the default value
+ if (entrylist.defvalue != NULL)
+ m_defdata = entrylist.defvalue;
+ m_data = m_defdata;
}
-/*-------------------------------------------------
- options_free - frees an options object
--------------------------------------------------*/
+//-------------------------------------------------
+// set_value - update our data value
+//-------------------------------------------------
-void options_free(core_options *opts)
+void core_options::entry::set_value(const char *newdata, int priority)
{
- options_data *data, *next;
-
- /* loop over data items and free them */
- for (data = opts->datalist; data != NULL; data = next)
- {
- int linknum;
-
- next = data->next;
+ // ignore if we don't have priority
+ if (priority < m_priority)
+ return;
- /* free names */
- for (linknum = 0; linknum < ARRAY_LENGTH(data->links); linknum++)
- if (data->links[linknum].name != NULL)
- astring_free(data->links[linknum].name);
+ // set the data and priority, then bump the sequence
+ m_data = newdata;
+ m_priority = priority;
+ m_seqid++;
+}
- /* free strings */
- astring_free(data->data);
- astring_free(data->defdata);
- /* free the data itself */
- free(data);
- }
+//-------------------------------------------------
+// set_default_value - set the default value of
+// an option, and reset the current value to it
+//-------------------------------------------------
- /* free the options itself */
- free(opts);
+void core_options::entry::set_default_value(const char *defvalue)
+{
+ m_data = defvalue;
+ m_defdata = defvalue;
+ m_priority = OPTION_PRIORITY_DEFAULT;
}
-/*-------------------------------------------------
- options_set_output_callback - installs a callback
- to be invoked when data is outputted in the
- process of outputting options
--------------------------------------------------*/
+//-------------------------------------------------
+// revert - revert back to our default if we are
+// at or below the given priority
+//-------------------------------------------------
-void options_set_output_callback(core_options *opts, options_message msgtype, void (*callback)(const char *s))
+void core_options::entry::revert(int priority)
{
- opts->output[msgtype] = callback;
+ // if our priority is low enough, revert to the default
+ if (m_priority <= priority)
+ {
+ m_data = m_defdata;
+ m_priority = OPTION_PRIORITY_DEFAULT;
+ }
}
-/*-------------------------------------------------
- options_revert - revert options at or below
- a certain priority back to their defaults
--------------------------------------------------*/
-void options_revert(core_options *opts, int priority)
+//**************************************************************************
+// CORE OPTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// core_options - constructor
+//-------------------------------------------------
+
+core_options::core_options()
+ : m_entrylist(NULL),
+ m_entrylist_tailptr(&m_entrylist)
{
- options_data *data;
+}
- /* iterate over options and revert to defaults if below the given priority */
- for (data = opts->datalist; data != NULL; data = data->next)
- if (data->priority <= priority)
- {
- astring_cpy(data->data, data->defdata);
- data->priority = OPTION_PRIORITY_DEFAULT;
- }
+core_options::core_options(const options_entry *entrylist)
+ : m_entrylist(NULL),
+ m_entrylist_tailptr(&m_entrylist)
+{
+ add_entries(entrylist);
}
-/*-------------------------------------------------
- options_revert_driver_only - revert options
- that are marked as driver only and are under
- priority level
--------------------------------------------------*/
+core_options::core_options(const options_entry *entrylist1, const options_entry *entrylist2)
+ : m_entrylist(NULL),
+ m_entrylist_tailptr(&m_entrylist)
+{
+ add_entries(entrylist1);
+ add_entries(entrylist2);
+}
-void options_revert_driver_only(core_options *opts, int priority)
+core_options::core_options(const options_entry *entrylist1, const options_entry *entrylist2, const options_entry *entrylist3)
+ : m_entrylist(NULL),
+ m_entrylist_tailptr(&m_entrylist)
{
- options_data *data;
+ add_entries(entrylist1);
+ add_entries(entrylist2);
+ add_entries(entrylist3);
+}
- /* iterate over options and revert to defaults if below the given priority */
- for (data = opts->datalist; data != NULL; data = data->next)
- if ((data->flags & OPTION_DRIVER_ONLY) && (data->priority < priority)) {
- astring_cpy(data->data, data->defdata);
- data->priority = OPTION_PRIORITY_DEFAULT;
- }
+core_options::core_options(const core_options &src)
+ : m_entrylist(NULL),
+ m_entrylist_tailptr(&m_entrylist)
+{
+ copyfrom(src);
}
-/*-------------------------------------------------
- options_copy - copy options from one core_options
- to another
--------------------------------------------------*/
-int options_copy(core_options *dest_opts, core_options *src_opts)
+//-------------------------------------------------
+// ~core_options - destructor
+//-------------------------------------------------
+
+core_options::~core_options()
{
- options_data *data;
+ // delete all entries from the list
+ while (m_entrylist != NULL)
+ remove_entry(*m_entrylist);
+}
- /* iterate over options in the destination */
- for (data = dest_opts->datalist; data != NULL; data = data->next)
- if (!(data->flags & OPTION_HEADER))
- {
- options_data *srcdata = find_entry_data(src_opts, astring_c(data->links[0].name), FALSE);
- /* if the option exists in the source, set it in the destination */
- if (srcdata != NULL)
- options_set_string(dest_opts, astring_c(srcdata->links[0].name), astring_c(srcdata->data), srcdata->priority);
- }
+//-------------------------------------------------
+// operator= - assignment operator
+//-------------------------------------------------
- return TRUE;
+core_options &core_options::operator=(const core_options &rhs)
+{
+ // ignore self-assignment
+ if (this != &rhs)
+ copyfrom(rhs);
+ return *this;
}
-/*-------------------------------------------------
- options_equal - compare two sets of options
--------------------------------------------------*/
+//-------------------------------------------------
+// operator== - compare two sets of options
+//-------------------------------------------------
-int options_equal(core_options *opts1, core_options *opts2)
+bool core_options::operator==(const core_options &rhs)
{
- options_data *data;
-
- /* iterate over options in the first list */
- for (data = opts1->datalist; data != NULL; data = data->next)
- if (!(data->flags & OPTION_HEADER))
+ // iterate over options in the first list
+ for (entry *curentry = m_entrylist; curentry != NULL; curentry = curentry->next())
+ if (!curentry->is_header())
{
- const char *value1 = options_get_string(opts1, astring_c(data->links[0].name));
- const char *value2 = options_get_string(opts2, astring_c(data->links[0].name));
-
- /* if the values differ, return false */
- if (strcmp(value1, value2) != 0)
- return FALSE;
+ // if the values differ, return false
+ if (strcmp(curentry->m_data, rhs.value(curentry->name())) != 0)
+ return false;
}
- return TRUE;
+ return true;
}
+//-------------------------------------------------
+// operator!= - compare two sets of options
+//-------------------------------------------------
-/***************************************************************************
- OPTION DEFINITIONS
-***************************************************************************/
+bool core_options::operator!=(const core_options &rhs)
+{
+ return !operator==(rhs);
+}
-/*-------------------------------------------------
- options_add_entries - add entries to the
- current options sets
--------------------------------------------------*/
-int options_add_entries(core_options *opts, const options_entry *entrylist, int force)
+//-------------------------------------------------
+// add_entries - add entries to the current
+// options sets
+//-------------------------------------------------
+
+void core_options::add_entries(const options_entry *entrylist, bool override_existing)
{
- /* loop over entries until we hit a NULL name */
- for ( ; entrylist->name != NULL || (entrylist->flags & OPTION_HEADER); entrylist++)
+ // loop over entries until we hit a NULL name
+ for ( ; entrylist->name != NULL || (entrylist->flags & OPTION_HEADER) != 0; entrylist++)
{
- options_data *match = NULL;
- int i;
-
- /* allocate a new item */
- options_data *data = (options_data *)malloc(sizeof(*data));
- if (data == NULL)
- return FALSE;
- memset(data, 0, sizeof(*data));
-
- /* parse the option name */
- if (entrylist->name != NULL)
- parse_option_name(opts, entrylist->name, data);
-
- /* do we match an existing entry? */
- for (i = 0; i < ARRAY_LENGTH(data->links) && match == NULL; i++)
- if (data->links[i].name != NULL)
- match = find_entry_data(opts, astring_c(data->links[i].name), FALSE);
-
- /* if so, throw away this entry and replace the data */
- if ((force == FALSE) && (match != NULL))
- {
- /* free what we've allocated so far */
- for (i = 0; i < ARRAY_LENGTH(data->links); i++)
- if (data->links[i].name != NULL)
- astring_free(data->links[i].name);
- free(data);
-
- /* use the matching entry as our data */
- data = match;
- }
-
- /* otherwise, finish making the new entry */
- else
+ // allocate a new entry
+ entry *newentry = new entry(*entrylist);
+ if (newentry->name() != NULL)
{
- /* allocate strings */
- data->data = astring_alloc();
- data->defdata = astring_alloc();
-
- /* copy the flags, and set the value equal to the default */
- data->flags = entrylist->flags;
- data->description = entrylist->description;
-
- /* add us to the end of the sequential list */
- *opts->datalist_nextptr = data;
- opts->datalist_nextptr = &data->next;
-
- /* add each name to the appropriate hash table with a link back to us */
- for (i = 0; i < ARRAY_LENGTH(data->links); i++)
- if (data->links[i].name != NULL)
+ // see if we match an existing entry
+ entry *existing = m_entrymap.find(newentry->name());
+ if (existing != NULL)
+ {
+ // if we're overriding existing entries, then remove the old one
+ if (override_existing)
+ remove_entry(*existing);
+
+ // otherwise, just override the default and current values and throw out the new entry
+ else
{
- int hash_entry = hash_value(opts, astring_c(data->links[i].name));
-
- /* set up link */
- data->links[i].data = data;
- data->links[i].next = opts->hashtable[hash_entry];
- opts->hashtable[hash_entry] = &data->links[i];
+ existing->set_default_value(newentry->value());
+ delete newentry;
+ continue;
}
+ }
}
-
- /* copy in the data and default data values */
- if (entrylist->defvalue != NULL)
- {
- astring_cpyc(data->data, entrylist->defvalue);
- astring_cpyc(data->defdata, entrylist->defvalue);
- }
- data->priority = OPTION_PRIORITY_DEFAULT;
+
+ // add us to the list and maps
+ append_entry(*newentry);
}
- return TRUE;
}
-int options_add_entries(core_options *opts, const options_entry *entrylist)
-{
- return options_add_entries(opts,entrylist,FALSE);
-}
-/*-------------------------------------------------
- options_set_option_default_value - change the
- default value of an option
--------------------------------------------------*/
+//-------------------------------------------------
+// set_default_value - change the default value
+// of an option
+//-------------------------------------------------
-int options_set_option_default_value(core_options *opts, const char *name, const char *defvalue)
+void core_options::set_default_value(const char *name, const char *defvalue)
{
- options_data *data = find_entry_data(opts, name, TRUE);
-
- /* if we don't have an entry for this, fail */
- if (data == NULL)
- return FALSE;
-
- /* update the data and default data; note that we assume that data == defdata */
- astring_cpyc(data->data, defvalue);
- astring_cpyc(data->defdata, defvalue);
- data->priority = OPTION_PRIORITY_DEFAULT;
- return TRUE;
+ // find the entry and bail if we can't
+ entry *curentry = m_entrymap.find(name);
+ if (curentry == NULL)
+ return;
+
+ // update the data and default data
+ curentry->set_default_value(defvalue);
}
-/*-------------------------------------------------
- options_set_option_callback - specifies a
- callback to be invoked when parsing options
--------------------------------------------------*/
+//-------------------------------------------------
+// parse_command_line - parse a series of
+// command line arguments
+//-------------------------------------------------
-int options_set_option_callback(core_options *opts, const char *name, void (*callback)(core_options *opts, const char *arg))
+bool core_options::parse_command_line(int argc, char **argv, int priority, astring &error_string)
{
- options_data *data = find_entry_data(opts, name, TRUE);
-
- /* if we don't find an entry, fail */
- if (data == NULL)
- return FALSE;
-
- /* set the callback */
- data->callback = callback;
- return TRUE;
-}
-
-
+ // reset the errors and the command
+ error_string.reset();
+ m_command.reset();
-/***************************************************************************
- OPTION DATA EXTRACTION
-***************************************************************************/
-
-/*-------------------------------------------------
- options_parse_command_line - parse a series
- of command line arguments
--------------------------------------------------*/
-
-int options_parse_command_line(core_options *opts, int argc, char **argv, int priority, int show_error)
-{
+ // iterate through arguments
int unadorned_index = 0;
- int arg;
- for (arg = 1; arg < argc; arg++)
+ for (int arg = 1; arg < argc; arg++)
{
- const char *optionname;
- options_data *data;
- int is_unadorned;
-
- /* determine the entry name to search for */
- is_unadorned = (argv[arg][0] != '-');
- if (!is_unadorned)
- optionname = &argv[arg][1];
- else
- optionname = OPTION_UNADORNED(unadorned_index);
-
- /* find our entry */
- data = find_entry_data(opts, optionname, TRUE);
- if (data == NULL) continue;
- if ((data->flags & OPTION_COMMAND) != 0) {
- // in case of any command force show error to TRUE
- show_error = TRUE;
- break;
+ // determine the entry name to search for
+ const char *curarg = argv[arg];
+ bool is_unadorned = (curarg[0] != '-');
+ const char *optionname = is_unadorned ? core_options::unadorned(unadorned_index++) : &curarg[1];
+
+ // find our entry; if not found, indicate invalid option
+ entry *curentry = m_entrymap.find(optionname);
+ if (curentry == NULL)
+ {
+ error_string.catprintf("Error: unknown option: %s\n", curarg);
+ return false;
}
- }
- /* loop over commands, looking for options */
- for (arg = 1; arg < argc; arg++)
- {
- const char *optionname, *newdata;
- options_data *data;
- int is_unadorned;
-
- /* determine the entry name to search for */
- is_unadorned = (argv[arg][0] != '-');
- if (!is_unadorned)
- optionname = &argv[arg][1];
- else
- optionname = OPTION_UNADORNED(unadorned_index);
-
- /* find our entry */
- data = find_entry_data(opts, optionname, TRUE);
- if (data == NULL)
+
+ // process commands first
+ if (curentry->type() == OPTION_COMMAND)
{
- if (!show_error) continue;
- message(opts, OPTMSG_ERROR, "Error: unknown option: %s\n", argv[arg]);
- return 1;
+ // can only have one command
+ if (m_command)
+ {
+ error_string.catprintf("Error: multiple commands specified -%s and %s\n", m_command.cstr(), curarg);
+ return false;
+ }
+ m_command = curentry->name();
+ continue;
}
- /* if unadorned, we have to bump the count (unless if the option repeats) */
- if (is_unadorned && !(data->flags & OPTION_REPEATS))
- unadorned_index++;
-
- /* get the data for this argument, special casing booleans */
- if ((data->flags & (OPTION_BOOLEAN | OPTION_COMMAND)) != 0)
- newdata = (strncmp(&argv[arg][1], "no", 2) == 0) ? "0" : "1";
- else if (argv[arg][0] != '-')
- newdata = argv[arg];
+ // get the data for this argument, special casing booleans
+ const char *newdata;
+ if (curentry->type() == OPTION_BOOLEAN)
+ newdata = (strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1";
+ else if (is_unadorned)
+ newdata = curarg;
else if (arg + 1 < argc)
newdata = argv[++arg];
else
{
- message(opts, OPTMSG_ERROR, "Error: option %s expected a parameter\n", argv[arg]);
- return 1;
+ error_string.catprintf("Error: option %s expected a parameter\n", curarg);
+ return false;
}
- /* if the option is deprecated or internal, don't process further */
- if ((data->flags & (OPTION_DEPRECATED | OPTION_INTERNAL)) != 0)
- continue;
-
- /* invoke callback, if present */
- if (data->callback != NULL)
- (*data->callback)(opts, newdata);
-
- /* allocate a new copy of data for this */
- update_data(opts, data, newdata, priority);
+ // set the new data
+ validate_and_set_data(*curentry, newdata, priority, error_string);
}
- return 0;
-}
-
-
-/*-------------------------------------------------
- options_force_option_callback - set option value
- and execute callback call
--------------------------------------------------*/
-
-int options_force_option_callback(core_options *opts, const char *optionname, const char *newval, int priority)
-{
- options_data *data = find_entry_data(opts, optionname, TRUE);
- if (data == NULL)
- {
- message(opts, OPTMSG_ERROR, "Error: unknown option: %s\n", optionname);
- return 1;
- }
-
- /* invoke callback, if present */
- if (data->callback != NULL)
- (*data->callback)(opts, newval);
-
- /* allocate a new copy of data for this */
- update_data(opts, data, newval, priority);
- return 0;
+ return true;
}
-/*-------------------------------------------------
- options_parse_ini_file - parse a series
- of entries in an INI file
--------------------------------------------------*/
+//-------------------------------------------------
+// parse_ini_file - parse a series of entries in
+// an INI file
+//-------------------------------------------------
-int options_parse_ini_file(core_options *opts, core_file *inifile, int priority, int ignoreprio)
+bool core_options::parse_ini_file(core_file &inifile, int priority, int ignore_priority, astring &error_string)
{
+ // loop over lines in the file
char buffer[4096];
-
- /* loop over data */
- while (core_fgets(buffer, ARRAY_LENGTH(buffer), inifile) != NULL)
+ while (core_fgets(buffer, ARRAY_LENGTH(buffer), &inifile) != NULL)
{
- char *optionname, *optiondata, *temp;
- options_data *data;
- int inquotes = FALSE;
-
- /* find the name */
+ // find the extent of the name
+ char *optionname;
for (optionname = buffer; *optionname != 0; optionname++)
if (!isspace((UINT8)*optionname))
break;
- /* skip comments */
+ // skip comments
if (*optionname == 0 || *optionname == '#')
continue;
- /* scan forward to find the first space */
+ // scan forward to find the first space
+ char *temp;
for (temp = optionname; *temp != 0; temp++)
if (isspace((UINT8)*temp))
break;
- /* if we hit the end early, print a warning and continue */
+ // if we hit the end early, print a warning and continue
if (*temp == 0)
{
- message(opts, OPTMSG_WARNING, "Warning: invalid line in INI: %s", buffer);
+ error_string.catprintf("Warning: invalid line in INI: %s", buffer);
continue;
}
- /* NULL-terminate */
+ // NULL-terminate
*temp++ = 0;
- optiondata = temp;
+ char *optiondata = temp;
- /* scan the data, stopping when we hit a comment */
+ // scan the data, stopping when we hit a comment
+ bool inquotes = false;
for (temp = optiondata; *temp != 0; temp++)
{
if (*temp == '"')
@@ -612,645 +436,319 @@ int options_parse_ini_file(core_options *opts, core_file *inifile, int priority,
}
*temp = 0;
- /* find our entry */
- data = find_entry_data(opts, optionname, FALSE);
- if (data == NULL)
+ // find our entry
+ entry *curentry = m_entrymap.find(optionname);
+ if (curentry == NULL)
{
- if (priority >= ignoreprio) message(opts, OPTMSG_WARNING, "Warning: unknown option in INI: %s\n", optionname);
+ if (priority >= ignore_priority)
+ error_string.catprintf("Warning: unknown option in INI: %s\n", optionname);
continue;
}
- if ((data->flags & (OPTION_DEPRECATED | OPTION_INTERNAL)) != 0)
- continue;
- /* allocate a new copy of data for this */
- update_data(opts, data, optiondata, priority);
+ // set the new data
+ validate_and_set_data(*curentry, optiondata, priority, error_string);
}
- return 0;
+ return true;
}
+//-------------------------------------------------
+// revert - revert options at or below a certain
+// priority back to their defaults
+//-------------------------------------------------
+
+void core_options::revert(int priority)
+{
+ // iterate over options and revert to defaults if below the given priority
+ for (entry *curentry = m_entrylist; curentry != NULL; curentry = curentry->next())
+ curentry->revert(priority);
+}
-/***************************************************************************
- OPTIONS OUTPUT
-***************************************************************************/
-/*-------------------------------------------------
- options_output_diff_ini_file - output the diff
- of the current state from a base state to an
- INI file
--------------------------------------------------*/
+//-------------------------------------------------
+// output_ini - output the options in INI format,
+// only outputting entries that different from
+// the optional diff
+//-------------------------------------------------
-void options_output_diff_ini_file(core_options *opts, core_options *baseopts, core_file *inifile)
+const char *core_options::output_ini(astring &buffer, const core_options *diff)
{
- options_data *data;
- const char *last_header = NULL;
- const char *name;
- const char *value;
- options_data *basedata;
+ // INI files are complete, so always start with a blank buffer
+ buffer.reset();
- /* loop over all items */
- for (data = opts->datalist; data != NULL; data = data->next)
+ // loop over all items
+ const char *last_header = NULL;
+ for (entry *curentry = m_entrylist; curentry != NULL; curentry = curentry->next())
{
- /* header: record description */
- if ((data->flags & OPTION_HEADER) != 0)
- last_header = data->description;
+ // header: record description
+ if (curentry->is_header())
+ last_header = curentry->description();
- /* otherwise, output entries for all non-deprecated and non-command items (if not in baseopts) */
- else if ((data->flags & (OPTION_DEPRECATED | OPTION_INTERNAL | OPTION_COMMAND)) == 0)
+ // otherwise, output entries for all non-command items
+ else if (!curentry->is_command())
{
- /* get name and data of this value */
- name = astring_c(data->links[0].name);
- value = astring_c(data->data);
-
- /* look up counterpart in baseopts, if baseopts is specified */
- basedata = (baseopts != NULL) ? find_entry_data(baseopts, name, FALSE) : NULL;
-
- /* is our data different, or not in baseopts? */
- if ((basedata == NULL) || (strcmp(value, astring_c(basedata->data)) != 0))
+ // look up counterpart in diff, if diff is specified
+ const char *name = curentry->name();
+ const char *value = curentry->value();
+ if (diff == NULL || strcmp(value, diff->value(name)) != 0)
{
- /* output header, if we have one */
+ // output header, if we have one
if (last_header != NULL)
{
- core_fprintf(inifile, "\n#\n# %s\n#\n", last_header);
+ buffer.catprintf("\n#\n# %s\n#\n", last_header);
last_header = NULL;
}
- /* and finally output the data */
+ // and finally output the data
if (strchr(value, ' ') != NULL)
- core_fprintf(inifile, "%-25s \"%s\"\n", name, value);
+ buffer.catprintf("%-25s \"%s\"\n", name, value);
else
- core_fprintf(inifile, "%-25s %s\n", name, value);
+ buffer.catprintf("%-25s %s\n", name, value);
}
}
}
+ return buffer;
}
-/*-------------------------------------------------
- options_output_ini_file - output the current
- state to an INI file
--------------------------------------------------*/
-
-void options_output_ini_file(core_options *opts, core_file *inifile)
-{
- options_output_diff_ini_file(opts, NULL, inifile);
-}
-
-
-/*-------------------------------------------------
- options_output_ini_file - output the current
- state to an INI file
--------------------------------------------------*/
-
-void options_output_ini_stdfile(core_options *opts, FILE *inifile)
-{
- options_data *data;
-
- /* loop over all items */
- for (data = opts->datalist; data != NULL; data = data->next)
- {
- /* header: just print */
- if ((data->flags & OPTION_HEADER) != 0)
- fprintf(inifile, "\n#\n# %s\n#\n", data->description);
-
- /* otherwise, output entries for all non-deprecated and non-command items */
- else if ((data->flags & (OPTION_DEPRECATED | OPTION_INTERNAL | OPTION_COMMAND)) == 0)
- {
- if (astring_chr(data->data, 0, ' ') != -1)
- fprintf(inifile, "%-25s \"%s\"\n", astring_c(data->links[0].name), astring_c(data->data));
- else
- fprintf(inifile, "%-25s %s\n", astring_c(data->links[0].name), astring_c(data->data));
- }
- }
-}
-
-
-/*-------------------------------------------------
- options_output_help - output option help to
- a file
--------------------------------------------------*/
+//-------------------------------------------------
+// output_help - output option help to a string
+//-------------------------------------------------
-void options_output_help(core_options *opts, void (*output)(const char *))
+const char *core_options::output_help(astring &buffer)
{
- options_data *data;
-
- /* loop over all items */
- for (data = opts->datalist; data != NULL; data = data->next)
+ // start empty
+ buffer.reset();
+
+ // loop over all items
+ for (entry *curentry = m_entrylist; curentry != NULL; curentry = curentry->next())
{
- /* header: just print */
- if ((data->flags & OPTION_HEADER) != 0)
- output_printf(output, "\n#\n# %s\n#\n", data->description);
+ // header: just print
+ if (curentry->is_header())
+ buffer.catprintf("\n#\n# %s\n#\n", curentry->description());
- /* otherwise, output entries for all non-deprecated items */
- else if ((data->flags & (OPTION_DEPRECATED | OPTION_INTERNAL)) == 0 && data->description != NULL)
- output_printf(output, "-%-20s%s\n", astring_c(data->links[0].name), data->description);
+ // otherwise, output entries for all non-deprecated items
+ else if (curentry->description() != NULL)
+ buffer.catprintf("-%-20s%s\n", curentry->name(), curentry->description());
}
+ return buffer;
}
+//-------------------------------------------------
+// value - return the raw option value
+//-------------------------------------------------
-/***************************************************************************
- OPTIONS READING
-***************************************************************************/
-
-/*-------------------------------------------------
- options_get_string - return data formatted
- as a string
--------------------------------------------------*/
-
-const char *options_get_string(core_options *opts, const char *name)
+const char *core_options::value(const char *name) const
{
- options_data *data = find_entry_data(opts, name, FALSE);
- const char *value = "";
-
- /* error if not found */
- if (data == NULL)
- message(opts, OPTMSG_ERROR, "Unexpected option %s queried\n", name);
-
- /* copy if non-NULL */
- else
- value = astring_c(data->data);
-
- return value;
+ entry *curentry = m_entrymap.find(name);
+ return (curentry != NULL) ? curentry->value() : "";
}
-/*-------------------------------------------------
- options_get_string_priority - return data
- formatted as a string if priority is equal
- or better
--------------------------------------------------*/
+//-------------------------------------------------
+// seqid - return the seqid for a given option
+//-------------------------------------------------
-const char *options_get_string_priority(core_options *opts, const char *name, int priority)
+UINT32 core_options::seqid(const char *name) const
{
- options_data *data = find_entry_data(opts, name, FALSE);
- const char *value = "";
-
- /* error if not found */
- if (data == NULL)
- message(opts, OPTMSG_ERROR, "Unexpected option %s queried\n", name);
-
- /* copy if non-NULL */
- else {
- if (data->priority!=OPTION_PRIORITY_DEFAULT) {
- if (priority > data->priority) return value;
- }
- value = astring_c(data->data);
- }
-
- return value;
+ entry *curentry = m_entrymap.find(name);
+ return (curentry != NULL) ? curentry->seqid() : 0;
}
-/*-------------------------------------------------
- options_get_bool - return data formatted as
- a boolean
--------------------------------------------------*/
+//-------------------------------------------------
+// set_value - set the raw option value
+//-------------------------------------------------
-int options_get_bool(core_options *opts, const char *name)
+bool core_options::set_value(const char *name, const char *value, int priority, astring &error_string)
{
- options_data *data = find_entry_data(opts, name, FALSE);
- int value = FALSE;
-
- /* error if not found */
- if (data == NULL)
- message(opts, OPTMSG_ERROR, "Unexpected boolean option %s queried\n", name);
-
- /* also error if we don't have a valid boolean value */
- else if (sscanf(astring_c(data->data), "%d", &value) != 1 || value < 0 || value > 1)
+ // find the entry first
+ entry *curentry = m_entrymap.find(name);
+ if (curentry == NULL)
{
- options_set_string(opts, name, astring_c(data->defdata), 0);
- sscanf(astring_c(data->data), "%d", &value);
- if (!data->error_reported)
- {
- message(opts, OPTMSG_ERROR, "Illegal boolean value for %s; reverting to %d\n", astring_c(data->links[0].name), value);
- data->error_reported = TRUE;
- }
+ error_string.catprintf("Attempted to set unknown option %s\n", name);
+ return false;
}
- return value;
+
+ // validate and set the item normally
+ return validate_and_set_data(*curentry, value, priority, error_string);
}
-
-/*-------------------------------------------------
- options_get_int - return data formatted as
- an integer
--------------------------------------------------*/
-
-int options_get_int(core_options *opts, const char *name)
+bool core_options::set_value(const char *name, int value, int priority, astring &error_string)
{
- options_data *data = find_entry_data(opts, name, FALSE);
- int value = 0;
-
- /* error if not found */
- if (data == NULL)
- message(opts, OPTMSG_ERROR, "Unexpected integer option %s queried\n", name);
-
- /* also error if we don't have a valid integer value */
- else if (sscanf(astring_c(data->data), "%d", &value) != 1)
- {
- options_set_string(opts, name, astring_c(data->defdata), 0);
- sscanf(astring_c(data->data), "%d", &value);
- if (!data->error_reported)
- {
- message(opts, OPTMSG_ERROR, "Illegal integer value for %s; reverting to %d\n", astring_c(data->links[0].name), value);
- data->error_reported = TRUE;
- }
- }
- return value;
+ astring tempstr;
+ tempstr.printf("%d", value);
+ return set_value(name, tempstr.cstr(), priority, error_string);
}
-
-/*-------------------------------------------------
- options_get_float - return data formatted as
- a float
--------------------------------------------------*/
-
-float options_get_float(core_options *opts, const char *name)
+bool core_options::set_value(const char *name, float value, int priority, astring &error_string)
{
- options_data *data = find_entry_data(opts, name, FALSE);
- float value = 0;
-
- /* error if not found */
- if (data == NULL)
- message(opts, OPTMSG_ERROR, "Unexpected float option %s queried\n", name);
-
- /* also error if we don't have a valid floating point value */
- else if (sscanf(astring_c(data->data), "%f", &value) != 1)
- {
- options_set_string(opts, name, astring_c(data->defdata), 0);
- sscanf(astring_c(data->data), "%f", &value);
- if (!data->error_reported)
- {
- message(opts, OPTMSG_ERROR, "Illegal float value for %s; reverting to %f\n", astring_c(data->links[0].name), (double)value);
- data->error_reported = TRUE;
- }
- }
- return value;
-}
-
-
-/*-------------------------------------------------
- options_get_seqid - return the seqid for an
- entry
--------------------------------------------------*/
-
-UINT32 options_get_seqid(core_options *opts, const char *name)
-{
- options_data *data = find_entry_data(opts, name, FALSE);
- return (data == NULL) ? 0 : data->seqid;
-}
-
-
-
-/***************************************************************************
- OPTIONS SETTING
-***************************************************************************/
-
-/*-------------------------------------------------
- options_set_string - set a string value
--------------------------------------------------*/
-
-void options_set_string(core_options *opts, const char *name, const char *value, int priority)
-{
- options_data *data = find_entry_data(opts, name, FALSE);
- update_data(opts, data, value, priority);
-}
-
-
-/*-------------------------------------------------
- options_set_bool - set a boolean value
--------------------------------------------------*/
-
-void options_set_bool(core_options *opts, const char *name, int value, int priority)
-{
- char temp[4];
- sprintf(temp, "%d", value ? 1 : 0);
- options_set_string(opts, name, temp, priority);
-}
-
-
-/*-------------------------------------------------
- options_set_int - set an integer value
--------------------------------------------------*/
-
-void options_set_int(core_options *opts, const char *name, int value, int priority)
-{
- char temp[20];
- sprintf(temp, "%d", value);
- options_set_string(opts, name, temp, priority);
+ astring tempstr;
+ tempstr.printf("%f", value);
+ return set_value(name, tempstr.cstr(), priority, error_string);
}
-/*-------------------------------------------------
- options_set_float - set a float value
--------------------------------------------------*/
+//-------------------------------------------------
+// reset - reset the options state, removing
+// everything
+//-------------------------------------------------
-void options_set_float(core_options *opts, const char *name, float value, int priority)
+void core_options::reset()
{
- char temp[100];
- sprintf(temp, "%f", value);
- options_set_string(opts, name, temp, priority);
-}
-
-
-
-/***************************************************************************
- OPTION DEFINITION QUERIES
-***************************************************************************/
-
-/*-------------------------------------------------
- options_enumerator_begin - retrieve the range of
- a float option
--------------------------------------------------*/
-
-options_enumerator *options_enumerator_begin(core_options *opts)
-{
- options_enumerator *enumerator;
-
- /* allocate memory for the enumerator */
- enumerator = (options_enumerator *)malloc(sizeof(*enumerator));
- if (enumerator == NULL)
- return NULL;
-
- /* start at the head of the list */
- enumerator->current = opts->datalist;
- return enumerator;
+ // remove all entries from the list
+ while (m_entrylist != NULL)
+ remove_entry(*m_entrylist);
+
+ // reset the map
+ m_entrymap.reset();
}
+//-------------------------------------------------
+// append_entry - append an entry to our list
+// and index it in the map
+//-------------------------------------------------
-/*-------------------------------------------------
- options_enumerator_next - returns the current
- option and advances the enumerator
--------------------------------------------------*/
-
-const char *options_enumerator_next(options_enumerator *enumerator)
+void core_options::append_entry(core_options::entry &newentry)
{
- astring *option_name = NULL;
-
- /* be sure to skip over false options */
- while (option_name == NULL && enumerator->current != NULL)
- {
- /* retrieve the current option name and advance the enumerator */
- option_name = enumerator->current->links[0].name;
- enumerator->current = enumerator->current->next;
- }
- return (option_name != NULL) ? astring_c(option_name) : NULL;
-}
-
-
+ // append to the list
+ *m_entrylist_tailptr = &newentry;
+ m_entrylist_tailptr = &newentry.m_next;
-/*-------------------------------------------------
- options_enumerator_free - disposes an options
- enumerator
--------------------------------------------------*/
-
-void options_enumerator_free(options_enumerator *enumerator)
-{
- free(enumerator);
+ // if we have names, add them to the map
+ for (int name = 0; name < ARRAY_LENGTH(newentry.m_name); name++)
+ if (newentry.m_name[name])
+ m_entrymap.add(newentry.m_name[name], &newentry);
}
-/*-------------------------------------------------
- options_get_range_type - determine the type
- of range for a particular option
--------------------------------------------------*/
+//-------------------------------------------------
+// remove_entry - remove an entry from our list
+// and map
+//-------------------------------------------------
-options_range_type options_get_range_type(core_options *opts, const char *name)
+void core_options::remove_entry(core_options::entry &delentry)
{
- options_data *data = find_entry_data(opts, name, FALSE);
- return data->range_type;
-}
-
-
-/*-------------------------------------------------
- options_get_range_int - retrieve the range of
- an integer option
--------------------------------------------------*/
+ // remove us from the list
+ entry *preventry = NULL;
+ for (entry *curentry = m_entrylist; curentry != NULL; curentry = curentry->next())
+ if (curentry == &delentry)
+ {
+ // update link from previous to us
+ if (preventry != NULL)
+ preventry->m_next = delentry.m_next;
+ else
+ m_entrylist = delentry.m_next;
+
+ // if we're the last item, update the next pointer
+ if (delentry.m_next == NULL)
+ {
+ if (preventry != NULL)
+ m_entrylist_tailptr = &preventry->m_next;
+ else
+ m_entrylist_tailptr = &m_entrylist;
+ }
-void options_get_range_int(core_options *opts, const char *name, int *minval, int *maxval)
-{
- options_data *data = find_entry_data(opts, name, FALSE);
- *minval = data->range_minimum.i;
- *maxval = data->range_maximum.i;
+ // remove all entries from the map
+ for (int name = 0; name < ARRAY_LENGTH(delentry.m_name); name++)
+ if (delentry.m_name[name])
+ m_entrymap.remove(delentry.m_name[name]);
+ break;
+ }
}
+//-------------------------------------------------
+// copyfrom - copy options from another set
+//-------------------------------------------------
-/*-------------------------------------------------
- options_get_range_float - retrieve the range of
- a float option
--------------------------------------------------*/
-
-void options_get_range_float(core_options *opts, const char *name, float *minval, float *maxval)
+void core_options::copyfrom(const core_options &src)
{
- options_data *data = find_entry_data(opts, name, FALSE);
- *minval = data->range_minimum.f;
- *maxval = data->range_maximum.f;
+ // reset ourselves first
+ reset();
+
+ // iterate through the src options and make our own
+ for (entry *curentry = src.m_entrylist; curentry != NULL; curentry = curentry->next())
+ append_entry(*new entry(*curentry));
}
+//-------------------------------------------------
+// validate_and_set_data - make sure the data is
+// of the appropriate type and within range,
+// then set it
+//-------------------------------------------------
-/***************************************************************************
- INTERNAL UTILITIES
-***************************************************************************/
-
-/*-------------------------------------------------
- find_entry_data - locate an entry whose name
- matches the given string
--------------------------------------------------*/
-
-static options_data *find_entry_data(core_options *opts, const char *string, int is_command_line)
+bool core_options::validate_and_set_data(core_options::entry &curentry, const char *newdata, int priority, astring &error_string)
{
- int hash_entry = hash_value(opts, string);
- options_hash_entry *link;
-
- /* scan all entries */
- for (link = opts->hashtable[hash_entry]; link != NULL; link = link->next)
- if (!(link->data->flags & OPTION_HEADER) && link->name != NULL && astring_cmpc(link->name, string) == 0)
- return link->data;
-
- /* haven't found it? if we are prefixed with "no", then try to search for that */
- if (is_command_line && string[0] == 'n' && string[1] == 'o')
+ // trim any whitespace
+ astring data(newdata);
+ data.trimspace();
+
+ // trim quotes
+ if (data.chr(0, '"') == 0 && data.rchr(0, '"') == data.len() - 1)
{
- options_data *data = find_entry_data(opts, &string[2], FALSE);
- if (data != NULL && (data->flags & OPTION_BOOLEAN))
- return data;
+ data.del(0, 1);
+ data.del(data.len() - 1, 1);
}
-
- /* didn't find it at all */
- return NULL;
-}
-
-
-/*-------------------------------------------------
- update_data - update the data value for a
- given entry
--------------------------------------------------*/
-
-static void update_data(core_options *opts, options_data *data, const char *newdata, int priority)
-{
- const char *dataend = newdata + strlen(newdata) - 1;
- const char *datastart = newdata;
- float f;
- int i;
-
- /* strip off leading/trailing spaces */
- while (isspace((UINT8)*datastart) && datastart <= dataend)
- datastart++;
- while (isspace((UINT8)*dataend) && datastart <= dataend)
- dataend--;
-
- /* strip off quotes */
- if (datastart != dataend && *datastart == '"' && *dataend == '"')
- datastart++, dataend--;
-
- /* check against range */
- switch (data->range_type)
+
+ // validate the type of data and optionally the range
+ float fval;
+ int ival;
+ switch (curentry.type())
{
- case OPTION_RANGE_NONE:
- /* do nothing */
+ // booleans must be 0 or 1
+ case OPTION_BOOLEAN:
+ if (sscanf(data, "%d", &ival) != 1 || ival < 0 || ival > 1)
+ {
+ error_string.catprintf("Illegal boolean value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.cstr(), curentry.value());
+ return false;
+ }
break;
-
- case OPTION_RANGE_INT:
- /* check against integer range */
- i = 0;
- if (sscanf(datastart, "%d", &i) != 1)
+
+ // integers must be integral
+ case OPTION_INTEGER:
+ if (sscanf(data, "%d", &ival) != 1)
{
- message(opts, OPTMSG_ERROR, "Illegal integer value for %s; keeping value of %s\n", astring_c(data->links[0].name), astring_c(data->data));
- data->error_reported = TRUE;
- return;
+ error_string.catprintf("Illegal integer value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.cstr(), curentry.value());
+ return false;
}
- if (i < data->range_minimum.i || i > data->range_maximum.i)
+ if (curentry.has_range() && (ival < atoi(curentry.minimum()) || ival > atoi(curentry.maximum())))
{
- message(opts, OPTMSG_ERROR, "Invalid %s value (must be between %i and %i); keeping value of %s\n",
- astring_c(data->links[0].name), data->range_minimum.i, data->range_maximum.i, astring_c(data->data));
- data->error_reported = TRUE;
- return;
+ error_string.catprintf("Out-of-range integer value for %s: \"%s\" (must be between %s and %s); reverting to %s\n", curentry.name(), data.cstr(), curentry.minimum(), curentry.maximum(), curentry.value());
+ return false;
}
break;
-
- case OPTION_RANGE_FLOAT:
- /* check against float range */
- f = 0;
- if (sscanf(datastart, "%f", &f) != 1)
+
+ // floating-point values must be numeric
+ case OPTION_FLOAT:
+ if (sscanf(data, "%f", &fval) != 1)
{
- message(opts, OPTMSG_ERROR, "Illegal float value for %s; keeping value of %s\n", astring_c(data->links[0].name), astring_c(data->data));
- data->error_reported = TRUE;
- return;
+ error_string.catprintf("Illegal float value for %s: \"%s\"; reverting to %s\n", curentry.name(), data.cstr(), curentry.value());
+ return false;
}
- if (f < data->range_minimum.f || f > data->range_maximum.f)
+ if (curentry.has_range() && (fval < atof(curentry.minimum()) || fval > atof(curentry.maximum())))
{
- message(opts, OPTMSG_ERROR, "Invalid %s value (must be between %f and %f); keeping value of %s\n",
- astring_c(data->links[0].name), data->range_minimum.f, data->range_maximum.f, astring_c(data->data));
- data->error_reported = TRUE;
- return;
+ error_string.catprintf("Out-of-range float value for %s: \"%s\" (must be between %s and %s); reverting to %s\n", curentry.name(), data.cstr(), curentry.minimum(), curentry.maximum(), curentry.value());
+ return false;
}
break;
- }
-
- /* ignore if we don't have priority */
- if (priority < data->priority) {
- return;
- }
- /* allocate a copy of the data */
- astring_cpych(data->data, datastart, dataend + 1 - datastart);
- data->priority = priority;
-
- /* bump the seqid and clear the error reporting */
- data->seqid++;
- data->error_reported = FALSE;
-}
-
-
-/*-------------------------------------------------
- parse_option_name - read data from an option_entry
- name into an option_data structure
--------------------------------------------------*/
-
-static int parse_option_name(core_options *opts, const char *srcstring, options_data *data)
-{
- const char *start;
- const char *end = NULL;
- int curentry;
-
- /* start with the original string and loop over entries */
- start = srcstring;
- for (curentry = 0; curentry < ARRAY_LENGTH(data->links); curentry++)
- {
- /* find the end of this entry and copy the string */
- for (end = start; *end != 0 && *end != ';' && *end != '('; end++)
- ;
- data->links[curentry].name = astring_dupch(start, end - start);
-
- /* if we hit the end of the source, stop */
- if (*end != ';')
+
+ // strings can be anything
+ case OPTION_STRING:
break;
- start = end + 1;
- }
-
- /* have we found a range? */
- if (end != NULL && *end == '(')
- {
- if (sscanf(end, "(%d-%d)", &data->range_minimum.i, &data->range_maximum.i) == 2)
- data->range_type = OPTION_RANGE_INT;
- else if (sscanf(end, "(%f-%f)", &data->range_minimum.f, &data->range_maximum.f) == 2)
- data->range_type = OPTION_RANGE_FLOAT;
- }
- return curentry;
-}
-
-
-/*-------------------------------------------------
- message - outputs a message to a listener
--------------------------------------------------*/
-
-static void message(core_options *opts, options_message msgtype, const char *format, ...)
-{
- char buf[1024];
- va_list argptr;
-
- /* output a message if there is a non-NULL handler for it */
- if (opts->output[msgtype] != NULL)
- {
- va_start(argptr, format);
- vsprintf(buf, format, argptr);
- va_end(argptr);
-
- (*opts->output[msgtype])(buf);
+
+ // anything else is invalid
+ case OPTION_INVALID:
+ case OPTION_HEADER:
+ default:
+ error_string.catprintf("Attempted to set invalid option %s\n", curentry.name());
+ return false;
}
-}
-
-
-/*-------------------------------------------------
- hash_value - computes the hash value for a string
--------------------------------------------------*/
-
-static UINT32 hash_value(core_options *opts, const char *str)
-{
- UINT32 hash = 5381;
- int c;
-
- while ((c = *str++) != 0)
- hash = ((hash << 5) + hash) + c;
-
- return hash % ARRAY_LENGTH(opts->hashtable);
-}
-
-
-/*-------------------------------------------------
- output_printf - outputs an arbitrary message
- to a callback
--------------------------------------------------*/
-
-static void output_printf(void (*output)(const char *s), const char *format, ...)
-{
- char buf[1024];
- va_list argptr;
-
- va_start(argptr, format);
- vsprintf(buf, format, argptr);
- va_end(argptr);
-
- output(buf);
+
+ // set the data
+ curentry.set_value(data, priority);
+ return true;
}