Merge pull request #1332 from npwoods/option_guide_and_imgtool

option_guide C++-ification, touched up imgtool
This commit is contained in:
Vas Crabb 2016-09-10 10:15:30 +10:00 committed by GitHub
commit 6a2b41aa0b
29 changed files with 686 additions and 730 deletions

View File

@ -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;
}

View File

@ -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; }

View File

@ -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);

View File

@ -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;
}

View File

@ -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; }

View File

@ -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
//-------------------------------------------------

View File

@ -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);

View File

@ -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<util::option_resolution> 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<util::option_resolution>(floppy_option_guide, format->param_guidelines);
if (!alloc_resolution)
try { alloc_resolution = std::make_unique<util::option_resolution>(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<util::option_resolution>(floppy_option_guide, floppy->floppy_option->param_guidelines);
if (!alloc_resolution)
try
{
alloc_resolution = std::make_unique<util::option_resolution>(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;

View File

@ -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

View File

@ -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 <std::size_t Count>
class option_guide_impl : protected std::array<option_guide::entry, Count>, public option_guide
{
public:
template<typename... T>
option_guide_impl(T &&... elems)
: std::array<option_guide::entry, Count>({ std::forward<T>(elems)... })
, option_guide(&(*this)[0], &(*this)[0] + Count)
{
}
};
template <typename... T>
option_guide_impl<sizeof...(T)> make_option_guide(int dummy, T &&... elems)
{
return option_guide_impl<sizeof...(T)>(std::forward<T>(elems)...);
}
// ======================> option_resolution
class option_resolution
{
public:
// TODO - audit unused parameters
enum class error
{
SUCCESS,
@ -102,61 +173,98 @@ public:
INTERNAL
};
template<typename T>
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<range<int> > 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<entry>::iterator entries_begin() { return m_entries.begin(); }
std::vector<entry>::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<entry> 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<entry>::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;
};

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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<util::option_resolution>(*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)

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;
}