diff options
Diffstat (limited to 'src/frontend/mame/infoxml.cpp')
-rw-r--r-- | src/frontend/mame/infoxml.cpp | 325 |
1 files changed, 186 insertions, 139 deletions
diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp index 8ca6dfcc875..37d649a1131 100644 --- a/src/frontend/mame/infoxml.cpp +++ b/src/frontend/mame/infoxml.cpp @@ -13,16 +13,20 @@ #include "mameopts.h" +// devices #include "machine/ram.h" #include "sound/samples.h" +// emu #include "config.h" #include "drivenum.h" +#include "main.h" #include "romload.h" #include "screen.h" #include "softlist_dev.h" #include "speaker.h" +// lib/util #include "corestr.h" #include "xmlfile.h" @@ -98,10 +102,8 @@ private: }; -typedef std::set<std::add_pointer_t<device_type>, device_type_compare> device_type_set; - -std::string normalize_string(const char *string); -std::string normalize_string(std::string_view string); +using device_type_set = std::set<std::add_pointer_t<device_type>, device_type_compare>; +using device_type_vector = std::vector<std::add_pointer_t<device_type> >; // internal helper void output_header(std::ostream &out, bool dtd); @@ -338,7 +340,7 @@ constexpr std::pair<device_t::feature_type, char const *> f_feature_names[] = { //------------------------------------------------- -// get_feature_name - get XML name for feature +// feature_name - get XML name for feature //------------------------------------------------- char const *info_xml_creator::feature_name(device_t::feature_type feature) @@ -356,6 +358,33 @@ char const *info_xml_creator::feature_name(device_t::feature_type feature) //------------------------------------------------- +// format_sourcefile - sanitise source file path +//------------------------------------------------- + +std::string info_xml_creator::format_sourcefile(std::string_view path) +{ + using namespace std::literals; + + if (auto prefix(path.rfind("src/mame/"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 9); + else if (auto prefix(path.rfind("src\\mame\\"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 9); + else if (auto prefix(path.rfind("/src/"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 5); + else if (auto prefix(path.rfind("\\src\\"sv)); std::string_view::npos != prefix) + path.remove_prefix(prefix + 5); + else if (path.substr(0, 4) == "src/"sv) + path.remove_prefix(4); + else if (path.substr(0, 4) == "src\\"sv) + path.remove_prefix(4); + + std::string result(path); + std::replace(result.begin(), result.end(), '\\', '/'); + return result; +} + + +//------------------------------------------------- // info_xml_creator - constructor //------------------------------------------------- @@ -388,7 +417,7 @@ void info_xml_creator::output(std::ostream &out, const std::vector<std::string> auto it = matched.begin(); for (const std::string &pat : patterns) { - if (!core_strwildcmp(pat.c_str(), shortname)) + if (!core_strwildcmp(pat, shortname)) { // this driver matches the pattern - tell the caller result = true; @@ -397,7 +426,7 @@ void info_xml_creator::output(std::ostream &out, const std::vector<std::string> if (!*it) { *it = true; - if (!core_iswildstr(pat.c_str())) + if (!core_iswildstr(pat)) { exact_matches++; @@ -448,11 +477,6 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const device_type_set m_dev_set; }; - // TODO: maybe not the best place for this as it affects the stream passed in - // if the device part is threaded, the local streams used by the tasks can be - // imbued and the stream passed in can be left alone - out.imbue(std::locale::classic()); - // prepare a driver enumerator and the queue driver_enumerator drivlist(m_lookup_options); device_filter devfilter(filter); @@ -460,14 +484,14 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const bool header_outputted = false; // essentially a local method to emit the header if necessary - auto output_header_if_necessary = [this, &header_outputted](std::ostream &out) - { - if (!header_outputted) - { - output_header(out, m_dtd); - header_outputted = true; - } - }; + auto const output_header_if_necessary = [this, &header_outputted] (std::ostream &out) + { + if (!header_outputted) + { + output_header(out, m_dtd); + header_outputted = true; + } + }; // only keep a device set when we're asked to track it std::optional<device_type_set> devset; @@ -476,14 +500,14 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const // prepare a queue of tasks - this is a FIFO queue because of the // need to be deterministic - std::queue<std::future<prepared_info>> tasks; + std::queue<std::future<prepared_info> > tasks; // while we want to be deterministic, asynchronous task scheduling is not; so we want to // track the amount of active tasks so that we can keep on spawning tasks even if we're // waiting on the task in the front of the queue std::atomic<unsigned int> active_task_count = 0; - unsigned int maximum_active_task_count = std::thread::hardware_concurrency() + 10; - unsigned int maximum_outstanding_task_count = maximum_active_task_count + 20; + unsigned int const maximum_active_task_count = std::thread::hardware_concurrency() + 10; + unsigned int const maximum_outstanding_task_count = maximum_active_task_count + 20; // loop until we're done enumerating drivers, and until there are no outstanding tasks while (!filtered_drivlist.done() || !tasks.empty()) @@ -491,32 +515,32 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const // loop until there are as many outstanding tasks as possible (we want to separately cap outstanding // tasks and active tasks) while (!filtered_drivlist.done() - && active_task_count < maximum_active_task_count - && tasks.size() < maximum_outstanding_task_count) + && (active_task_count < maximum_active_task_count) + && (tasks.size() < maximum_outstanding_task_count)) { // we want to launch a task; grab a packet of drivers to process - std::vector<std::reference_wrapper<const game_driver>> drivers = filtered_drivlist.next(20); + std::vector<std::reference_wrapper<const game_driver> > drivers = filtered_drivlist.next(20); if (drivers.empty()) break; - // do the dirty work asychronously - auto task_proc = [&drivlist, drivers{ std::move(drivers) }, include_devices, &active_task_count] - { - prepared_info result; - std::ostringstream stream; - stream.imbue(std::locale::classic()); + // do the dirty work asynchronously + auto task_proc = [&drivlist, drivers = std::move(drivers), include_devices, &active_task_count] + { + prepared_info result; + std::ostringstream stream; + stream.imbue(std::locale::classic()); - // output each of the drivers - for (const game_driver &driver : drivers) - output_one(stream, drivlist, driver, include_devices ? &result.m_dev_set : nullptr); + // output each of the drivers + for (const game_driver &driver : drivers) + output_one(stream, drivlist, driver, include_devices ? &result.m_dev_set : nullptr); - // capture the XML snippet - result.m_xml_snippet = stream.str(); + // capture the XML snippet + result.m_xml_snippet = std::move(stream).str(); - // we're done with the task; decrement the counter and return - active_task_count--; - return result; - }; + // we're done with the task; decrement the counter and return + active_task_count--; + return result; + }; // add this task to the queue active_task_count++; @@ -526,8 +550,7 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const // we've put as many outstanding tasks out as we can; are there any tasks outstanding? if (!tasks.empty()) { - // wait for the task at the front of the queue to complete and get the info, in the - // spirit of determinism + // wait for the oldest task to complete and get the info, in the spirit of determinism prepared_info pi = tasks.front().get(); tasks.pop(); @@ -577,39 +600,6 @@ namespace { //------------------------------------------------- -// normalize_string -//------------------------------------------------- - -std::string normalize_string(const char *string) -{ - if (string) - return normalize_string(std::string_view(string)); - else - return std::string(); -} - -std::string normalize_string(std::string_view string) -{ - std::string result; - result.reserve(string.length()); - - for (char ch : string) - { - switch (ch) - { - case '\"': result.append("""); break; - case '&': result.append("&"); break; - case '<': result.append("<"); break; - case '>': result.append(">"); break; - default: result.append(1, ch); break; - } - } - - return result; -} - - -//------------------------------------------------- // device_filter::filter - apply the filter, if // present //------------------------------------------------- @@ -625,9 +615,10 @@ bool device_filter::filter(const char *shortname) // of game_drivers, while applying filters //------------------------------------------------- -std::vector<std::reference_wrapper<const game_driver>> filtered_driver_enumerator::next(int count) +std::vector<std::reference_wrapper<const game_driver> > filtered_driver_enumerator::next(int count) { - std::vector<std::reference_wrapper<const game_driver>> results; + std::vector<std::reference_wrapper<const game_driver> > results; + results.reserve(count); while (!done() && results.size() < count) { if (!m_drivlist.next()) @@ -639,7 +630,7 @@ std::vector<std::reference_wrapper<const game_driver>> filtered_driver_enumerato else if (m_devfilter.filter(m_drivlist.driver().name)) { const game_driver &driver(m_drivlist.driver()); - results.push_back(driver); + results.emplace_back(driver); } } return results; @@ -665,6 +656,7 @@ void output_header(std::ostream &out, bool dtd) } // top-level tag + assert(emulator_info::get_build_version() != nullptr); util::stream_format(out, "<%s build=\"%s\" debug=\"" #ifdef MAME_DEBUG @@ -674,7 +666,7 @@ void output_header(std::ostream &out, bool dtd) #endif "\" mameconfig=\"%d\">\n", XML_ROOT, - normalize_string(emulator_info::get_build_version()), + util::xml::normalize_string(emulator_info::get_build_version()), configuration_manager::CONFIG_VERSION); } @@ -697,6 +689,8 @@ void output_footer(std::ostream &out) void output_one(std::ostream &out, driver_enumerator &drivlist, const game_driver &driver, device_type_set *devtypes) { + using util::xml::normalize_string; + machine_config config(driver, drivlist.options()); device_enumerator iter(config.root_device()); @@ -747,14 +741,8 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive // print the header and the machine name util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name)); - // strip away any path information from the source_file and output it - std::string_view src(driver.type.source()); - auto prefix(src.find("src/mame/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\mame\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 9); - util::stream_format(out, " sourcefile=\"%s\"", normalize_string(src)); + // strip away extra path information from the source file and output it + util::stream_format(out, " sourcefile=\"%s\"", normalize_string(info_xml_creator::format_sourcefile(driver.type.source()))); // append bios and runnable flags if (driver.flags & machine_flags::IS_BIOS_ROOT) @@ -817,6 +805,8 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive void output_one_device(std::ostream &out, machine_config &config, device_t &device, const char *devtag) { + using util::xml::normalize_string; + bool has_speaker = false, has_input = false; // check if the device adds speakers to the system sound_interface_enumerator snditer(device); @@ -846,13 +836,7 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi // start to output info util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname())); - std::string_view src(device.source()); - auto prefix(src.find("src/")); - if (std::string_view::npos == prefix) - prefix = src.find("src\\"); - if (std::string_view::npos != prefix) - src.remove_prefix(prefix + 4); - util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src)); + util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(info_xml_creator::format_sourcefile(device.source()))); auto const parent(device.type().parent_rom_device_type()); if (parent) util::stream_format(out, " romof=\"%s\"", normalize_string(parent->shortname())); @@ -891,38 +875,85 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi void output_devices(std::ostream &out, emu_options &lookup_options, device_type_set const *filter) { - // get config for empty machine - machine_config config(GAME_NAME(___empty), lookup_options); - - auto const action = [&config, &out] (device_type type) + auto const action = [&lookup_options, &out] (auto &types, auto deref) { - // add it at the root of the machine config - device_t *dev; + // machinery for making output order deterministic and capping outstanding tasks + std::queue<std::future<std::string> > tasks; + std::atomic<unsigned int> active_task_count = 0; + unsigned int const maximum_active_task_count = std::thread::hardware_concurrency() + 10; + unsigned int const maximum_outstanding_task_count = maximum_active_task_count + 20; + + // loop until we're done enumerating devices and there are no outstanding tasks + auto it = std::begin(types); + while ((std::end(types) != it) || !tasks.empty()) { - machine_config::token const tok(config.begin_configuration(config.root_device())); - dev = config.device_add("_tmp", type, 0); - } + // look until there are as many outstanding tasks as possible + while ((std::end(types) != it) + && (active_task_count < maximum_active_task_count) + && (tasks.size() < maximum_outstanding_task_count)) + { + device_type_vector batch; + batch.reserve(10); + while ((std::end(types) != it) && (batch.size() < 10)) + batch.emplace_back(deref(*it++)); + if (batch.empty()) + break; - // notify this device and all its subdevices that they are now configured - for (device_t &device : device_enumerator(*dev)) - if (!device.configured()) - device.config_complete(); + // do the dirty work asynchronously + auto task_proc = [&active_task_count, &lookup_options, batch = std::move(batch)] + { + // use a single machine configuration and stream for a batch of devices + machine_config config(GAME_NAME(___empty), lookup_options); + std::ostringstream stream; + stream.imbue(std::locale::classic()); + for (auto type : batch) + { + // add it at the root of the machine config + device_t *dev; + { + machine_config::token const tok(config.begin_configuration(config.root_device())); + dev = config.device_add("_tmp", *type, 0); + } + + // notify this device and all its subdevices that they are now configured + for (device_t &device : device_enumerator(*dev)) + if (!device.configured()) + device.config_complete(); + + // print details and remove it + output_one_device(stream, config, *dev, dev->tag()); + machine_config::token const tok(config.begin_configuration(config.root_device())); + config.device_remove("_tmp"); + } + + // we're done with the task; decrement the counter and return + active_task_count--; + return std::move(stream).str(); + }; + + // add this task to the queue + active_task_count++; + tasks.emplace(std::async(std::launch::async, std::move(task_proc))); + } - // print details and remove it - output_one_device(out, config, *dev, dev->tag()); - machine_config::token const tok(config.begin_configuration(config.root_device())); - config.device_remove("_tmp"); + // we've put as many outstanding tasks out as we can; are there any tasks outstanding? + if (!tasks.empty()) + { + // wait for the oldest task to complete and get the info, in the spirit of determinism + std::string snippet = tasks.front().get(); + tasks.pop(); + + // emit whatever XML we accumulated in the task + out << snippet; + } + } }; // run through devices if (filter) - { - for (std::add_pointer_t<device_type> type : *filter) action(*type); - } + action(*filter, [] (auto &x) { return x; }); else - { - for (device_type type : registered_device_types) action(type); - } + action(registered_device_types, [] (auto &x) { return &x; }); } @@ -935,7 +966,7 @@ void output_device_refs(std::ostream &out, device_t &root) { for (device_t &device : device_enumerator(root)) if (&device != &root) - util::stream_format(out, "\t\t<device_ref name=\"%s\"/>\n", normalize_string(device.shortname())); + util::stream_format(out, "\t\t<device_ref name=\"%s\"/>\n", util::xml::normalize_string(device.shortname())); } @@ -952,7 +983,7 @@ void output_sampleof(std::ostream &out, device_t &device) samples_iterator sampiter(samples); if (sampiter.altbasename() != nullptr) { - util::stream_format(out, " sampleof=\"%s\"", normalize_string(sampiter.altbasename())); + util::stream_format(out, " sampleof=\"%s\"", util::xml::normalize_string(sampiter.altbasename())); // must stop here, as there can only be one attribute of the same name return; @@ -980,8 +1011,8 @@ void output_bios(std::ostream &out, device_t const &device) { // output extracted name and descriptions' out << "\t\t<biosset"; - util::stream_format(out, " name=\"%s\"", normalize_string(bios.get_name())); - util::stream_format(out, " description=\"%s\"", normalize_string(bios.get_description())); + util::stream_format(out, " name=\"%s\"", util::xml::normalize_string(bios.get_name())); + util::stream_format(out, " description=\"%s\"", util::xml::normalize_string(bios.get_description())); if (defaultname && !std::strcmp(defaultname, bios.get_name())) out << " default=\"yes\""; out << "/>\n"; @@ -1052,6 +1083,8 @@ void output_rom(std::ostream &out, machine_config &config, driver_list const *dr tiny_rom_entry const *region(nullptr); for (tiny_rom_entry const *rom = device.rom_region(); rom && !ROMENTRY_ISEND(rom); ++rom) { + using util::xml::normalize_string; + if (ROMENTRY_ISREGION(rom)) region = rom; else if (ROMENTRY_ISSYSTEM_BIOS(rom)) @@ -1146,7 +1179,7 @@ void output_sample(std::ostream &out, device_t &device) continue; // output the sample name - util::stream_format(out, "\t\t<sample name=\"%s\"/>\n", normalize_string(samplename)); + util::stream_format(out, "\t\t<sample name=\"%s\"/>\n", util::xml::normalize_string(samplename)); } } } @@ -1159,6 +1192,8 @@ void output_sample(std::ostream &out, device_t &device) void output_chips(std::ostream &out, device_t &device, const char *root_tag) { + using util::xml::normalize_string; + // iterate over executable devices for (device_execute_interface &exec : execute_interface_enumerator(device)) { @@ -1211,7 +1246,7 @@ void output_display(std::ostream &out, device_t &device, machine_flags::type con std::string newtag(screendev.tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - util::stream_format(out, "\t\t<display tag=\"%s\"", normalize_string(newtag)); + util::stream_format(out, "\t\t<display tag=\"%s\"", util::xml::normalize_string(newtag)); switch (screendev.screen_type()) { @@ -1323,7 +1358,7 @@ void output_ioport_condition(std::ostream &out, const ioport_condition &conditio case ioport_condition::NOTLESSTHAN: rel = "ge"; break; } - util::stream_format(out, "<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", normalize_string(condition.tag()), condition.mask(), rel, condition.value()); + util::stream_format(out, "<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", util::xml::normalize_string(condition.tag()), condition.mask(), rel, condition.value()); } //------------------------------------------------- @@ -1385,14 +1420,14 @@ void output_input(std::ostream &out, const ioport_list &portlist) int player; // player which the input belongs to int nbuttons; // total number of buttons int reqbuttons; // total number of non-optional buttons - int maxbuttons; // max index of buttons (using IPT_BUTTONn) [probably to be removed soonish] + uint32_t maxbuttons; // max index of buttons (using IPT_BUTTONn) [probably to be removed soonish] int ways; // directions for joystick bool analog; // is analog input? - uint8_t helper[3]; // for dual joysticks [possibly to be removed soonish] - int32_t min; // analog minimum value - int32_t max; // analog maximum value - int32_t sensitivity; // default analog sensitivity - int32_t keydelta; // default analog keydelta + uint8_t helper[3]; // for dual joysticks [possibly to be removed soonish] + int32_t min; // analog minimum value + int32_t max; // analog maximum value + int32_t sensitivity; // default analog sensitivity + int32_t keydelta; // default analog keydelta bool reverse; // default analog reverse setting } control_info[CTRL_COUNT * CTRL_PCOUNT]; @@ -1400,7 +1435,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) // tracking info as we iterate int nplayer = 0; - int ncoin = 0; + uint32_t ncoin = 0; bool service = false; bool tilt = false; @@ -1728,7 +1763,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) out << "\t\t<input"; util::stream_format(out, " players=\"%d\"", nplayer); if (ncoin != 0) - util::stream_format(out, " coins=\"%d\"", ncoin); + util::stream_format(out, " coins=\"%u\"", ncoin); if (service) util::stream_format(out, " service=\"yes\""); if (tilt) @@ -1739,6 +1774,8 @@ void output_input(std::ostream &out, const ioport_list &portlist) for (auto & elem : control_info) if (elem.type != nullptr) { + using util::xml::normalize_string; + //printf("type %s - player %d - buttons %d\n", elem.type, elem.player, elem.nbuttons); if (elem.analog) { @@ -1747,7 +1784,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) util::stream_format(out, " player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - util::stream_format(out, " buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); + util::stream_format(out, " buttons=\"%u\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) util::stream_format(out, " reqbuttons=\"%d\"", elem.reqbuttons); } @@ -1773,7 +1810,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) util::stream_format(out, " player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - util::stream_format(out, " buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); + util::stream_format(out, " buttons=\"%u\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) util::stream_format(out, " reqbuttons=\"%d\"", elem.reqbuttons); } @@ -1832,10 +1869,13 @@ void output_switches(std::ostream &out, const ioport_list &portlist, const char for (ioport_field const &field : port.second->fields()) if (field.type() == type) { + using util::xml::normalize_string; + std::string newtag(port.second->tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // output the switch name information + assert(field.specific_name() != nullptr); std::string const normalized_field_name(normalize_string(field.specific_name())); std::string const normalized_newtag(normalize_string(newtag)); util::stream_format(out, "\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name, normalized_newtag, field.mask()); @@ -1883,7 +1923,7 @@ void output_ports(std::ostream &out, const ioport_list &portlist) // cycle through ports for (auto &port : portlist) { - util::stream_format(out, "\t\t<port tag=\"%s\">\n", normalize_string(port.second->tag())); + util::stream_format(out, "\t\t<port tag=\"%s\">\n", util::xml::normalize_string(port.second->tag())); for (ioport_field const &field : port.second->fields()) { if (field.is_analog()) @@ -1906,7 +1946,7 @@ void output_adjusters(std::ostream &out, const ioport_list &portlist) for (ioport_field const &field : port.second->fields()) if (field.type() == IPT_ADJUSTER) { - util::stream_format(out, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", normalize_string(field.specific_name()), field.defvalue()); + util::stream_format(out, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", util::xml::normalize_string(field.specific_name()), field.defvalue()); } } @@ -2012,11 +2052,14 @@ void output_images(std::ostream &out, device_t &device, const char *root_tag) { if (strcmp(imagedev.device().tag(), device.tag())) { + using util::xml::normalize_string; + bool loadable = imagedev.user_loadable(); std::string newtag(imagedev.device().tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // print m_output device type + assert(imagedev.image_type_name() != nullptr); util::stream_format(out, "\t\t<device type=\"%s\"", normalize_string(imagedev.image_type_name())); // does this device have a tag? @@ -2076,6 +2119,8 @@ void output_slots(std::ostream &out, machine_config &config, device_t &device, c if (devtypes || listed) { + using util::xml::normalize_string; + machine_config::token const tok(config.begin_configuration(slot.device())); std::string newtag(slot.device().tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); @@ -2124,6 +2169,8 @@ void output_software_lists(std::ostream &out, device_t &root, const char *root_t { for (const software_list_device &swlist : software_list_device_enumerator(root)) { + using util::xml::normalize_string; + if (&static_cast<const device_t &>(swlist) == &root) { assert(swlist.list_name().empty()); @@ -2161,11 +2208,11 @@ void output_ramoptions(std::ostream &out, device_t &root) { assert(!havedefault); havedefault = true; - util::stream_format(out, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", normalize_string(option.first), option.second); + util::stream_format(out, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", util::xml::normalize_string(option.first), option.second); } else { - util::stream_format(out, "\t\t<ramoption name=\"%s\">%u</ramoption>\n", normalize_string(option.first), option.second); + util::stream_format(out, "\t\t<ramoption name=\"%s\">%u</ramoption>\n", util::xml::normalize_string(option.first), option.second); } } if (!havedefault) |