diff --git a/src/devices/imagedev/diablo.cpp b/src/devices/imagedev/diablo.cpp index 413d4c6b9b5..238e0dd5a89 100644 --- a/src/devices/imagedev/diablo.cpp +++ b/src/devices/imagedev/diablo.cpp @@ -10,7 +10,7 @@ #include "diablo.h" -static OPTION_GUIDE_START(dsk_option_guide) +OPTION_GUIDE_START(dsk_option_guide) OPTION_INT('C', "cylinders", "Cylinders") OPTION_INT('H', "heads", "Heads") OPTION_INT('S', "sectors", "Sectors") @@ -62,7 +62,7 @@ void diablo_image_device::device_config_complete() update_names(); } -const option_guide *diablo_image_device::create_option_guide() const +const util::option_guide &diablo_image_device::create_option_guide() const { return dsk_option_guide; } diff --git a/src/devices/imagedev/diablo.h b/src/devices/imagedev/diablo.h index 8ab2ac1addc..f4d99532345 100644 --- a/src/devices/imagedev/diablo.h +++ b/src/devices/imagedev/diablo.h @@ -45,7 +45,7 @@ public: virtual bool is_reset_on_load() const override { return 0; } virtual const char *image_interface() const override { return m_interface; } virtual const char *file_extensions() const override { return "chd,dsk"; } - virtual const option_guide *create_option_guide() const override; + virtual const util::option_guide &create_option_guide() const override; // specific implementation hard_disk_file *get_hard_disk_file() { return m_hard_disk_handle; } diff --git a/src/devices/imagedev/flopdrv.h b/src/devices/imagedev/flopdrv.h index 34e54100364..c362d62aa9e 100644 --- a/src/devices/imagedev/flopdrv.h +++ b/src/devices/imagedev/flopdrv.h @@ -114,7 +114,7 @@ public: virtual bool is_reset_on_load() const override { return 0; } virtual const char *image_interface() const override; virtual const char *file_extensions() const override { return m_extension_list; } - virtual const option_guide *create_option_guide() const override { return floppy_option_guide; } + virtual const util::option_guide &create_option_guide() const override { return floppy_option_guide; } floppy_image_legacy *flopimg_get_image(); void floppy_drive_set_geometry(floppy_type_t type); diff --git a/src/devices/imagedev/harddriv.cpp b/src/devices/imagedev/harddriv.cpp index 3e7cb789552..8070a1d9afe 100644 --- a/src/devices/imagedev/harddriv.cpp +++ b/src/devices/imagedev/harddriv.cpp @@ -19,7 +19,7 @@ #include "harddriv.h" -static OPTION_GUIDE_START(hd_option_guide) +OPTION_GUIDE_START(hd_option_guide) OPTION_INT('C', "cylinders", "Cylinders") OPTION_INT('H', "heads", "Heads") OPTION_INT('S', "sectors", "Sectors") @@ -85,7 +85,7 @@ void harddisk_image_device::device_config_complete() update_names(); } -const option_guide *harddisk_image_device::create_option_guide() const +const util::option_guide &harddisk_image_device::create_option_guide() const { return hd_option_guide; } diff --git a/src/devices/imagedev/harddriv.h b/src/devices/imagedev/harddriv.h index d2ce6aeaef9..2438262690c 100644 --- a/src/devices/imagedev/harddriv.h +++ b/src/devices/imagedev/harddriv.h @@ -47,7 +47,7 @@ public: virtual bool is_reset_on_load() const override { return 0; } virtual const char *image_interface() const override { return m_interface; } virtual const char *file_extensions() const override { return "chd,hd"; } - virtual const option_guide *create_option_guide() const override; + virtual const util::option_guide &create_option_guide() const override; // specific implementation hard_disk_file *get_hard_disk_file() { return m_hard_disk_handle; } diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index c1cc72aaef4..223ee296327 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -1263,6 +1263,18 @@ void device_image_interface::unload() } +//------------------------------------------------- +// create_option_guide +//------------------------------------------------- + +OPTION_GUIDE_START(null_option_guide) +OPTION_GUIDE_END + +const util::option_guide &device_image_interface::create_option_guide() const +{ + return null_option_guide; +} + //------------------------------------------------- // update_names - update brief and instance names //------------------------------------------------- diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 80cf0a0ce91..f36b5e7c835 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -161,11 +161,11 @@ public: virtual bool support_command_line_image_creation() const; virtual const char *image_interface() const { return nullptr; } virtual const char *file_extensions() const = 0; - virtual const option_guide *create_option_guide() const { return nullptr; } + virtual const util::option_guide &create_option_guide() const; const image_device_format *device_get_indexed_creatable_format(int index) const { if (index < m_formatlist.size()) return m_formatlist.at(index).get(); else return nullptr; } const image_device_format *device_get_named_creatable_format(const std::string &format_name); - const option_guide *device_get_creation_option_guide() const { return create_option_guide(); } + const util::option_guide &device_get_creation_option_guide() const { return create_option_guide(); } const char *error(); void seterror(image_error_t err, const char *message); diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp index 48240973d3a..82f8d28ca93 100644 --- a/src/lib/formats/flopimg.cpp +++ b/src/lib/formats/flopimg.cpp @@ -204,35 +204,9 @@ floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const std: -static floperr_t option_to_floppy_error(util::option_resolution::error oerr) -{ - floperr_t err; - switch(oerr) { - case util::option_resolution::error::SUCCESS: - err = FLOPPY_ERROR_SUCCESS; - break; - case util::option_resolution::error::OUTOFMEMORY: - err = FLOPPY_ERROR_OUTOFMEMORY; - break; - case util::option_resolution::error::PARAMOUTOFRANGE: - case util::option_resolution::error::PARAMNOTSPECIFIED: - case util::option_resolution::error::PARAMNOTFOUND: - case util::option_resolution::error::PARAMALREADYSPECIFIED: - case util::option_resolution::error::BADPARAM: - case util::option_resolution::error::SYNTAX: - default: - err = FLOPPY_ERROR_INTERNAL; - break; - }; - return err; -} - - - floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy) { floppy_image_legacy *floppy = nullptr; - util::option_resolution::error oerr; floperr_t err; int heads, tracks, h, t; std::unique_ptr alloc_resolution; @@ -250,26 +224,16 @@ floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct Flo /* if this format expects creation parameters and none were specified, create some */ if (!parameters && format->param_guidelines) { - alloc_resolution = std::make_unique(floppy_option_guide, format->param_guidelines); - if (!alloc_resolution) + try { alloc_resolution = std::make_unique(floppy_option_guide); } + catch (...) { err = FLOPPY_ERROR_OUTOFMEMORY; goto done; } + alloc_resolution->set_specification(format->param_guidelines); parameters = alloc_resolution.get(); } - /* finish the parameters, if specified */ - if (parameters) - { - oerr = parameters->finish(); - if (oerr != util::option_resolution::error::SUCCESS) - { - err = option_to_floppy_error(oerr); - goto done; - } - } - /* call the format constructor */ err = format->construct(floppy, format, parameters); if (err) @@ -690,17 +654,19 @@ floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, /* create a dummy resolution; if no parameters were specified */ if (!parameters) { - alloc_resolution = std::make_unique(floppy_option_guide, floppy->floppy_option->param_guidelines); - if (!alloc_resolution) + try + { + alloc_resolution = std::make_unique(floppy_option_guide); + } + catch (...) + { return FLOPPY_ERROR_OUTOFMEMORY; + } + alloc_resolution->set_specification(floppy->floppy_option->param_guidelines); parameters = alloc_resolution.get(); } - auto oerr = parameters->finish(); - if (oerr != util::option_resolution::error::SUCCESS) - return option_to_floppy_error(oerr); - err = format->format_track(floppy, head, track, parameters); if (err) return err; diff --git a/src/lib/util/opresolv.cpp b/src/lib/util/opresolv.cpp index baf66580d26..74595d43abd 100644 --- a/src/lib/util/opresolv.cpp +++ b/src/lib/util/opresolv.cpp @@ -2,7 +2,7 @@ // copyright-holders:Nathan Woods /**************************************************************************** - opresolv.h + opresolv.cpp Extensible ranged option resolution handling @@ -19,226 +19,51 @@ namespace util { + /*************************************************************************** - option_resolution + option_resolution ***************************************************************************/ // ------------------------------------------------- -// entry::int_value +// ctor // ------------------------------------------------- -int option_resolution::entry::int_value() const +option_resolution::option_resolution(const option_guide &guide) { - return atoi(value.c_str()); -} + // reserve space for entries + m_entries.reserve(guide.end() - guide.begin()); - -// ------------------------------------------------- -// entry::set_int_value -// ------------------------------------------------- - -void option_resolution::entry::set_int_value(int i) -{ - value = string_format("%d", i); -} - - -// ------------------------------------------------- -// resolve_single_param -// ------------------------------------------------- - -option_resolution::error option_resolution::resolve_single_param(const char *specification, option_resolution::entry *param_value, - struct range *range, size_t range_count) -{ - int FLAG_IN_RANGE = 0x01; - int FLAG_IN_DEFAULT = 0x02; - int FLAG_DEFAULT_SPECIFIED = 0x04; - int FLAG_HALF_RANGE = 0x08; - - int last_value = 0; - int value = 0; - int flags = 0; - const char *s = specification; - - while(*s && !isalpha(*s)) + // initialize each of the entries; can't use foreach because we need to scan the + // ENUM_VALUE entries + for (auto iter = guide.begin(); iter != guide.end(); iter++) { - if (*s == '-') - { - /* range specifier */ - if (flags & (FLAG_IN_RANGE|FLAG_IN_DEFAULT)) - { - return error::SYNTAX; - } - flags |= FLAG_IN_RANGE; - s++; + // create the entry + m_entries.emplace_back(*iter); + entry &entry(m_entries.back()); - if (range) - { - range->max = -1; - if ((flags & FLAG_HALF_RANGE) == 0) - { - range->min = -1; - flags |= FLAG_HALF_RANGE; - } - } - } - else if (*s == '[') + // if this is an enumeration, identify the values + if (iter->type() == option_guide::entry::option_type::ENUM_BEGIN) { - /* begin default value */ - if (flags & (FLAG_IN_DEFAULT|FLAG_DEFAULT_SPECIFIED)) - { - return error::SYNTAX; - } - flags |= FLAG_IN_DEFAULT; - s++; - } - else if (*s == ']') - { - /* end default value */ - if ((flags & FLAG_IN_DEFAULT) == 0) - { - return error::SYNTAX; - } - flags &= ~FLAG_IN_DEFAULT; - flags |= FLAG_DEFAULT_SPECIFIED; - s++; + // enum values begin after the ENUM_BEGIN + auto enum_value_begin = iter + 1; + auto enum_value_end = enum_value_begin; - if (param_value && param_value->int_value() == -1) - param_value->set_int_value(value); - } - else if (*s == '/') - { - /* value separator */ - if (flags & (FLAG_IN_DEFAULT|FLAG_IN_RANGE)) + // and identify all entries of type ENUM_VALUE + while (enum_value_end != guide.end() && enum_value_end->type() == option_guide::entry::option_type::ENUM_VALUE) { - return error::SYNTAX; - } - s++; - - /* if we are spitting out ranges, complete the range */ - if (range && (flags & FLAG_HALF_RANGE)) - { - range++; - flags &= ~FLAG_HALF_RANGE; - if (--range_count == 0) - range = nullptr; - } - } - else if (*s == ';') - { - /* basic separator */ - s++; - } - else if (isdigit(*s)) - { - /* numeric value */ - last_value = value; - value = 0; - do - { - value *= 10; - value += *s - '0'; - s++; - } - while(isdigit(*s)); - - if (range) - { - if ((flags & FLAG_HALF_RANGE) == 0) - { - range->min = value; - flags |= FLAG_HALF_RANGE; - } - range->max = value; + iter++; + enum_value_end++; } - // if we have a value; check to see if it is out of range - if (param_value && (param_value->int_value() != -1) && (param_value->int_value() != value)) - { - if ((last_value < param_value->int_value()) && (param_value->int_value() < value)) - { - if ((flags & FLAG_IN_RANGE) == 0) - return error::PARAMOUTOFRANGE; - } - } - flags &= ~FLAG_IN_RANGE; - } - else - { - return error::SYNTAX; + // set the range + entry.set_enum_value_range(enum_value_begin, enum_value_end); } } - - // we can't have zero length guidelines strings - if (s == specification) - { - return error::SYNTAX; - } - - return error::SUCCESS; } // ------------------------------------------------- -// lookup_in_specification -// ------------------------------------------------- - -const char *option_resolution::lookup_in_specification(const char *specification, const option_guide *option) -{ - const char *s; - s = strchr(specification, option->parameter); - return s ? s + 1 : nullptr; -} - - -// ------------------------------------------------- -// ctor -// ------------------------------------------------- - -option_resolution::option_resolution(const option_guide *guide, const char *specification) -{ - const option_guide *guide_entry; - int option_count; - int opt = -1; - - assert(guide); - - // first count the number of options specified in the guide - option_count = count_options(guide, specification); - - // set up the entries list - m_specification = specification; - m_entries.resize(option_count); - - // initialize each of the entries - opt = 0; - guide_entry = guide; - while(guide_entry->option_type != OPTIONTYPE_END) - { - switch(guide_entry->option_type) - { - case OPTIONTYPE_INT: - case OPTIONTYPE_ENUM_BEGIN: - case OPTIONTYPE_STRING: - if (lookup_in_specification(specification, guide_entry)) - m_entries[opt++].guide_entry = guide_entry; - break; - - case OPTIONTYPE_ENUM_VALUE: - break; - - default: - assert(false && "Invalid option type"); - break; - } - guide_entry++; - } - assert(opt == option_count); -} - - -// ------------------------------------------------- -// dtor +// dtor // ------------------------------------------------- option_resolution::~option_resolution() @@ -247,318 +72,412 @@ option_resolution::~option_resolution() // ------------------------------------------------- -// add_param +// lookup_in_specification // ------------------------------------------------- -option_resolution::error option_resolution::add_param(const char *param, const std::string &value) +const char *option_resolution::lookup_in_specification(const char *specification, const option_guide::entry &option) { - int i; - bool must_resolve; - error err; - const char *option_specification; - entry *entry = nullptr; - - for(auto &this_entry : m_entries) - { - if (!strcmp(param, this_entry.guide_entry->identifier)) - { - entry = &this_entry; - break; - } - } - if (entry == nullptr) - return error::PARAMNOTFOUND; - - if (entry->state != entry_state::UNSPECIFIED) - return error::PARAMALREADYSPECIFIED; - - switch(entry->guide_entry->option_type) { - case OPTIONTYPE_INT: - entry->set_int_value(atoi(value.c_str())); - entry->state = entry_state::SPECIFIED; - must_resolve = true; - break; - - case OPTIONTYPE_STRING: - entry->value = value; - entry->state = entry_state::SPECIFIED; - must_resolve = false; - break; - - case OPTIONTYPE_ENUM_BEGIN: - for (i = 1; entry->guide_entry[i].option_type == OPTIONTYPE_ENUM_VALUE; i++) - { - if (!core_stricmp(value.c_str(), entry->guide_entry[i].identifier)) - { - entry->set_int_value(entry->guide_entry[i].parameter); - entry->state = entry_state::SPECIFIED; - break; - } - } - if (entry->state != entry_state::SPECIFIED) - return error::BADPARAM; - - must_resolve = true; - break; - - default: - assert(0); - return error::INTERNAL; - } - - // do a resolution step if necessary - if (must_resolve) - { - option_specification = lookup_in_specification(m_specification, entry->guide_entry); - err = resolve_single_param(option_specification, entry, nullptr, 0); - if (err != error::SUCCESS) - return err; - - // did we not get a real value? - if (entry->int_value() < 0) - return error::PARAMNOTSPECIFIED; - } - - return error::SUCCESS; + const char *s; + s = strchr(specification, option.parameter()); + return s ? s + 1 : nullptr; } // ------------------------------------------------- -// finish +// set_specification - sets the option specification +// and mutates values accordingly // ------------------------------------------------- -option_resolution::error option_resolution::finish() -{ - const char *option_specification; - error err; - - for (auto &entry : m_entries) - { - if (entry.state == entry_state::UNSPECIFIED) - { - switch(entry.guide_entry->option_type) { - case OPTIONTYPE_INT: - case OPTIONTYPE_ENUM_BEGIN: - option_specification = lookup_in_specification(m_specification, entry.guide_entry); - assert(option_specification); - entry.set_int_value(-1); - err = resolve_single_param(option_specification, &entry, nullptr, 0); - if (err != error::SUCCESS) - return err; - break; - - case OPTIONTYPE_STRING: - entry.value = ""; - break; - - default: - assert(FALSE); - return error::INTERNAL; - } - entry.state = entry_state::SPECIFIED; - } - } - return error::SUCCESS; -} - - -// ------------------------------------------------- -// lookup_entry -// ------------------------------------------------- - -const option_resolution::entry *option_resolution::lookup_entry(int option_char) const +void option_resolution::set_specification(const std::string &specification) { for (auto &entry : m_entries) { - switch(entry.guide_entry->option_type) { - case OPTIONTYPE_INT: - case OPTIONTYPE_STRING: - case OPTIONTYPE_ENUM_BEGIN: - if (entry.guide_entry->parameter == option_char) - return &entry; - break; + // find this entry's info in the specification + auto entry_specification = lookup_in_specification(specification.c_str(), entry.m_guide_entry); - default: - assert(FALSE); - return nullptr; + // parse this entry's specification (e.g. - set up ranges and defaults) + entry.parse_specification(entry_specification); + + // is this a range typed that needs to be defaulted for the first time? + if (entry.is_pertinent() && entry.is_ranged() && entry.value().empty()) + { + entry.set_value(entry.default_value()); } } - return nullptr; } // ------------------------------------------------- -// lookup_int +// find // ------------------------------------------------- -int option_resolution::lookup_int(int option_char) const +option_resolution::entry *option_resolution::find(int parameter) { - auto entry = lookup_entry(option_char); - return entry ? entry->int_value() : -1; + auto iter = std::find_if( + m_entries.begin(), + m_entries.end(), + [parameter](const entry &e) { return e.parameter() == parameter; }); + + return iter != m_entries.end() + ? &*iter + : nullptr; } // ------------------------------------------------- -// lookup_string +// find // ------------------------------------------------- -const char *option_resolution::lookup_string(int option_char) const +option_resolution::entry *option_resolution::find(const std::string &identifier) { - auto entry = lookup_entry(option_char); - return entry ? entry->value.c_str() : nullptr; + auto iter = std::find_if( + m_entries.begin(), + m_entries.end(), + [&](const entry &e) { return !strcmp(e.identifier(), identifier.c_str()); }); + + return iter != m_entries.end() + ? &*iter + : nullptr; } // ------------------------------------------------- -// find_option +// lookup_int // ------------------------------------------------- -const option_guide *option_resolution::find_option(int option_char) const +int option_resolution::lookup_int(int parameter) { - auto entry = lookup_entry(option_char); - return entry ? entry->guide_entry : nullptr; + auto entry = find(parameter); + assert(entry != nullptr); + return entry->value_int(); } // ------------------------------------------------- -// index_option +// lookup_string // ------------------------------------------------- -const option_guide *option_resolution::index_option(int indx) const +const std::string &option_resolution::lookup_string(int parameter) { - if ((indx < 0) || (indx >= m_entries.size())) - return nullptr; - return m_entries[indx].guide_entry; + auto entry = find(parameter); + assert(entry != nullptr); + return entry->value(); } // ------------------------------------------------- -// count_options -// ------------------------------------------------- - -size_t option_resolution::count_options(const option_guide *guide, const char *specification) -{ - size_t option_count = 0; - - while(guide->option_type != OPTIONTYPE_END) - { - switch(guide->option_type) { - case OPTIONTYPE_INT: - case OPTIONTYPE_STRING: - case OPTIONTYPE_ENUM_BEGIN: - if (lookup_in_specification(specification, guide)) - option_count++; - break; - case OPTIONTYPE_ENUM_VALUE: - break; - default: - assert(FALSE); - return 0; - } - guide++; - } - return option_count; -} - - -// ------------------------------------------------- -// list_ranges -// ------------------------------------------------- - -option_resolution::error option_resolution::list_ranges(const char *specification, int option_char, range *range, size_t range_count) -{ - assert(range_count > 0); - - // clear out range - memset(range, -1, sizeof(*range) * range_count); - range_count--; - - specification = strchr(specification, option_char); - if (!specification) - { - return error::SYNTAX; - } - - return resolve_single_param(specification + 1, nullptr, range, range_count); -} - - -// ------------------------------------------------- -// get_default +// error_string // ------------------------------------------------- option_resolution::error option_resolution::get_default(const char *specification, int option_char, int *val) { - assert(val); - - // clear out default - *val = -1; - - specification = strchr(specification, option_char); - if (!specification) - { - return error::SYNTAX; - } - - entry ent; - auto err = resolve_single_param(specification + 1, &ent, nullptr, 0); - *val = ent.int_value(); - return err; + // NYI + return error::INTERNAL; } // ------------------------------------------------- -// list_ranges -// ------------------------------------------------- - -option_resolution::error option_resolution::is_valid_value(const char *specification, int option_char, int val) -{ - option_resolution::error err; - range ranges[256]; - int i; - - err = list_ranges(specification, option_char, ranges, ARRAY_LENGTH(ranges)); - if (err != error::SUCCESS) - return err; - - for (i = 0; (ranges[i].min >= 0) && (ranges[i].max >= 0); i++) - { - if ((ranges[i].min <= val) && (ranges[i].max >= val)) - return error::SUCCESS; - } - return error::PARAMOUTOFRANGE; -} - - -// ------------------------------------------------- -// contains -// ------------------------------------------------- - -bool option_resolution::contains(const char *specification, int option_char) -{ - return strchr(specification, option_char) != nullptr; -} - - -// ------------------------------------------------- -// error_string +// error_string // ------------------------------------------------- const char *option_resolution::error_string(option_resolution::error err) { switch (err) { - case error::SUCCESS: return "The operation completed successfully"; - case error::OUTOFMEMORY: return "Out of memory"; - case error::PARAMOUTOFRANGE: return "Parameter out of range"; - case error::PARAMNOTSPECIFIED: return "Parameter not specified"; - case error::PARAMNOTFOUND: return "Unknown parameter"; - case error::PARAMALREADYSPECIFIED: return "Parameter specified multiple times"; - case error::BADPARAM: return "Invalid parameter"; - case error::SYNTAX: return "Syntax error"; - case error::INTERNAL: return "Internal error"; + case error::SUCCESS: return "The operation completed successfully"; + case error::OUTOFMEMORY: return "Out of memory"; + case error::PARAMOUTOFRANGE: return "Parameter out of range"; + case error::PARAMNOTSPECIFIED: return "Parameter not specified"; + case error::PARAMNOTFOUND: return "Unknown parameter"; + case error::PARAMALREADYSPECIFIED: return "Parameter specified multiple times"; + case error::BADPARAM: return "Invalid parameter"; + case error::SYNTAX: return "Syntax error"; + case error::INTERNAL: return "Internal error"; } return nullptr; } -} // namespace util + +// ------------------------------------------------- +// entry::ctor +// ------------------------------------------------- + +option_resolution::entry::entry(const option_guide::entry &guide_entry) + : m_guide_entry(guide_entry), m_is_pertinent(false) +{ +} + + +// ------------------------------------------------- +// entry::set_enum_value_range +// ------------------------------------------------- + +void option_resolution::entry::set_enum_value_range(const option_guide::entry *begin, const option_guide::entry *end) +{ + m_enum_value_begin = begin; + m_enum_value_end = end; +} + + +// ------------------------------------------------- +// entry::parse_specification +// ------------------------------------------------- + +void option_resolution::entry::parse_specification(const char *specification) +{ + // clear some items out + m_ranges.clear(); + m_default_value.clear(); + + // is this even pertinent? + m_is_pertinent = (specification != nullptr) && (specification[0] != '\0'); + if (m_is_pertinent) + { + int value = 0; + bool in_range = false; + bool in_default = false; + bool default_specified = false; + bool half_range = false; + size_t pos = 0; + + m_ranges.emplace_back(); + + while (specification[pos] && !isalpha(specification[pos])) + { + if (specification[pos] == '-') + { + // range specifier + assert(!in_range && !in_default && "Syntax error in specification"); + + in_range = true; + pos++; + + m_ranges.back().max = -1; + if (!half_range) + { + m_ranges.back().min = -1; + half_range = true; + } + } + else if (specification[pos] == '[') + { + // begin default value + assert(!in_default && !default_specified && "Syntax error in specification"); + + in_default = true; + pos++; + } + else if (specification[pos] == ']') + { + // end default value + assert(in_default && "Syntax error in specification"); + + in_default = false; + default_specified = true; + pos++; + + m_default_value = numeric_value(value); + } + else if (specification[pos] == '/') + { + // value separator + assert(!in_default && !in_range && "Syntax error in specification"); + pos++; + + // if we are spitting out ranges, complete the range + if (half_range) + { + m_ranges.emplace_back(); + half_range = false; + } + } + else if (specification[pos] == ';') + { + // basic separator + pos++; + } + else if (isdigit(specification[pos])) + { + // numeric value */ + value = 0; + do + { + value *= 10; + value += specification[pos++] - '0'; + } while (isdigit(specification[pos])); + + if (!half_range) + { + m_ranges.back().min = value; + half_range = true; + } + m_ranges.back().max = value; + in_range = false; + } + else + { + // invalid character - abort because we cannot recover from this syntax error + throw false; + } + } + + // we can't have zero length guidelines strings + assert(pos > 0); + + // appease compiler for scenarios where assert() has been preprocessed out + (void)(in_range && in_default && default_specified); + } +} + + +// ------------------------------------------------- +// entry::numeric_value +// ------------------------------------------------- + +std::string option_resolution::entry::numeric_value(int value) +{ + return string_format("%d", value); +} + + +// ------------------------------------------------- +// entry::value +// ------------------------------------------------- + +const std::string &option_resolution::entry::value() const +{ + static std::string empty_string; + return is_pertinent() ? m_value : empty_string; +} + + +// ------------------------------------------------- +// entry::value_int +// ------------------------------------------------- + +int option_resolution::entry::value_int() const +{ + return is_pertinent() ? atoi(m_value.c_str()) : -1; +} + + +// ------------------------------------------------- +// entry::set_value +// ------------------------------------------------- + +bool option_resolution::entry::set_value(const std::string &value) +{ + // reject the value if this isn't pertinent + if (!is_pertinent()) + return false; + + // if this is ranged, check against the ranges + if (is_ranged() && find_in_ranges(std::atoi(value.c_str())) == m_ranges.cend()) + return false; + + // looks good! change the value + m_value = value; + return true; +} + + +// ------------------------------------------------- +// entry::can_bump_lower +// ------------------------------------------------- + +bool option_resolution::entry::can_bump_lower() const +{ + return !m_ranges.empty() + && value_int() > m_ranges.front().min; +} + + +// ------------------------------------------------- +// entry::can_bump_higher +// ------------------------------------------------- + +bool option_resolution::entry::can_bump_higher() const +{ + return !m_ranges.empty() + && value_int() < m_ranges.back().max; +} + + +// ------------------------------------------------- +// entry::bump_lower +// ------------------------------------------------- + +bool option_resolution::entry::bump_lower() +{ + auto old_value = value_int(); + auto current_range = find_in_ranges(old_value); + assert(current_range != m_ranges.end()); + + int new_value; + if (old_value > current_range->min) + { + // decrement within current range + new_value = old_value - 1; + } + else if (current_range != m_ranges.begin()) + { + // go to the top of the previous range + new_value = (current_range - 1)->max; + } + else + { + // at the minimum; don't bump + new_value = old_value; + } + + set_value(new_value); + return new_value != old_value; +} + + +// ------------------------------------------------- +// entry::bump_higher +// ------------------------------------------------- + +bool option_resolution::entry::bump_higher() +{ + auto old_value = value_int(); + auto current_range = find_in_ranges(old_value); + assert(current_range != m_ranges.end()); + + int new_value; + if (old_value < current_range->max) + { + // increment within current range + new_value = old_value + 1; + } + else if (current_range != (m_ranges.end() - 1)) + { + // go to the bottom of the next range + new_value = (current_range + 1)->min; + } + else + { + // at the minimum; don't bump + new_value = old_value; + } + + set_value(new_value); + return new_value != old_value; +} + + +// ------------------------------------------------- +// entry::find_in_ranges +// ------------------------------------------------- + +option_resolution::entry::rangelist::const_iterator option_resolution::entry::find_in_ranges(int value) const +{ + return std::find_if( + m_ranges.begin(), + m_ranges.end(), + [&](const auto &r) { return r.min <= value && value <= r.max; }); +} + + +} // namespace util \ No newline at end of file diff --git a/src/lib/util/opresolv.h b/src/lib/util/opresolv.h index 097d6e303ac..3d919d26d59 100644 --- a/src/lib/util/opresolv.h +++ b/src/lib/util/opresolv.h @@ -50,45 +50,116 @@ // TYPE DEFINITIONS //************************************************************************** -enum option_type -{ - OPTIONTYPE_END, - OPTIONTYPE_INT, - OPTIONTYPE_STRING, - OPTIONTYPE_ENUM_BEGIN, - OPTIONTYPE_ENUM_VALUE -}; - -struct option_guide -{ - enum option_type option_type; - int parameter; - const char *identifier; - const char *display_name; -}; - -#define OPTION_GUIDE_START(option_guide_) \ - const option_guide option_guide_[] = \ - { -#define OPTION_GUIDE_END \ - { OPTIONTYPE_END } \ - }; -#define OPTION_GUIDE_EXTERN(option_guide_) \ - extern const option_guide option_guide_[] -#define OPTION_INT(option_char, identifier, display_name) \ - { OPTIONTYPE_INT, (option_char), (identifier), (display_name) }, -#define OPTION_STRING(option_char, identifier, display_name) \ - { OPTIONTYPE_STRING, (option_char), (identifier), (display_name) }, -#define OPTION_ENUM_START(option_char, identifier, display_name) \ - { OPTIONTYPE_ENUM_BEGIN, (option_char), (identifier), (display_name) }, -#define OPTION_ENUM(value, identifier, display_name) \ - { OPTIONTYPE_ENUM_VALUE, (value), (identifier), (display_name) }, +#define OPTION_GUIDE_START(option_guide_) \ + namespace option_guide_impl_##option_guide_ \ + { \ + static const util::option_guide &get(); \ + }; \ + const util::option_guide &option_guide_ = option_guide_impl_##option_guide_::get(); \ + namespace option_guide_impl_##option_guide_ \ + { \ + static const auto actual = util::make_option_guide(0 +#define OPTION_GUIDE_END \ + ); \ + static const util::option_guide &get() { return actual; } \ + }; +#define OPTION_GUIDE_EXTERN(option_guide_) \ + extern const util::option_guide &option_guide_ +#define OPTION_INT(option_char, identifier, display_name) \ + ,util::option_guide::entry(util::option_guide::entry::option_type::INT, (option_char), (identifier), (display_name)) +#define OPTION_STRING(option_char, identifier, display_name) \ + ,util::option_guide::entry(util::option_guide::entry::option_type::STRING, (option_char), (identifier), (display_name)) +#define OPTION_ENUM_START(option_char, identifier, display_name) \ + ,util::option_guide::entry(util::option_guide::entry::option_type::ENUM_BEGIN, (option_char), (identifier), (display_name)) +#define OPTION_ENUM(value, identifier, display_name) \ + ,util::option_guide::entry(util::option_guide::entry::option_type::ENUM_VALUE, (value), (identifier), (display_name)) #define OPTION_ENUM_END namespace util { + +// ======================> option_guide + +class option_guide +{ +public: + class entry + { + public: + enum class option_type + { + INVALID, + INT, + STRING, + ENUM_BEGIN, + ENUM_VALUE + }; + + constexpr entry() + : m_type(option_type::INVALID), m_parameter(0), m_identifier(nullptr), m_display_name(nullptr) + { + } + + constexpr entry(option_type type, int parameter = 0, const char *identifier = nullptr, const char *display_name = nullptr) + : m_type(type), m_parameter(parameter), m_identifier(identifier), m_display_name(display_name) + { + } + + // accessors + const option_type type() const { return m_type; } + int parameter() const { return m_parameter; } + const char *identifier() const { return m_identifier; } + const char *display_name() const { return m_display_name; } + + private: + option_type m_type; + int m_parameter; + const char *m_identifier; + const char *m_display_name; + }; + + // methods + const entry *begin() const { return m_begin; } + const entry *end() const { return m_end; } + +protected: + option_guide(const entry *begin, const entry *end) + : m_begin(begin), m_end(end) + { + } + + +private: + const entry *m_begin; + const entry *m_end; +}; + +// ======================> option_guide_impl + +template +class option_guide_impl : protected std::array, public option_guide +{ +public: + template + option_guide_impl(T &&... elems) + : std::array({ std::forward(elems)... }) + , option_guide(&(*this)[0], &(*this)[0] + Count) + { + } +}; + +template +option_guide_impl make_option_guide(int dummy, T &&... elems) +{ + return option_guide_impl(std::forward(elems)...); +} + + +// ======================> option_resolution + class option_resolution { public: + // TODO - audit unused parameters enum class error { SUCCESS, @@ -102,61 +173,98 @@ public: INTERNAL }; + template struct range { - int min, max; + range() { min = -1; max = -1; } + T min, max; }; - option_resolution(const option_guide *guide, const char *specification); + // class to represent specific entry + class entry + { + friend class option_resolution; + + public: + typedef std::vector > rangelist; + + // ctor + entry(const option_guide::entry &guide_entry); + + // returns true if this entry is subject to range constraints + bool is_ranged() const { return !m_ranges.empty(); } + + // accessors + bool is_pertinent() const { return m_is_pertinent; } + const std::string &value() const; + int value_int() const; + const std::string &default_value() const { return m_default_value; } + const rangelist &ranges() const { return m_ranges; } + const option_guide::entry *enum_value_begin() const { return m_enum_value_begin; } + const option_guide::entry *enum_value_end() const { return m_enum_value_end; } + + // accessors for guide data + option_guide::entry::option_type option_type() const { return m_guide_entry.type(); } + const char *display_name() const { return m_guide_entry.display_name(); } + const char *identifier() const { return m_guide_entry.identifier(); } + int parameter() const { return m_guide_entry.parameter(); } + + + // mutators + bool set_value(const std::string &value); + bool set_value(int value) { return set_value(numeric_value(value)); } + + // higher level operations + bool can_bump_lower() const; + bool can_bump_higher() const; + bool bump_lower(); + bool bump_higher(); + + private: + // references to the option guide + const option_guide::entry & m_guide_entry; + const option_guide::entry * m_enum_value_begin; + const option_guide::entry * m_enum_value_end; + + // runtime state + bool m_is_pertinent; + std::string m_value; + std::string m_default_value; + rangelist m_ranges; + + // methods + void parse_specification(const char *specification); + void set_enum_value_range(const option_guide::entry *begin, const option_guide::entry *end); + static std::string numeric_value(int value); + rangelist::const_iterator find_in_ranges(int value) const; + }; + + // ctor/dtor + option_resolution(const option_guide &guide); ~option_resolution(); - // processing options with option_resolution objects - error add_param(const char *param, const std::string &value); - error finish(); - int lookup_int(int option_char) const; - const char *lookup_string(int option_char) const; + // sets a specification + void set_specification(const std::string &specification); - // accessors - const char *specification() const { return m_specification; } - const option_guide *find_option(int option_char) const; - const option_guide *index_option(int indx) const; - - // processing option guides - static size_t count_options(const option_guide *guide, const char *specification); - - // processing option specifications - static error list_ranges(const char *specification, int option_char, - range *range, size_t range_count); - static error get_default(const char *specification, int option_char, int *val); - static error is_valid_value(const char *specification, int option_char, int val); - static bool contains(const char *specification, int option_char); + // entry lookup - note that we're not exposing m_entries directly because we don't really + // have a way of making the list be immutable but the members be mutable at the same time + std::vector::iterator entries_begin() { return m_entries.begin(); } + std::vector::iterator entries_end() { return m_entries.end(); } + entry *find(int parameter); + entry *find(const std::string &identifier); + int lookup_int(int parameter); + const std::string &lookup_string(int parameter); // misc static const char *error_string(error err); + static error get_default(const char *specification, int option_char, int *val); private: - enum class entry_state - { - UNSPECIFIED, - SPECIFIED - }; - - struct entry - { - const option_guide *guide_entry; - entry_state state; - std::string value; - - int int_value() const; - void set_int_value(int i); - }; - - const char *m_specification; std::vector m_entries; - static error resolve_single_param(const char *specification, entry *param_value, - struct range *range, size_t range_count); - static const char *lookup_in_specification(const char *specification, const option_guide *option); + error set_parameter(std::vector::iterator iter, const std::string &value); + + static const char *lookup_in_specification(const char *specification, const option_guide::entry &option); const entry *lookup_entry(int option_char) const; }; diff --git a/src/mame/machine/psion_pack.cpp b/src/mame/machine/psion_pack.cpp index d95124372ad..5f9550dde73 100644 --- a/src/mame/machine/psion_pack.cpp +++ b/src/mame/machine/psion_pack.cpp @@ -40,7 +40,7 @@ #define OPK_HEAD_SIZE 6 -static OPTION_GUIDE_START( datapack_option_guide ) +OPTION_GUIDE_START( datapack_option_guide ) OPTION_INT('S', "size", "Datapack size" ) OPTION_INT('R', "ram", "RAM/EPROM" ) OPTION_INT('P', "paged", "Paged" ) @@ -105,7 +105,7 @@ void datapack_device::device_config_complete() // option_guide for create new image //------------------------------------------------- -const option_guide *datapack_device::create_option_guide() const +const util::option_guide &datapack_device::create_option_guide() const { return datapack_option_guide; } diff --git a/src/mame/machine/psion_pack.h b/src/mame/machine/psion_pack.h index f0358844e93..b5335420f41 100644 --- a/src/mame/machine/psion_pack.h +++ b/src/mame/machine/psion_pack.h @@ -40,7 +40,7 @@ public: virtual bool is_reset_on_load() const override { return 0; } virtual const char *image_interface() const override { return "psion_pack"; } virtual const char *file_extensions() const override { return "opk"; } - virtual const option_guide *create_option_guide() const override; + virtual const util::option_guide &create_option_guide() const override; // specific implementation UINT8 data_r(); diff --git a/src/tools/imgtool/iflopimg.cpp b/src/tools/imgtool/iflopimg.cpp index aebd63212f5..f9857fe3db3 100644 --- a/src/tools/imgtool/iflopimg.cpp +++ b/src/tools/imgtool/iflopimg.cpp @@ -269,7 +269,7 @@ static void imgtool_floppy_get_info(const imgtool_class *imgclass, UINT32 state, case IMGTOOLINFO_PTR_OPEN: info->open = imgtool_floppy_open; break; case IMGTOOLINFO_PTR_CREATE: info->create = imgtool_floppy_create; break; case IMGTOOLINFO_PTR_CLOSE: info->close = imgtool_floppy_close; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = format->param_guidelines ? floppy_option_guide : nullptr; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = format->param_guidelines ? &floppy_option_guide : nullptr; break; case IMGTOOLINFO_PTR_GET_SECTOR_SIZE: info->get_sector_size = imgtool_floppy_get_sector_size; break; case IMGTOOLINFO_PTR_READ_SECTOR: info->read_sector = imgtool_floppy_read_sector; break; case IMGTOOLINFO_PTR_WRITE_SECTOR: info->write_sector = imgtool_floppy_write_sector; break; diff --git a/src/tools/imgtool/imghd.cpp b/src/tools/imgtool/imghd.cpp index 79a60a5d010..89f543d8185 100644 --- a/src/tools/imgtool/imghd.cpp +++ b/src/tools/imgtool/imghd.cpp @@ -226,7 +226,7 @@ enum mess_hd_createopts_seclen = 'F' }; -static OPTION_GUIDE_START( mess_hd_create_optionguide ) +OPTION_GUIDE_START( mess_hd_create_optionguide ) OPTION_INT(mess_hd_createopts_blocksize, "blocksize", "Sectors Per Block" ) OPTION_INT(mess_hd_createopts_cylinders, "cylinders", "Cylinders" ) OPTION_INT(mess_hd_createopts_heads, "heads", "Heads" ) @@ -247,7 +247,7 @@ void hd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinfo case IMGTOOLINFO_PTR_CREATE: info->create = mess_hd_image_create; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = mess_hd_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &mess_hd_create_optionguide; break; case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), mess_hd_create_optionspecs); break; } } diff --git a/src/tools/imgtool/imgtool.cpp b/src/tools/imgtool/imgtool.cpp index 95efbc9ab18..8039146f22e 100644 --- a/src/tools/imgtool/imgtool.cpp +++ b/src/tools/imgtool/imgtool.cpp @@ -2,7 +2,7 @@ // copyright-holders:Nathan Woods /*************************************************************************** - imgtool.c + imgtool.cpp Core code for Imgtool @@ -66,7 +66,7 @@ struct imgtool_partition imgtoolerr_t (*suggest_transfer)(imgtool_partition *partition, const char *path, imgtool_transfer_suggestion *suggestions, size_t suggestions_length); imgtoolerr_t (*get_chain) (imgtool_partition *partition, const char *path, imgtool_chainent *chain, size_t chain_size); - const option_guide *writefile_optguide; + const util::option_guide *writefile_optguide; const char *writefile_optspec; }; @@ -800,7 +800,7 @@ imgtoolerr_t imgtool_partition_open(imgtool_image *image, int partition_index, i p->get_iconinfo = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_iconinfo *)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_ICON_INFO); p->suggest_transfer = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_transfer_suggestion *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_SUGGEST_TRANSFER); p->get_chain = (imgtoolerr_t (*)(imgtool_partition *, const char *, imgtool_chainent *, size_t)) imgtool_get_info_fct(&imgclass, IMGTOOLINFO_PTR_GET_CHAIN); - p->writefile_optguide = (const option_guide *) imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); + p->writefile_optguide = (const util::option_guide *) imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); p->writefile_optspec = pool_strdup_allow_null(p->pool, (char*)imgtool_get_info_ptr(&imgclass, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC)); /* mask out if writing is untested */ @@ -928,10 +928,8 @@ void imgtool_partition_get_attribute_name(imgtool_partition *partition, UINT32 a int imgtool_validitychecks(void) { int error = 0; - int val; imgtoolerr_t err = (imgtoolerr_t)IMGTOOLERR_SUCCESS; const imgtool_module *module = nullptr; - const option_guide *guide_entry; imgtool_module_features features; int created_library = FALSE; @@ -1017,44 +1015,12 @@ int imgtool_validitychecks(void) if (module->createimage_optguide && module->createimage_optspec) { - guide_entry = module->createimage_optguide; - while (guide_entry->option_type != OPTIONTYPE_END) - { - if (util::option_resolution::contains(module->createimage_optspec, guide_entry->parameter)) - { - switch (guide_entry->option_type) - { - case OPTIONTYPE_INT: - case OPTIONTYPE_ENUM_BEGIN: - err = (imgtoolerr_t)util::option_resolution::get_default(module->createimage_optspec, - guide_entry->parameter, &val); - if (err) - goto done; - break; - - default: - break; - } - if (!guide_entry->identifier) - { - printf("imgtool module %s creation option %d has null identifier\n", - module->name, (int) (guide_entry - module->createimage_optguide)); - error = 1; - } - if (!guide_entry->display_name) - { - printf("imgtool module %s creation option %d has null display_name\n", - module->name, (int) (guide_entry - module->createimage_optguide)); - error = 1; - } - } - guide_entry++; - } + auto resolution = std::make_unique(*module->createimage_optguide); + resolution->set_specification(module->createimage_optspec); } } } -done: if (created_library) imgtool_exit(); if (err) @@ -1218,12 +1184,14 @@ imgtoolerr_t imgtool_image_create(const imgtool_module *module, const char *fnam /* allocate dummy options if necessary */ if (!opts && module->createimage_optguide) { - try { alloc_resolution.reset(new util::option_resolution(module->createimage_optguide, module->createimage_optspec)); } + try { alloc_resolution.reset(new util::option_resolution(*module->createimage_optguide)); } catch (...) { return (imgtoolerr_t)IMGTOOLERR_OUTOFMEMORY; } + + if (module->createimage_optspec) + alloc_resolution->set_specification(module->createimage_optspec); + opts = alloc_resolution.get(); } - if (opts) - opts->finish(); return internal_open(module, fname, OSD_FOPEN_RW_CREATE, opts, image); } @@ -2000,16 +1968,16 @@ imgtoolerr_t imgtool_partition_write_file(imgtool_partition *partition, const ch /* allocate dummy options if necessary */ if (!opts && partition->writefile_optguide) { - try { alloc_resolution.reset(new util::option_resolution(partition->writefile_optguide, partition->writefile_optspec)); } + try { alloc_resolution.reset(new util::option_resolution(*partition->writefile_optguide)); } catch (...) { err = IMGTOOLERR_OUTOFMEMORY; goto done; } + if (partition->writefile_optspec) + alloc_resolution->set_specification(partition->writefile_optspec); opts = alloc_resolution.get(); } - if (opts) - opts->finish(); /* if free_space is implemented; do a quick check to see if space is available */ if (partition->free_space) diff --git a/src/tools/imgtool/library.cpp b/src/tools/imgtool/library.cpp index 491e1c8e1c8..fd6d6843e45 100644 --- a/src/tools/imgtool/library.cpp +++ b/src/tools/imgtool/library.cpp @@ -102,7 +102,7 @@ static void imgtool_library_add_class(imgtool_library *library, const imgtool_cl module->write_block = (imgtoolerr_t (*)(imgtool_image *, const void *, UINT64)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_WRITE_BLOCK); module->list_partitions = (imgtoolerr_t (*)(imgtool_image *, imgtool_partition_info *, size_t)) imgtool_get_info_fct(imgclass, IMGTOOLINFO_PTR_LIST_PARTITIONS); module->block_size = imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_BLOCK_SIZE); - module->createimage_optguide = (const option_guide *) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE); + module->createimage_optguide = (const util::option_guide *) imgtool_get_info_ptr(imgclass, IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE); module->createimage_optspec = imgtool_library_strdup_allow_null(library, (const char*)imgtool_get_info_ptr(imgclass, IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC)); module->image_extra_bytes += imgtool_get_info_int(imgclass, IMGTOOLINFO_INT_IMAGE_EXTRA_BYTES); } diff --git a/src/tools/imgtool/library.h b/src/tools/imgtool/library.h index 9371f019bfc..63a6a08a5fb 100644 --- a/src/tools/imgtool/library.h +++ b/src/tools/imgtool/library.h @@ -291,8 +291,8 @@ union imgtoolinfo int (*approve_filename_char)(unicode_char ch); int (*make_class)(int index, imgtool_class *imgclass); - const option_guide *createimage_optguide; - const option_guide *writefile_optguide; + const util::option_guide *createimage_optguide; + const util::option_guide *writefile_optguide; }; @@ -369,7 +369,7 @@ struct imgtool_module UINT32 block_size; - const option_guide *createimage_optguide; + const util::option_guide *createimage_optguide; const char *createimage_optspec; const void *extra; diff --git a/src/tools/imgtool/main.cpp b/src/tools/imgtool/main.cpp index 1faac27ee22..a57e6d8154a 100644 --- a/src/tools/imgtool/main.cpp +++ b/src/tools/imgtool/main.cpp @@ -2,7 +2,7 @@ // copyright-holders:Nathan Woods /*************************************************************************** - main.c + main.cpp Imgtool command line front end @@ -17,6 +17,8 @@ #include "imgtool.h" #include "main.h" #include "modules.h" +#include "strformat.h" + /* ---------------------------------------------------------------------- */ static void writeusage(FILE *f, int write_word_usage, const struct command *c, char *argv[]) @@ -40,7 +42,6 @@ static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed, char *s; char *name = nullptr; char *value = nullptr; - util::option_resolution::error oerr; static char buf[256]; if (filter) @@ -97,9 +98,7 @@ static int parse_options(int argc, char *argv[], int minunnamed, int maxunnamed, if (i < minunnamed) goto error; /* Too few unnamed */ - oerr = resolution->add_param(name, value); - if (oerr != util::option_resolution::error::SUCCESS) - goto opterror; + resolution->find(name)->set_value(value); } } } @@ -113,10 +112,6 @@ optionalreadyspecified: fprintf(stderr, "Cannot specify multiple %ss\n", name); return -1; -opterror: - fprintf(stderr, "%s: %s\n", name, util::option_resolution::error_string(oerr)); - return -1; - error: fprintf(stderr, "%s: Unrecognized option\n", argv[i]); return -1; @@ -328,7 +323,7 @@ static int cmd_put(const struct command *c, int argc, char *argv[]) char **filename_list; int filename_count; int partition_index = 0; - const option_guide *writefile_optguide; + const util::option_guide *writefile_optguide; const char *writefile_optspec; module = imgtool_find_module(argv[0]); @@ -353,17 +348,18 @@ static int cmd_put(const struct command *c, int argc, char *argv[]) if (err) goto done; - writefile_optguide = (const option_guide *) imgtool_partition_get_info_ptr(partition, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); + writefile_optguide = (const util::option_guide *) imgtool_partition_get_info_ptr(partition, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); writefile_optspec = (const char *)imgtool_partition_get_info_ptr(partition, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC); if (writefile_optguide && writefile_optspec) { - try { resolution.reset(new util::option_resolution(writefile_optguide, writefile_optspec)); } + try { resolution.reset(new util::option_resolution(*writefile_optguide)); } catch (...) { err = IMGTOOLERR_OUTOFMEMORY; goto done; } + resolution->set_specification(writefile_optspec); } } @@ -592,12 +588,13 @@ static int cmd_create(const struct command *c, int argc, char *argv[]) if (module->createimage_optguide && module->createimage_optspec) { - try { resolution.reset(new util::option_resolution(module->createimage_optguide, module->createimage_optspec)); } + try { resolution.reset(new util::option_resolution(*module->createimage_optguide)); } catch (...) { err = IMGTOOLERR_OUTOFMEMORY; goto error; } + resolution->set_specification(module->createimage_optspec); } unnamedargs = parse_options(argc, argv, 2, 3, resolution.get(), nullptr, nullptr); @@ -742,77 +739,63 @@ static int cmd_listfilters(const struct command *c, int argc, char *argv[]) return 0; } -static void listoptions(const option_guide *opt_guide, const char *opt_spec) +static void listoptions(const util::option_guide &opt_guide, const char *opt_spec) { - char opt_name[32]; - const char *opt_desc; - util::option_resolution::range range[32]; - char range_buffer[512]; - char buf[32]; - int i; - - assert(opt_guide); + util::option_resolution resolution(opt_guide); + resolution.set_specification(opt_spec); fprintf(stdout, "Option Allowed values Description\n"); fprintf(stdout, "---------------- ------------------------------ -----------\n"); - while(opt_guide->option_type != OPTIONTYPE_END) + std::stringstream description_buffer; + for (auto iter = resolution.entries_begin(); iter != resolution.entries_end(); iter++) { - range_buffer[0] = 0; - snprintf(opt_name, ARRAY_LENGTH(opt_name), "--%s", opt_guide->identifier); - opt_desc = opt_guide->display_name; + const util::option_resolution::entry &entry = *iter; - /* is this option relevant? */ - if (!strchr(opt_spec, opt_guide->parameter)) - { - opt_guide++; + std::string opt_name = string_format("--%s", entry.identifier()); + const char *opt_desc = entry.display_name(); + + // is this option relevant? + if (!strchr(opt_spec, entry.parameter())) continue; - } - switch(opt_guide->option_type) { - case OPTIONTYPE_INT: - util::option_resolution::list_ranges(opt_spec, opt_guide->parameter, - range, ARRAY_LENGTH(range)); - - for (i = 0; range[i].max >= 0; i++) + switch (entry.option_type()) + { + case util::option_guide::entry::option_type::INT: + for (const auto &range : entry.ranges()) { - if (range[i].min == range[i].max) - snprintf(buf, ARRAY_LENGTH(buf), "%i", range[i].min); + if (!description_buffer.str().empty()) + description_buffer << "/"; + + if (range.min == range.max) + util::stream_format(description_buffer, "%d", range.min); else - snprintf(buf, ARRAY_LENGTH(buf), "%i-%i", range[i].min, range[i].max); - - if (i > 0) - strncatz(range_buffer, "/", sizeof(range_buffer)); - strncatz(range_buffer, buf, sizeof(range_buffer)); + util::stream_format(description_buffer, "%d-%d", range.min, range.max); } break; - case OPTIONTYPE_ENUM_BEGIN: - i = 0; - while(opt_guide[1].option_type == OPTIONTYPE_ENUM_VALUE) + case util::option_guide::entry::option_type::ENUM_BEGIN: + for (auto enum_value = entry.enum_value_begin(); enum_value != entry.enum_value_end(); enum_value++) { - if (i > 0) - strncatz(range_buffer, "/", sizeof(range_buffer)); - strncatz(range_buffer, opt_guide[1].identifier, sizeof(range_buffer)); - - opt_guide++; - i++; + if (!description_buffer.str().empty()) + description_buffer << '/'; + description_buffer << enum_value->identifier(); } break; - case OPTIONTYPE_STRING: - snprintf(range_buffer, sizeof(range_buffer), "(string)"); + case util::option_guide::entry::option_type::STRING: + description_buffer << "(string)"; break; + default: assert(0); break; } fprintf(stdout, "%16s %-30s %s\n", - opt_name, - range_buffer, + opt_name.c_str(), + description_buffer.str().c_str(), opt_desc); - opt_guide++; } } @@ -821,7 +804,7 @@ static void listoptions(const option_guide *opt_guide, const char *opt_spec) static int cmd_listdriveroptions(const struct command *c, int argc, char *argv[]) { const imgtool_module *mod; - const option_guide *opt_guide; + const util::option_guide *opt_guide; const char *opt_spec; mod = imgtool_find_module(argv[0]); @@ -834,12 +817,12 @@ static int cmd_listdriveroptions(const struct command *c, int argc, char *argv[] fprintf(stdout, "Driver specific options for module '%s':\n\n", argv[0]); /* list write options */ - opt_guide = (const option_guide *) imgtool_get_info_ptr(&mod->imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); + opt_guide = (const util::option_guide *) imgtool_get_info_ptr(&mod->imgclass, IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE); opt_spec = imgtool_get_info_string(&mod->imgclass, IMGTOOLINFO_STR_WRITEFILE_OPTSPEC); if (opt_guide) { fprintf(stdout, "Image specific file options (usable on the 'put' command):\n\n"); - listoptions(opt_guide, opt_spec); + listoptions(*opt_guide, opt_spec); puts("\n"); } else @@ -852,7 +835,7 @@ static int cmd_listdriveroptions(const struct command *c, int argc, char *argv[] if (opt_guide) { fprintf(stdout, "Image specific creation options (usable on the 'create' command):\n\n"); - listoptions(opt_guide, mod->createimage_optspec); + listoptions(*opt_guide, mod->createimage_optspec); puts("\n"); } else @@ -940,7 +923,7 @@ int CLIB_DECL main(int argc, char *argv[]) } /* Usage */ - fprintf(stderr, "imgtool - Generic image manipulation tool for use with MESS\n\n"); + fprintf(stderr, "imgtool - Generic image manipulation tool for use with MAME\n\n"); for (i = 0; i < ARRAY_LENGTH(cmds); i++) { writeusage(stdout, (i == 0), &cmds[i], argv); diff --git a/src/tools/imgtool/modules/amiga.cpp b/src/tools/imgtool/modules/amiga.cpp index fa53e24dfad..d506b97cf07 100644 --- a/src/tools/imgtool/modules/amiga.cpp +++ b/src/tools/imgtool/modules/amiga.cpp @@ -2193,7 +2193,7 @@ static imgtoolerr_t amiga_image_writefile(imgtool_partition *partition, const ch static imgtoolerr_t amiga_image_create(imgtool_image *img, imgtool_stream *stream, util::option_resolution *opts) { amiga_floppy *f = (amiga_floppy *) imgtool_image_extra_bytes(img); - const char *dskname = opts->lookup_string('N'); + const std::string &dskname = opts->lookup_string('N'); imgtoolerr_t ret; UINT8 buffer[BSIZE]; root_block root; @@ -2252,10 +2252,10 @@ static imgtoolerr_t amiga_image_create(imgtool_image *img, imgtool_stream *strea amiga_setup_time(now, &root.c); /* volume name */ - if (dskname) + if (!dskname.empty()) { - root.name_len = strlen(dskname); - memcpy(&root.diskname, dskname, root.name_len); + root.name_len = dskname.length(); + memcpy(&root.diskname, dskname.c_str(), root.name_len); } else { @@ -2342,7 +2342,7 @@ static imgtoolerr_t amiga_image_suggesttransfer(imgtool_partition *partition, co *****************************************************************************/ -static OPTION_GUIDE_START(amiga_createimage_optionguide) +OPTION_GUIDE_START(amiga_createimage_optionguide) OPTION_STRING( 'N', "name", "Volume name" ) OPTION_ENUM_START( 'S', "density", "Density" ) OPTION_ENUM( 0, "dd", "Double Density" ) @@ -2406,6 +2406,6 @@ void amiga_floppy_get_info(const imgtool_class *imgclass, UINT32 state, union im case IMGTOOLINFO_PTR_SET_ATTRS: info->set_attrs = amiga_image_setattrs; break; case IMGTOOLINFO_PTR_GET_ICON_INFO: info->get_iconinfo = amiga_image_geticoninfo; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = amiga_image_suggesttransfer; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = amiga_createimage_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &amiga_createimage_optionguide; break; } } diff --git a/src/tools/imgtool/modules/bml3.cpp b/src/tools/imgtool/modules/bml3.cpp index c658b42ebf0..80048fc340f 100644 --- a/src/tools/imgtool/modules/bml3.cpp +++ b/src/tools/imgtool/modules/bml3.cpp @@ -882,7 +882,7 @@ static imgtoolerr_t bml3_diskimage_suggesttransfer(imgtool_partition *partition, Imgtool module declaration *********************************************************************/ -static OPTION_GUIDE_START( bml3_writefile_optionguide ) +OPTION_GUIDE_START( bml3_writefile_optionguide ) OPTION_ENUM_START( BML3_OPTIONS_FTYPE, "ftype", "File type" ) OPTION_ENUM( 0, "basic", "Basic" ) OPTION_ENUM( 1, "data", "Data" ) @@ -922,7 +922,7 @@ void bml3_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinf case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = bml3_diskimage_writefile; break; case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = bml3_diskimage_deletefile; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = bml3_diskimage_suggesttransfer; break; - case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = bml3_writefile_optionguide; break; + case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &bml3_writefile_optionguide; break; case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_default; break; } } diff --git a/src/tools/imgtool/modules/cybiko.cpp b/src/tools/imgtool/modules/cybiko.cpp index 649b3e9cab9..a90f9daa745 100644 --- a/src/tools/imgtool/modules/cybiko.cpp +++ b/src/tools/imgtool/modules/cybiko.cpp @@ -531,7 +531,7 @@ static imgtoolerr_t cybiko_image_delete_file( imgtool_partition *partition, cons return IMGTOOLERR_SUCCESS; } -static OPTION_GUIDE_START( cybiko_image_createimage_optguide ) +OPTION_GUIDE_START( cybiko_image_createimage_optguide ) OPTION_ENUM_START( 'F', "flash", "Flash Type" ) OPTION_ENUM( 0, "AT45DB041", "AT45DB041 (528 KByte)" ) OPTION_ENUM( 1, "AT45DB081", "AT45DB081 (1056 KByte)" ) @@ -564,7 +564,7 @@ void cybiko_get_info( const imgtool_class *imgclass, UINT32 state, union imgtool case IMGTOOLINFO_PTR_READ_FILE : info->read_file = cybiko_image_read_file; break; case IMGTOOLINFO_PTR_WRITE_FILE : info->write_file = cybiko_image_write_file; break; case IMGTOOLINFO_PTR_DELETE_FILE : info->delete_file = cybiko_image_delete_file; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = cybiko_image_createimage_optguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = &cybiko_image_createimage_optguide; break; // case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE : info->writefile_optguide = cybiko_image_writefile_optguide; break; // --- the following bits of info are returned as NULL-terminated strings --- case IMGTOOLINFO_STR_NAME : strcpy( info->s = imgtool_temp_str(), "cybiko"); break; diff --git a/src/tools/imgtool/modules/hp48.cpp b/src/tools/imgtool/modules/hp48.cpp index bfc193e9979..f73459c3bfd 100644 --- a/src/tools/imgtool/modules/hp48.cpp +++ b/src/tools/imgtool/modules/hp48.cpp @@ -136,7 +136,7 @@ static const char* hp48_prefix = "HPHP48-R"; -static OPTION_GUIDE_START( hp48_create_optionguide ) +OPTION_GUIDE_START( hp48_create_optionguide ) OPTION_INT('S', "size", "Size in KB" ) OPTION_GUIDE_END @@ -726,7 +726,7 @@ void hp48_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolinf case IMGTOOLINFO_STR_FILE_EXTENSIONS: strcpy(info->s = imgtool_temp_str(), "crd"); break; case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), hp48_create_optionspec); break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = hp48_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &hp48_create_optionguide; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case IMGTOOLINFO_PTR_OPEN: info->open = hp48_open; break; diff --git a/src/tools/imgtool/modules/pc_hard.cpp b/src/tools/imgtool/modules/pc_hard.cpp index 97ddd3b6894..57f1f5ad52d 100644 --- a/src/tools/imgtool/modules/pc_hard.cpp +++ b/src/tools/imgtool/modules/pc_hard.cpp @@ -55,7 +55,7 @@ #define FAT_SECLEN 512 -static OPTION_GUIDE_START( pc_chd_create_optionguide ) +OPTION_GUIDE_START( pc_chd_create_optionguide ) OPTION_INT('T', "cylinders", "Cylinders" ) OPTION_INT('H', "heads", "Heads" ) OPTION_INT('S', "sectors", "Sectors" ) @@ -463,7 +463,7 @@ void pc_chd_get_info(const imgtool_class *imgclass, UINT32 state, union imgtooli case IMGTOOLINFO_PTR_READ_BLOCK: info->read_block = pc_chd_image_readblock; break; case IMGTOOLINFO_PTR_WRITE_BLOCK: info->write_block = pc_chd_image_writeblock; break; case IMGTOOLINFO_PTR_GET_SECTOR_SIZE: info->get_sector_size = pc_chd_image_getsectorsize; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = pc_chd_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &pc_chd_create_optionguide; break; case IMGTOOLINFO_PTR_GET_GEOMETRY: info->get_geometry = pc_chd_image_get_geometry; break; case IMGTOOLINFO_PTR_LIST_PARTITIONS: info->list_partitions = pc_chd_list_partitions; break; } diff --git a/src/tools/imgtool/modules/psion.cpp b/src/tools/imgtool/modules/psion.cpp index 815cd78f265..3fcd398d30e 100644 --- a/src/tools/imgtool/modules/psion.cpp +++ b/src/tools/imgtool/modules/psion.cpp @@ -626,7 +626,7 @@ static imgtoolerr_t datapack_delete_file( imgtool_partition *partition, const ch return IMGTOOLERR_FILENOTFOUND; } -static OPTION_GUIDE_START( psion_create_optguide ) +OPTION_GUIDE_START( psion_create_optguide ) OPTION_ENUM_START( 'S', "size", "datapack size" ) OPTION_ENUM( 1, "8k", "8 kbyte" ) OPTION_ENUM( 2, "16k", "16 kbyts" ) @@ -641,7 +641,7 @@ static OPTION_GUIDE_START( psion_create_optguide ) OPTION_INT('C', "copy", "copyable datapack" ) OPTION_GUIDE_END -static OPTION_GUIDE_START( psion_write_optguide ) +OPTION_GUIDE_START( psion_write_optguide ) OPTION_ENUM_START( 'T', "type", "file type" ) OPTION_ENUM( 1, "OB3", "OB3 files" ) OPTION_ENUM( 2, "OPL", "OPL files" ) @@ -669,8 +669,8 @@ void psion_get_info( const imgtool_class *imgclass, UINT32 state, union imgtooli case IMGTOOLINFO_PTR_READ_FILE : info->read_file = datapack_read_file; break; case IMGTOOLINFO_PTR_WRITE_FILE : info->write_file = datapack_write_file; break; case IMGTOOLINFO_PTR_DELETE_FILE : info->delete_file = datapack_delete_file; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = psion_create_optguide; break; - case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE : info->createimage_optguide = psion_write_optguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE : info->createimage_optguide = &psion_create_optguide; break; + case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE : info->createimage_optguide = &psion_write_optguide; break; // --- the following bits of info are returned as NULL-terminated strings --- case IMGTOOLINFO_STR_NAME : strcpy( info->s = imgtool_temp_str(), "psionpack"); break; diff --git a/src/tools/imgtool/modules/rsdos.cpp b/src/tools/imgtool/modules/rsdos.cpp index e067ae8de5f..823e3d98339 100644 --- a/src/tools/imgtool/modules/rsdos.cpp +++ b/src/tools/imgtool/modules/rsdos.cpp @@ -579,7 +579,7 @@ static imgtoolerr_t rsdos_diskimage_suggesttransfer(imgtool_partition *partition Imgtool module declaration *********************************************************************/ -static OPTION_GUIDE_START( coco_rsdos_writefile_optionguide ) +OPTION_GUIDE_START( coco_rsdos_writefile_optionguide ) OPTION_ENUM_START( RSDOS_OPTIONS_FTYPE, "ftype", "File type" ) OPTION_ENUM( 0, "basic", "Basic" ) OPTION_ENUM( 1, "data", "Data" ) @@ -617,7 +617,7 @@ void rsdos_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolin case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = rsdos_diskimage_writefile; break; case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = rsdos_diskimage_deletefile; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = rsdos_diskimage_suggesttransfer; break; - case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = coco_rsdos_writefile_optionguide; break; + case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &coco_rsdos_writefile_optionguide; break; case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_coco; break; } } diff --git a/src/tools/imgtool/modules/thomson.cpp b/src/tools/imgtool/modules/thomson.cpp index 4d0c6718780..ecd475add86 100644 --- a/src/tools/imgtool/modules/thomson.cpp +++ b/src/tools/imgtool/modules/thomson.cpp @@ -1065,7 +1065,7 @@ static imgtoolerr_t thom_write_file(imgtool_partition *part, } /* comment */ - char const *const comment = opts->lookup_string('C'); + char const *const comment = opts->lookup_string('C').c_str(); if (comment && *comment) strncpy(d.comment, comment, 8); @@ -1132,7 +1132,7 @@ static imgtoolerr_t thom_create(imgtool_image* img, /* get parameters */ f->heads = opts->lookup_int('H'); f->tracks = opts->lookup_int('T'); - name = opts->lookup_string('N'); + name = opts->lookup_string('N').c_str(); switch ( opts->lookup_int('D') ) { case 0: f->sector_size = 128; f->sectuse_size = 128; break; case 1: f->sector_size = 256; f->sectuse_size = 255; break; @@ -1519,7 +1519,7 @@ FILTER( thombas128, /************************* driver ***************************/ -static OPTION_GUIDE_START( thom_createimage_optguide ) +OPTION_GUIDE_START( thom_createimage_optguide ) OPTION_INT( 'H', "heads", "Heads" ) OPTION_INT( 'T', "tracks", "Tracks" ) OPTION_ENUM_START( 'D', "density", "Density" ) @@ -1529,7 +1529,7 @@ static OPTION_GUIDE_START( thom_createimage_optguide ) OPTION_STRING( 'N', "name", "Floppy name" ) OPTION_GUIDE_END -static OPTION_GUIDE_START( thom_writefile_optguide ) +OPTION_GUIDE_START( thom_writefile_optguide ) OPTION_ENUM_START( 'T', "ftype", "File type" ) OPTION_ENUM( 0, "auto", "Automatic (by extension)" ) OPTION_ENUM( 1, "B", "Program" ) @@ -1571,7 +1571,7 @@ static void thom_basic_get_info(const imgtool_class *clas, case IMGTOOLINFO_PTR_CREATE: info->create = thom_create; break; case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: - info->createimage_optguide = thom_createimage_optguide; break; + info->createimage_optguide = &thom_createimage_optguide; break; case IMGTOOLINFO_PTR_BEGIN_ENUM: info->begin_enum = thom_begin_enum; break; case IMGTOOLINFO_PTR_NEXT_ENUM: @@ -1581,7 +1581,7 @@ static void thom_basic_get_info(const imgtool_class *clas, case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = thom_write_file; break; case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: - info->writefile_optguide = thom_writefile_optguide; break; + info->writefile_optguide = &thom_writefile_optguide; break; case IMGTOOLINFO_STR_WRITEFILE_OPTSPEC: strcpy( info->s = imgtool_temp_str(), "T[0]-4;F[0]-2;C" ); break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: diff --git a/src/tools/imgtool/modules/ti99.cpp b/src/tools/imgtool/modules/ti99.cpp index 5e643af8129..57b58ea75b1 100644 --- a/src/tools/imgtool/modules/ti99.cpp +++ b/src/tools/imgtool/modules/ti99.cpp @@ -3877,7 +3877,7 @@ enum dsk_createopts_density = 'F' }; -static OPTION_GUIDE_START( dsk_create_optionguide ) +OPTION_GUIDE_START( dsk_create_optionguide ) OPTION_STRING(dsk_createopts_volname, "label", "Volume name" ) OPTION_INT(dsk_createopts_sides, "sides", "Sides" ) OPTION_INT(dsk_createopts_tracks, "tracks", "Tracks" ) @@ -3929,7 +3929,7 @@ void ti99_old_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoo case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (old MESS format)"); break; case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_mess; break; case IMGTOOLINFO_PTR_CREATE: info->create = dsk_image_create_mess; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = dsk_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &dsk_create_optionguide; break; case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), dsk_create_optionspecs); break; default: ti99_dsk_getinfo(imgclass, state, info); break; } @@ -3943,7 +3943,7 @@ void ti99_v9t9_get_info(const imgtool_class *imgclass, UINT32 state, union imgto case IMGTOOLINFO_STR_DESCRIPTION: strcpy(info->s = imgtool_temp_str(), "TI99 Diskette (V9T9 format)"); break; case IMGTOOLINFO_PTR_OPEN: info->open = dsk_image_init_v9t9; break; case IMGTOOLINFO_PTR_CREATE: info->create = dsk_image_create_v9t9; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = dsk_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &dsk_create_optionguide; break; case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), dsk_create_optionspecs); break; default: ti99_dsk_getinfo(imgclass, state, info); break; } @@ -5244,7 +5244,7 @@ static imgtoolerr_t dsk_image_create(imgtool_image *image, imgtool_stream *f, ut l1_img.file_handle = f; /* read options */ - volname = createoptions->lookup_string(dsk_createopts_volname); + volname = createoptions->lookup_string(dsk_createopts_volname).c_str(); l1_img.geometry.heads = createoptions->lookup_int(dsk_createopts_sides); l1_img.geometry.cylinders = createoptions->lookup_int(dsk_createopts_tracks); l1_img.geometry.secspertrack = createoptions->lookup_int(dsk_createopts_sectors); diff --git a/src/tools/imgtool/modules/ti990hd.cpp b/src/tools/imgtool/modules/ti990hd.cpp index d4731f4d753..195606e720a 100644 --- a/src/tools/imgtool/modules/ti990hd.cpp +++ b/src/tools/imgtool/modules/ti990hd.cpp @@ -409,7 +409,7 @@ enum ti990_createopts_sectorsize = 'E' }; -static OPTION_GUIDE_START( ti990_create_optionguide ) +OPTION_GUIDE_START( ti990_create_optionguide ) /*OPTION_STRING(ti990_createopts_volname, "label", "Volume name" )*/ OPTION_INT(ti990_createopts_cylinders, "cylinders", "Cylinders" ) OPTION_INT(ti990_createopts_heads, "heads", "Heads" ) @@ -442,7 +442,7 @@ void ti990_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolin case IMGTOOLINFO_PTR_DELETE_FILE: /* info->delete_file = ti990_image_deletefile; */ break; case IMGTOOLINFO_PTR_CREATE: info->create = ti990_image_create; break; - case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = ti990_create_optionguide; break; + case IMGTOOLINFO_PTR_CREATEIMAGE_OPTGUIDE: info->createimage_optguide = &ti990_create_optionguide; break; case IMGTOOLINFO_STR_CREATEIMAGE_OPTSPEC: strcpy(info->s = imgtool_temp_str(), ti990_create_optionspecs); break; } } diff --git a/src/tools/imgtool/modules/vzdos.cpp b/src/tools/imgtool/modules/vzdos.cpp index 09f01556b06..db0d056e10d 100644 --- a/src/tools/imgtool/modules/vzdos.cpp +++ b/src/tools/imgtool/modules/vzdos.cpp @@ -903,7 +903,7 @@ void filter_vzsnapshot_getinfo(UINT32 state, union filterinfo *info) Imgtool module declaration *********************************************************************/ -static OPTION_GUIDE_START(vzdos_writefile_optionguide) +OPTION_GUIDE_START(vzdos_writefile_optionguide) OPTION_ENUM_START( 'T', "ftype", "File type" ) OPTION_ENUM( 0, "basic", "Basic" ) OPTION_ENUM( 1, "binary", "Binary" ) @@ -953,7 +953,7 @@ void vzdos_get_info(const imgtool_class *imgclass, UINT32 state, union imgtoolin case IMGTOOLINFO_PTR_WRITE_FILE: info->write_file = vzdos_diskimage_writefile; break; case IMGTOOLINFO_PTR_DELETE_FILE: info->delete_file = vzdos_diskimage_deletefile; break; case IMGTOOLINFO_PTR_FLOPPY_CREATE: info->create = vzdos_diskimage_create; break; - case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = vzdos_writefile_optionguide; break; + case IMGTOOLINFO_PTR_WRITEFILE_OPTGUIDE: info->writefile_optguide = &vzdos_writefile_optionguide; break; case IMGTOOLINFO_PTR_SUGGEST_TRANSFER: info->suggest_transfer = vzdos_diskimage_suggesttransfer; break; case IMGTOOLINFO_PTR_FLOPPY_FORMAT: info->p = (void *) floppyoptions_vz; break; }