diff options
43 files changed, 1114 insertions, 1013 deletions
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index 0744b67d87d..10208d8e357 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -85,18 +85,21 @@ static attotime attotime_from_nltime(netlist::netlist_time_ext t) } #endif -class netlist_mame_device::netlist_mame_callbacks_t : public netlist::callbacks_t +class netlist_mame_device::netlist_mame_t : public netlist::netlist_state_t { public: - netlist_mame_callbacks_t(const netlist_mame_device &parent) - : netlist::callbacks_t() + netlist_mame_t(netlist_mame_device &parent, const pstring &name) + : netlist::netlist_state_t(name, plib::plog_delegate(&netlist_mame_t::logger, this)) , m_parent(parent) { } -protected: - void vlog(const plib::plog_level &l, const pstring &ls) const noexcept override + running_machine &machine() { return m_parent.machine(); } + netlist_mame_device &parent() const { return m_parent; } + +private: + void logger(plib::plog_level l, const pstring &ls) { switch (l) { @@ -121,78 +124,6 @@ protected: } } - std::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override - { - //return plib::make_unique<plib::dynlib_static>(nullptr); - return std::make_unique<plib::dynlib_static>(nl_static_solver_syms); - } - -private: - const netlist_mame_device &m_parent; -}; - -class netlist_validate_callbacks_t : public netlist::callbacks_t -{ -public: - - netlist_validate_callbacks_t() - : netlist::callbacks_t() - { - } - -protected: - void vlog(const plib::plog_level &l, const pstring &ls) const noexcept override - { - switch (l) - { - case plib::plog_level::DEBUG: - break; - case plib::plog_level::VERBOSE: - break; - case plib::plog_level::INFO: - osd_printf_verbose("netlist INFO: %s\n", ls); - break; - case plib::plog_level::WARNING: - osd_printf_warning("netlist WARNING: %s\n", ls); - break; - case plib::plog_level::ERROR: - osd_printf_error("netlist ERROR: %s\n", ls); - break; - case plib::plog_level::FATAL: - osd_printf_error("netlist FATAL: %s\n", ls); - break; - } - } - - std::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override - { - return std::make_unique<plib::dynlib_static>(nullptr); - } - -private: -}; - - -class netlist_mame_device::netlist_mame_t : public netlist::netlist_state_t -{ -public: - - netlist_mame_t(netlist_mame_device &parent, const pstring &name) - : netlist::netlist_state_t(name, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t, netlist::host_arena>(parent)) - , m_parent(parent) - { - } - - netlist_mame_t(netlist_mame_device &parent, const pstring &name, netlist::host_arena::unique_ptr<netlist::callbacks_t> cbs) - : netlist::netlist_state_t(name, std::move(cbs)) - , m_parent(parent) - { - } - - running_machine &machine() { return m_parent.machine(); } - netlist_mame_device &parent() const { return m_parent; } - -private: netlist_mame_device &m_parent; }; @@ -236,7 +167,7 @@ public: { } - virtual stream_ptr stream(const pstring &name) override; + virtual plib::istream_uptr stream(const pstring &name) override; private: device_t &m_dev; pstring m_name; @@ -247,7 +178,7 @@ class netlist_data_memregions_t : public netlist::source_data_t public: netlist_data_memregions_t(const device_t &dev); - virtual stream_ptr stream(const pstring &name) override; + virtual plib::istream_uptr stream(const pstring &name) override; private: const device_t &m_dev; @@ -258,13 +189,13 @@ private: // memregion source support // ---------------------------------------------------------------------------------------- -netlist_source_memregion_t::stream_ptr netlist_source_memregion_t::stream(const pstring &name) +plib::istream_uptr netlist_source_memregion_t::stream(const pstring &name) { if (m_dev.has_running_machine()) { - memory_region *mem = m_dev.memregion(m_name.c_str()); - stream_ptr ret(std::make_unique<std::istringstream>(pstring(reinterpret_cast<char *>(mem->base()), mem->bytes())), name); - ret.stream().imbue(std::locale::classic()); + memory_region *mem = m_dev.memregion(putf8string(m_name).c_str()); + plib::istream_uptr ret(std::make_unique<std::istringstream>(putf8string(reinterpret_cast<char *>(mem->base()), mem->bytes())), name); + ret->imbue(std::locale::classic()); return ret; } else @@ -296,20 +227,20 @@ static bool rom_exists(device_t &root, pstring name) return false; } -netlist_data_memregions_t::stream_ptr netlist_data_memregions_t::stream(const pstring &name) +plib::istream_uptr netlist_data_memregions_t::stream(const pstring &name) { //memory_region *mem = static_cast<netlist_mame_device::netlist_mame_t &>(setup().setup().exec()).parent().memregion(name.c_str()); if (m_dev.has_running_machine()) { - memory_region *mem = m_dev.memregion(name.c_str()); + memory_region *mem = m_dev.memregion(putf8string(name).c_str()); if (mem != nullptr) { - stream_ptr ret(std::make_unique<std::istringstream>(std::string(reinterpret_cast<char *>(mem->base()), mem->bytes()), std::ios_base::binary), name); - ret.stream().imbue(std::locale::classic()); + plib::istream_uptr ret(std::make_unique<std::istringstream>(std::string(reinterpret_cast<char *>(mem->base()), mem->bytes()), std::ios_base::binary), name); + ret->imbue(std::locale::classic()); return ret; } else - return stream_ptr(); + return plib::istream_uptr(); } else { @@ -317,12 +248,12 @@ netlist_data_memregions_t::stream_ptr netlist_data_memregions_t::stream(const ps if (rom_exists(m_dev.mconfig().root_device(), pstring(m_dev.tag()) + ":" + name)) { // Create an empty stream. - stream_ptr ret(std::make_unique<std::istringstream>(std::ios_base::binary), name); - ret.stream().imbue(std::locale::classic()); + plib::istream_uptr ret(std::make_unique<std::istringstream>(std::ios_base::binary), name); + ret->imbue(std::locale::classic()); return ret; } else - return stream_ptr(); + return plib::istream_uptr(); } } @@ -813,9 +744,9 @@ void netlist_mame_stream_input_device::custom_netlist_additions(netlist::nlparse parser.register_dev("NETDEV_SOUND_IN", name); parser.register_param(name + ".CHAN", pstring(m_param_name)); - parser.register_param_val(name + ".MULT", m_mult); - parser.register_param_val(name + ".OFFSET", m_offset); - parser.register_param_val(name + ".ID", m_channel); + parser.register_param(name + ".MULT", m_mult); + parser.register_param(name + ".OFFSET", m_offset); + parser.register_param(name + ".ID", m_channel); } @@ -845,19 +776,19 @@ void netlist_mame_stream_output_device::set_params(int channel, const char *out_ /// struct save_helper { - save_helper(device_t *dev, const pstring &prefix) + save_helper(device_t *dev, const std::string &prefix) : m_device(dev), m_prefix(prefix) {} template<typename T, typename X = void *> - void save_item(T &&item, const pstring &name, X = nullptr) + void save_item(T &&item, const std::string &name, X = nullptr) { m_device->save_item(item, (m_prefix + "_" + name).c_str()); } template <typename X = void *> std::enable_if_t<plib::compile_info::has_int128::value && std::is_pointer<X>::value, void> - save_item(INT128 &item, const pstring &name, X = nullptr) + save_item(INT128 &item, const std::string &name, X = nullptr) { auto *p = reinterpret_cast<std::uint64_t *>(&item); m_device->save_item(p[0], (m_prefix + "_" + name + "_1").c_str()); @@ -866,7 +797,7 @@ struct save_helper private: device_t *m_device; - pstring m_prefix; + std::string m_prefix; }; void netlist_mame_stream_output_device::device_start() @@ -1029,16 +960,48 @@ void netlist_mame_device::common_dev_start(netlist::netlist_state_t *lnetlist) c } } +struct validity_logger +{ + void log(plib::plog_level l, const pstring &ls) + { + putf8string ls8(ls); + + switch (l) + { + case plib::plog_level::DEBUG: + break; + case plib::plog_level::VERBOSE: + break; + case plib::plog_level::INFO: + osd_printf_verbose("netlist INFO: %s\n", ls8); + break; + case plib::plog_level::WARNING: + osd_printf_warning("netlist WARNING: %s\n", ls8); + break; + case plib::plog_level::ERROR: + osd_printf_error("netlist ERROR: %s\n", ls8); + break; + case plib::plog_level::FATAL: + osd_printf_error("netlist FATAL: %s\n", ls8); + break; + } + } +}; + std::unique_ptr<netlist::netlist_state_t> netlist_mame_device::base_validity_check(validity_checker &valid) const { try { + validity_logger logger; plib::chrono::timer<plib::chrono::system_ticks> t; t.start(); auto lnetlist = std::make_unique<netlist::netlist_state_t>("netlist", - plib::make_unique<netlist_validate_callbacks_t, netlist::host_arena>()); + plib::plog_delegate(&validity_logger::log, &logger)); // enable validation mode lnetlist->set_extended_validation(true); + + lnetlist->set_static_solver_lib(std::make_unique<plib::dynlib_static>(nullptr)); + common_dev_start(lnetlist.get()); lnetlist->setup().prepare_to_run(); @@ -1084,6 +1047,9 @@ void netlist_mame_device::device_validity_check(validity_checker &valid) const void netlist_mame_device::device_start_common() { m_netlist = std::make_unique<netlist_mame_t>(*this, "netlist"); + + m_netlist->set_static_solver_lib(std::make_unique<plib::dynlib_static>(nl_static_solver_syms)); + if (!machine().options().verbose()) { m_netlist->log().verbose.set_enabled(false); @@ -1186,37 +1152,39 @@ void netlist_mame_device::save_state() { for (auto const & s : netlist().run_state_manager().save_list()) { - netlist().log().debug("saving state for {1}\n", s->name().c_str()); + putf8string u8name(s->name()); + + netlist().log().debug("saving state for {1}\n", u8name.c_str()); if (s->dt().is_float()) { if (s->dt().size() == sizeof(double)) - save_pointer((double *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((double *) s->ptr(), u8name.c_str(), s->count()); else if (s->dt().size() == sizeof(float)) - save_pointer((float *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((float *) s->ptr(), u8name.c_str(), s->count()); else - netlist().log().fatal("Unknown floating type for {1}\n", s->name().c_str()); + netlist().log().fatal("Unknown floating type for {1}\n", u8name.c_str()); } else if (s->dt().is_integral()) { if (s->dt().size() == sizeof(int64_t)) - save_pointer((int64_t *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((int64_t *) s->ptr(), u8name.c_str(), s->count()); else if (s->dt().size() == sizeof(int32_t)) - save_pointer((int32_t *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((int32_t *) s->ptr(), u8name.c_str(), s->count()); else if (s->dt().size() == sizeof(int16_t)) - save_pointer((int16_t *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((int16_t *) s->ptr(), u8name.c_str(), s->count()); else if (s->dt().size() == sizeof(int8_t)) - save_pointer((int8_t *) s->ptr(), s->name().c_str(), s->count()); + save_pointer((int8_t *) s->ptr(), u8name.c_str(), s->count()); else if (plib::compile_info::has_int128::value && s->dt().size() == sizeof(INT128)) - save_pointer((int64_t *) s->ptr(), s->name().c_str(), s->count() * 2); + save_pointer((int64_t *) s->ptr(), u8name.c_str(), s->count() * 2); else - netlist().log().fatal("Unknown integral type size {1} for {2}\n", s->dt().size(), s->name().c_str()); + netlist().log().fatal("Unknown integral type size {1} for {2}\n", s->dt().size(), u8name.c_str()); } else if (s->dt().is_custom()) { /* do nothing */ } else - netlist().log().fatal("found unsupported save element {1}\n", s->name()); + netlist().log().fatal("found unsupported save element {1}\n", u8name); } } @@ -1259,7 +1227,7 @@ void netlist_mame_cpu_device::device_start() int index = 0; for (auto &n : netlist().nets()) { - pstring name = n->name(); //plib::replace_all(n->name(), ".", "_"); + putf8string name(n->name()); //plib::replace_all(n->name(), ".", "_"); if (n->is_logic()) { auto nl = downcast<netlist::logic_net_t *>(n.get()); diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h index 8b35b13bacf..b7a78c0bd77 100644 --- a/src/devices/machine/netlist.h +++ b/src/devices/machine/netlist.h @@ -105,6 +105,7 @@ protected: std::unique_ptr<netlist::netlist_state_t> base_validity_check(validity_checker &valid) const; private: + void common_dev_start(netlist::netlist_state_t *lnetlist) const; std::unique_ptr<netlist_mame_t> m_netlist; diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h index 246c7c1a14e..781dc2a16bb 100644 --- a/src/lib/netlist/analog/nld_generic_models.h +++ b/src/lib/netlist/analog/nld_generic_models.h @@ -9,7 +9,7 @@ /// #include "nl_base.h" -#include "../nl_setup.h" +//#include "../nl_setup.h" // // Set to 0 to use a linearized diode model in the range exceeding diff --git a/src/lib/netlist/core/netlist_state.h b/src/lib/netlist/core/netlist_state.h index 318eaae6b2d..137f264ddfd 100644 --- a/src/lib/netlist/core/netlist_state.h +++ b/src/lib/netlist/core/netlist_state.h @@ -36,7 +36,8 @@ namespace netlist // need to preserve order of device creation ... using devices_collection_type = std::vector<std::pair<pstring, device_arena::owned_ptr<core_device_t>>>; - netlist_state_t(const pstring &name, host_arena::unique_ptr<callbacks_t> &&callbacks); + + netlist_state_t(const pstring &name, plib::plog_delegate logger); PCOPYASSIGNMOVE(netlist_state_t, delete) @@ -92,7 +93,15 @@ namespace netlist log_type & log() noexcept { return m_log; } const log_type &log() const noexcept { return m_log; } - plib::dynlib_base &lib() const noexcept { return *m_lib; } + plib::dynlib_base &static_solver_lib() const noexcept { return *m_lib; } + + /// \brief provide library with static solver implementations. + /// + /// By default no static solvers are provided since these are + /// determined by the specific use case. You can pass such a collection + /// of symbols with this method. + /// + void set_static_solver_lib(std::unique_ptr<plib::dynlib_base> &&lib); netlist_t &exec() noexcept { return *m_netlist; } const netlist_t &exec() const noexcept { return *m_netlist; } @@ -252,7 +261,6 @@ namespace netlist device_arena::unique_ptr<netlist_t> m_netlist; std::unique_ptr<plib::dynlib_base> m_lib; plib::state_manager_t m_state; - host_arena::unique_ptr<callbacks_t> m_callbacks; log_type m_log; // FIXME: should only be available during device construcion diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h index adb13f465da..2007d1f844d 100644 --- a/src/lib/netlist/core/param.h +++ b/src/lib/netlist/core/param.h @@ -8,19 +8,6 @@ #ifndef NL_CORE_PARAM_H_ #define NL_CORE_PARAM_H_ -#if 0 -#include "../nl_config.h" -#include "../nl_factory.h" -#include "../nl_setup.h" - -#include "../plib/ppreprocessor.h" - -#include <initializer_list> -#include <stack> -#include <unordered_map> -#include <vector> -#endif - #include "../nltypes.h" #include "base_objects.h" @@ -244,7 +231,7 @@ namespace netlist { } - plib::psource_t::stream_ptr stream(); + plib::istream_uptr stream(); protected: void changed() noexcept override { } }; @@ -264,7 +251,7 @@ namespace netlist protected: void changed() noexcept override { - plib::istream_read(stream().stream(), m_data.data(), 1<<AW); + plib::istream_read(*stream(), m_data.data(), 1<<AW); } private: @@ -321,7 +308,7 @@ namespace netlist auto f = this->stream(); if (!f.empty()) { - plib::istream_read(f.stream(), m_data.data(), 1<<AW); + plib::istream_read(*f, m_data.data(), 1<<AW); // FIXME: check for failbit if not in validation. } else diff --git a/src/lib/netlist/core/setup.h b/src/lib/netlist/core/setup.h index f2d0b748fd0..c0d43c95586 100644 --- a/src/lib/netlist/core/setup.h +++ b/src/lib/netlist/core/setup.h @@ -13,7 +13,7 @@ #include "../nl_setup.h" #include "../nltypes.h" -#include "../plib/ppreprocessor.h" +//#include "../plib/ppreprocessor.h" #include "../plib/pstream.h" #include "../plib/pstring.h" @@ -260,7 +260,7 @@ namespace netlist } protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: pstring m_str; @@ -276,7 +276,7 @@ namespace netlist } protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: pstring m_filename; @@ -292,7 +292,7 @@ namespace netlist } protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: pstring m_pattern; @@ -307,10 +307,10 @@ namespace netlist } protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: - pstring m_str; + std::string m_str; }; class source_proc_t : public source_netlist_t @@ -325,7 +325,7 @@ namespace netlist bool parse(nlparse_t &setup, const pstring &name) override; protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: nlsetup_func m_setup_func; @@ -344,7 +344,7 @@ namespace netlist bool parse(nlparse_t &setup, const pstring &name) override; protected: - stream_ptr stream(const pstring &name) override; + plib::istream_uptr stream(const pstring &name) override; private: parser_t::token_store m_store; diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp index a633e8074f7..10f3693bea8 100644 --- a/src/lib/netlist/devices/nld_system.cpp +++ b/src/lib/netlist/devices/nld_system.cpp @@ -1,7 +1,7 @@ // license:GPL-2.0+ // copyright-holders:Couriersud /* - * nld_system.c + * nld_system.cpp * */ @@ -9,11 +9,107 @@ #include "solver/nld_matrix_solver.h" #include "nlid_system.h" +#include "plib/pstrutil.h" + namespace netlist { namespace devices { + // ----------------------------------------------------------------------------- + // extclock + // ----------------------------------------------------------------------------- + + NETLIB_OBJECT(extclock) + { + NETLIB_CONSTRUCTOR(extclock) + , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0)) + , m_pattern(*this, "PATTERN", "1,1") + , m_offset(*this, "OFFSET", nlconst::zero()) + , m_feedback(*this, "FB", NETLIB_DELEGATE(first)) + , m_Q(*this, "Q") + , m_cnt(*this, "m_cnt", 0) + , m_off(*this, "m_off", netlist_time::zero()) + { + m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + + connect("FB", "Q"); + + netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); + std::vector<pstring> pat(plib::psplit(m_pattern(),',')); + m_off = netlist_time::from_fp(m_offset()); + + std::array<std::int64_t, 32> pati = { 0 }; + + m_size = static_cast<std::uint8_t>(pat.size()); + netlist_time::mult_type total = 0; + for (unsigned i=0; i<m_size; i++) + { + pati[i] = plib::pstonum<std::int64_t>(pat[i]); + total += pati[i]; + } + netlist_time ttotal = netlist_time::zero(); + auto sm1 = static_cast<uint8_t>(m_size - 1); + for (unsigned i=0; i < sm1; i++) + { + m_inc[i] = base * pati[i]; + ttotal += m_inc[i]; + } + m_inc[sm1] = base * total - ttotal; + + } + + NETLIB_RESETI() + { + m_cnt = 0; + m_off = netlist_time::from_fp<decltype(m_offset())>(m_offset()); + m_feedback.set_delegate(NETLIB_DELEGATE(first)); + } + //NETLIB_UPDATE_PARAMI(); + + private: + + NETLIB_HANDLERI(clk2) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); + if (++m_cnt >= m_size) + m_cnt = 0; + } + + NETLIB_HANDLERI(clk2_pow2) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); + m_cnt = (++m_cnt) & (m_size-1); + } + + NETLIB_HANDLERI(first) + { + m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off()); + m_off = netlist_time::zero(); + if (++m_cnt >= m_size) + m_cnt = 0; + + // continue with optimized clock handlers .... + + if ((m_size & (m_size-1)) == 0) // power of 2? + m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2_pow2, this)); + else + m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2, this)); + } + + + param_fp_t m_freq; + param_str_t m_pattern; + param_fp_t m_offset; + + logic_input_t m_feedback; + logic_output_t m_Q; + state_var_u8 m_cnt; + std::uint8_t m_size; + state_var<netlist_time> m_off; + std::array<netlist_time, 32> m_inc; + }; + NETLIB_DEVICE_IMPL(netlistparams, "PARAMETER", "") NETLIB_DEVICE_IMPL(nc_pin, "NC_PIN", "") diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index 2e43544339a..e13786e7a28 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -116,100 +116,6 @@ namespace devices }; // ----------------------------------------------------------------------------- - // extclock - // ----------------------------------------------------------------------------- - - NETLIB_OBJECT(extclock) - { - NETLIB_CONSTRUCTOR(extclock) - , m_freq(*this, "FREQ", nlconst::magic(7159000.0 * 5.0)) - , m_pattern(*this, "PATTERN", "1,1") - , m_offset(*this, "OFFSET", nlconst::zero()) - , m_feedback(*this, "FB", NETLIB_DELEGATE(first)) - , m_Q(*this, "Q") - , m_cnt(*this, "m_cnt", 0) - , m_off(*this, "m_off", netlist_time::zero()) - { - m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); - - connect("FB", "Q"); - - netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*nlconst::two())); - std::vector<pstring> pat(plib::psplit(m_pattern(),",")); - m_off = netlist_time::from_fp(m_offset()); - - std::array<std::int64_t, 32> pati = { 0 }; - - m_size = static_cast<std::uint8_t>(pat.size()); - netlist_time::mult_type total = 0; - for (unsigned i=0; i<m_size; i++) - { - pati[i] = plib::pstonum<std::int64_t>(pat[i]); - total += pati[i]; - } - netlist_time ttotal = netlist_time::zero(); - auto sm1 = static_cast<uint8_t>(m_size - 1); - for (unsigned i=0; i < sm1; i++) - { - m_inc[i] = base * pati[i]; - ttotal += m_inc[i]; - } - m_inc[sm1] = base * total - ttotal; - - } - - NETLIB_RESETI() - { - m_cnt = 0; - m_off = netlist_time::from_fp<decltype(m_offset())>(m_offset()); - m_feedback.set_delegate(NETLIB_DELEGATE(first)); - } - //NETLIB_UPDATE_PARAMI(); - - private: - - NETLIB_HANDLERI(clk2) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); - if (++m_cnt >= m_size) - m_cnt = 0; - } - - NETLIB_HANDLERI(clk2_pow2) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt]); - m_cnt = (++m_cnt) & (m_size-1); - } - - NETLIB_HANDLERI(first) - { - m_Q.push((m_cnt & 1) ^ 1, m_inc[m_cnt] + m_off()); - m_off = netlist_time::zero(); - if (++m_cnt >= m_size) - m_cnt = 0; - - // continue with optimized clock handlers .... - - if ((m_size & (m_size-1)) == 0) // power of 2? - m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2_pow2, this)); - else - m_feedback.set_delegate(nldelegate(&NETLIB_NAME(extclock)::clk2, this)); - } - - - param_fp_t m_freq; - param_str_t m_pattern; - param_fp_t m_offset; - - logic_input_t m_feedback; - logic_output_t m_Q; - state_var_u8 m_cnt; - std::uint8_t m_size; - state_var<netlist_time> m_off; - std::array<netlist_time, 32> m_inc; - }; - - // ----------------------------------------------------------------------------- // Special support devices ... // ----------------------------------------------------------------------------- diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 12219353283..008426e4008 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -377,12 +377,12 @@ namespace devices pstring header = desc[0]; - std::vector<pstring> io(plib::psplit(header,"|")); + std::vector<pstring> io(plib::psplit(header,'|')); // checks nl_assert_always(io.size() == 2, "too many '|'"); - std::vector<pstring> inout(plib::psplit(io[0], ",")); + std::vector<pstring> inout(plib::psplit(io[0], ',')); nl_assert_always(inout.size() == m_num_bits, "bitcount wrong"); - std::vector<pstring> outputs(plib::psplit(io[1], ",")); + std::vector<pstring> outputs(plib::psplit(io[1], ',')); nl_assert_always(outputs.size() == m_NO, "output count wrong"); #if !USE_TT_ALTERNATIVE @@ -582,14 +582,14 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable) while (!ttline.empty()) { - std::vector<pstring> io(plib::psplit(ttline,"|")); + std::vector<pstring> io(plib::psplit(ttline,'|')); // checks nl_assert_always(io.size() == 3, "io.count mismatch"); - std::vector<pstring> inout(plib::psplit(io[0], ",")); + std::vector<pstring> inout(plib::psplit(io[0], ',')); nl_assert_always(inout.size() == m_num_bits, "number of bits not matching"); - std::vector<pstring> out(plib::psplit(io[1], ",")); + std::vector<pstring> out(plib::psplit(io[1], ',')); nl_assert_always(out.size() == m_NO, "output count not matching"); - std::vector<pstring> times(plib::psplit(io[2], ",")); + std::vector<pstring> times(plib::psplit(io[2], ',')); nl_assert_always(times.size() == m_NO, "timing count not matching"); tt_bitset val = 0; @@ -700,7 +700,7 @@ namespace factory ENTRY(12, props); default: pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no); - nl_assert_always(false, msg.c_str()); + nl_assert_always(false, putf8string(msg).c_str()); } ret->m_desc = desc.desc; ret->m_family_name = (!desc.family.empty() ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY())); diff --git a/src/lib/netlist/macro/nlm_cd4xxx_lib.cpp b/src/lib/netlist/macro/nlm_cd4xxx_lib.cpp index 126fc42e883..13c80aa391b 100644 --- a/src/lib/netlist/macro/nlm_cd4xxx_lib.cpp +++ b/src/lib/netlist/macro/nlm_cd4xxx_lib.cpp @@ -480,7 +480,7 @@ static NETLIST_START(MM5837_DIP) A.VDD, /* VDD |1 ++ 8| NC */ NC.I, A.VGG, /* VGG |2 7| NC */ NC.I, A.OUT, /* OUT |3 6| NC */ NC.I, - A.VSS, /* VSS |4 5| NC */ NC.I, + A.VSS, /* VSS |4 5| NC */ NC.I /* +--------+ */ ) NETLIST_END() diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index 91e192240df..7016d482a92 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -26,11 +26,6 @@ namespace netlist // callbacks_t // ---------------------------------------------------------------------------------------- - std::unique_ptr<plib::dynlib_base> callbacks_t:: static_solver_lib() const - { - return std::make_unique<plib::dynlib_static>(nullptr); - } - // ---------------------------------------------------------------------------------------- // queue_t // ---------------------------------------------------------------------------------------- @@ -108,14 +103,11 @@ namespace netlist // ---------------------------------------------------------------------------------------- netlist_state_t::netlist_state_t(const pstring &name, - host_arena::unique_ptr<callbacks_t> &&callbacks) - : m_callbacks(std::move(callbacks)) // Order is important here - , m_log(*m_callbacks) + plib::plog_delegate logger) + : m_log(logger) , m_extended_validation(false) , m_dummy_version(1) { - m_lib = m_callbacks->static_solver_lib(); - m_setup = plib::make_unique<setup_t, host_arena>(*this); // create the run interface m_netlist = plib::make_unique<netlist_t>(m_pool, *this, name); @@ -163,6 +155,11 @@ namespace netlist #endif } + void netlist_state_t::set_static_solver_lib(std::unique_ptr<plib::dynlib_base> &&lib) + { + m_lib = std::move(lib); + }; + void netlist_t::stop() { @@ -908,7 +905,7 @@ namespace netlist } - plib::psource_t::stream_ptr param_data_t::stream() + plib::istream_uptr param_data_t::stream() { return device().state().parser().get_data_stream(str()); } diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h index 02cce0db128..89ce603ac52 100644 --- a/src/lib/netlist/nl_factory.h +++ b/src/lib/netlist/nl_factory.h @@ -12,7 +12,7 @@ #include "plib/palloc.h" #include "plib/pmempool.h" #include "plib/ptypes.h" -#include "plib/putil.h" +#include "plib/psource.h" #include <tuple> #include <utility> diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp index 665327a1001..f032a50076e 100644 --- a/src/lib/netlist/nl_parser.cpp +++ b/src/lib/netlist/nl_parser.cpp @@ -65,14 +65,14 @@ parser_t::parser_t(nlparse_t &setup) } -bool parser_t::parse(plib::psource_t::stream_ptr &&strm, const pstring &nlname) +bool parser_t::parse(plib::istream_uptr &&strm, const pstring &nlname) { token_store tokstor; parse_tokens(std::move(strm), tokstor); return parse(tokstor, nlname); } -void parser_t::parse_tokens(plib::psource_t::stream_ptr &&strm, token_store &tokstor) +void parser_t::parse_tokens(plib::istream_uptr &&strm, token_store &tokstor) { plib::putf8_reader u8reader(strm.release_stream()); m_tokenizer.append_to_store(&u8reader, tokstor); @@ -88,7 +88,7 @@ bool parser_t::parse(const token_store &tokstor, const pstring &nlname) { // FIXME: line numbers in cached local netlists are wrong // need to process raw tokens here. - token_t token = get_token(); + token_t token = get_token_raw(); if (token.is_type(token_type::ENDOFFILE)) { return false; @@ -96,13 +96,13 @@ bool parser_t::parse(const token_store &tokstor, const pstring &nlname) if (token.is(m_tok_NETLIST_END) || token.is(m_tok_TRUTHTABLE_END)) { - require_token(m_tok_paren_left); if (!in_nl) error (MF_PARSER_UNEXPECTED_1(token.str())); else { in_nl = false; } + require_token(m_tok_paren_left); require_token(m_tok_paren_right); m_cur_local->push_back(token); @@ -131,11 +131,10 @@ bool parser_t::parse(const token_store &tokstor, const pstring &nlname) // create a new cached local store m_local.emplace(name.str(), token_store()); m_cur_local = &m_local[name.str()]; - m_cur_local->push_back(token_t(token_type::LINEMARKER)); auto sl = sourceloc(); - auto num = plib::pfmt("{1}")(sl.line()); - m_cur_local->push_back(token_t(token_type::NUMBER, num)); - m_cur_local->push_back(token_t(token_type::STRING, sl.file_name())); + auto li = plib::pfmt("# {1} \"{2}\"")(sl.line(), sl.file_name()); + + m_cur_local->push_back(token_t(token_type::LINEMARKER, li)); m_cur_local->push_back(token); m_cur_local->push_back(token_t(m_tok_paren_left)); m_cur_local->push_back(name); @@ -152,7 +151,8 @@ bool parser_t::parse(const token_store &tokstor, const pstring &nlname) } else if (!in_nl) { - if (!token.is(m_tok_static)) + if (!token.is(m_tok_static) && !token.is_type(token_type::SOURCELINE) + && !token.is_type(token_type::LINEMARKER)) error(MF_EXPECTED_NETLIST_START_1(token.str())); } else @@ -464,14 +464,14 @@ void parser_t::netdev_defparam() if (tok.is_type(token_type::STRING)) { m_setup.log().debug("Parser: DefParam: {1} {2}\n", param, tok.str()); - m_setup.defparam(param, tok.str()); + m_setup.register_defparam(param, tok.str()); require_token(m_tok_paren_right); } else { auto val = stringify_expression(tok); m_setup.log().debug("Parser: Param: {1} {2}\n", param, val); - m_setup.defparam(param, val); + m_setup.register_defparam(param, val); require_token(tok, m_tok_paren_right); } } diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h index 99a42daed23..d186effc57c 100644 --- a/src/lib/netlist/nl_parser.h +++ b/src/lib/netlist/nl_parser.h @@ -25,9 +25,9 @@ namespace netlist parser_t(nlparse_t &setup); - bool parse(plib::psource_t::stream_ptr &&strm, const pstring &nlname); + bool parse(plib::istream_uptr &&strm, const pstring &nlname); bool parse(const token_store &tokstor, const pstring &nlname); - void parse_tokens(plib::psource_t::stream_ptr &&strm, token_store &tokstor); + void parse_tokens(plib::istream_uptr &&strm, token_store &tokstor); protected: void parse_netlist(const pstring &nlname); diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 39d9144cd6d..a2e1734c24c 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -13,6 +13,7 @@ #include "plib/penum.h" #include "plib/pstonum.h" #include "plib/putil.h" +#include "plib/pstrutil.h" #include "solver/nld_solver.h" @@ -39,7 +40,7 @@ namespace netlist void nlparse_t::register_dip_alias_arr(const pstring &terms) { - std::vector<pstring> list(plib::psplit(terms,", ")); + const auto list(plib::psplit(terms,pstring(", "))); if (list.empty() || (list.size() % 2) == 1) { log().fatal(MF_DIP_PINS_MUST_BE_AN_EQUAL_NUMBER_OF_PINS_1(build_fqn(""))); @@ -93,7 +94,7 @@ namespace netlist m_abstract.m_device_factory.insert(m_abstract.m_device_factory.end(), {key, f}); - auto paramlist = plib::psplit(f->param_desc(), ","); + auto paramlist = plib::psplit(f->param_desc(), ','); if (!params_and_connections.empty()) { @@ -169,7 +170,7 @@ namespace netlist void nlparse_t::register_link_arr(const pstring &terms) { - std::vector<pstring> list(plib::psplit(terms,", ")); + const auto list(plib::psplit(terms,pstring(", "))); if (list.size() < 2) { log().fatal(MF_NET_C_NEEDS_AT_LEAST_2_TERMINAL()); @@ -206,7 +207,7 @@ namespace netlist m_namespace_stack.pop(); } - void nlparse_t::register_param(const pstring ¶m, const nl_fptype value) + void nlparse_t::register_param_fp(const pstring ¶m, const nl_fptype value) { if (plib::abs(value - plib::floor(value)) > nlconst::magic(1e-30) || plib::abs(value) > nlconst::magic(1e9)) @@ -247,7 +248,7 @@ namespace netlist } } - void nlparse_t::defparam(const pstring &name, const pstring &def) + void nlparse_t::register_defparam(const pstring &name, const pstring &def) { // strip " from stringified strings pstring val(def); @@ -358,7 +359,7 @@ namespace netlist return parser.parse(tokens, name); } - bool nlparse_t::parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name) + bool nlparse_t::parse_stream(plib::istream_uptr &&istrm, const pstring &name) { #if 0 auto key = istrm.filename(); @@ -369,28 +370,21 @@ namespace netlist } else { - //printf("searching %s\n", name.c_str()); - plib::ppreprocessor y(m_includes, &m_defines); - y.process(std::move(istrm), istrm.filename()); - - auto abc = std::make_unique<std::stringstream>(); - plib::copystream(*abc, y); + auto preprocessed = std::make_unique<std::stringstream>( + plib::ppreprocessor(m_includes, &m_defines).process(std::move(istrm), istrm.filename())); parser_t::token_store &st = m_source_cache[key]; parser_t parser(*this); - parser.parse_tokens(plib::psource_t::stream_ptr(std::move(abc), key), st); + parser.parse_tokens(plib::istream_uptr(std::move(preprocessed), key), st); return parser.parse(st, name); } #else - plib::ppreprocessor y(m_includes, &m_defines); - y.process(std::move(istrm), istrm.filename()); - - auto abc = std::make_unique<std::stringstream>(); - plib::copystream(*abc, y); + auto preprocessed = std::make_unique<std::stringstream>(putf8string( + plib::ppreprocessor(m_includes, &m_defines).process(std::move(istrm), istrm.filename()))); parser_t::token_store st; parser_t parser(*this); - parser.parse_tokens(plib::psource_t::stream_ptr(std::move(abc), istrm.filename()), st); + parser.parse_tokens(plib::istream_uptr(std::move(preprocessed), istrm.filename()), st); return parser.parse(st, name); #endif } @@ -461,13 +455,13 @@ namespace netlist // Sources // ---------------------------------------------------------------------------------------- - plib::psource_t::stream_ptr nlparse_t::get_data_stream(const pstring &name) + plib::istream_uptr nlparse_t::get_data_stream(const pstring &name) { auto strm = m_sources.get_stream<source_data_t>(name); if (!strm.empty()) return strm; log().warning(MW_DATA_1_NOT_FOUND(name)); - return plib::psource_t::stream_ptr(); + return plib::istream_uptr(); } // ---------------------------------------------------------------------------------------- @@ -1310,7 +1304,7 @@ void models_t::model_parse(const pstring &model_in, map_t &map) // FIMXE: Not optimal remainder = plib::left(remainder, remainder.size() - 1); - std::vector<pstring> pairs(plib::psplit(remainder," ", true)); + const auto pairs(plib::psplit(remainder,' ', true)); for (const pstring &pe : pairs) { auto pose = pe.find('='); @@ -1552,7 +1546,7 @@ void setup_t::prepare_to_run() if (!envlog.empty()) { - std::vector<pstring> loglist(plib::psplit(envlog, ":")); + const auto loglist(plib::psplit(envlog, ':')); m_parser.register_dynamic_log_devices(loglist); } @@ -1707,44 +1701,44 @@ bool source_netlist_t::parse(nlparse_t &setup, const pstring &name) return (!strm.empty()) ? setup.parse_stream(std::move(strm), name) : false; } -source_string_t::stream_ptr source_string_t::stream(const pstring &name) +plib::istream_uptr source_string_t::stream(const pstring &name) { plib::unused_var(name); - source_string_t::stream_ptr ret(std::make_unique<std::istringstream>(m_str), name); - ret.stream().imbue(std::locale::classic()); + plib::istream_uptr ret(std::make_unique<std::istringstream>(putf8string(m_str)), name); + ret->imbue(std::locale::classic()); return ret; } -source_mem_t::stream_ptr source_mem_t::stream(const pstring &name) +plib::istream_uptr source_mem_t::stream(const pstring &name) { plib::unused_var(name); - source_mem_t::stream_ptr ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary), name); - ret.stream().imbue(std::locale::classic()); + plib::istream_uptr ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary), name); + ret->imbue(std::locale::classic()); return ret; } -source_file_t::stream_ptr source_file_t::stream(const pstring &name) +plib::istream_uptr source_file_t::stream(const pstring &name) { plib::unused_var(name); auto f = std::make_unique<plib::ifstream>(plib::filesystem::u8path(m_filename)); if (f->is_open()) { - return stream_ptr(std::move(f), m_filename); + return plib::istream_uptr(std::move(f), m_filename); } else - return stream_ptr(); + return plib::istream_uptr(); } -source_file_t::stream_ptr source_pattern_t::stream(const pstring &name) +plib::istream_uptr source_pattern_t::stream(const pstring &name) { pstring filename = plib::pfmt(m_pattern)(name); auto f = std::make_unique<plib::ifstream>(plib::filesystem::u8path(filename)); if (f->is_open()) { - return stream_ptr(std::move(f), filename); + return plib::istream_uptr(std::move(f), filename); } else - return stream_ptr(); + return plib::istream_uptr(); } @@ -1759,10 +1753,10 @@ bool source_proc_t::parse(nlparse_t &setup, const pstring &name) return false; } -source_proc_t::stream_ptr source_proc_t::stream(const pstring &name) +plib::istream_uptr source_proc_t::stream(const pstring &name) { plib::unused_var(name); - return stream_ptr(); + return plib::istream_uptr(); } bool source_token_t::parse(nlparse_t &setup, const pstring &name) @@ -1776,10 +1770,10 @@ bool source_token_t::parse(nlparse_t &setup, const pstring &name) return false; } -source_proc_t::stream_ptr source_token_t::stream(const pstring &name) +plib::istream_uptr source_token_t::stream(const pstring &name) { plib::unused_var(name); - return stream_ptr(); + return plib::istream_uptr(); } } // namespace netlist diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h index 39dfb2dd747..5cb312adfd7 100644 --- a/src/lib/netlist/nl_setup.h +++ b/src/lib/netlist/nl_setup.h @@ -13,7 +13,7 @@ #include "plib/ppreprocessor.h" #include "plib/pstream.h" #include "plib/pstring.h" -#include "plib/putil.h" +#include "plib/psource.h" #include "nl_config.h" #include "nl_parser.h" @@ -57,8 +57,8 @@ #define PARAM(name, val) \ setup.register_param(NET_STR(name), NET_STR(val)); -#define DEFPARAM(name, val) \ - setup.defparam(NET_STR(name), NET_STR(val)); +#define DEFPARAM(name, val) \ + setup.register_defparam(NET_STR(name), NET_STR(val)); #define HINT(name, val) \ setup.register_hint(# name , ".HINT_" # val); @@ -191,13 +191,15 @@ namespace netlist void register_link_fqn(const pstring &sin, const pstring &sout); void register_param(const pstring ¶m, const pstring &value); - void register_param(const pstring ¶m, nl_fptype value); + + // DEFPARAM support + void register_defparam(const pstring &name, const pstring &def); template <typename T> std::enable_if_t<plib::is_arithmetic<T>::value> - register_param_val(const pstring ¶m, T value) + register_param(const pstring ¶m, T value) { - register_param(param, plib::narrow_cast<nl_fptype>(value)); + register_param_fp(param, plib::narrow_cast<nl_fptype>(value)); } void register_lib_entry(const pstring &name, const pstring &def_params, plib::source_location &&loc); @@ -208,41 +210,30 @@ namespace netlist template <typename S, typename... Args> void register_source(Args&&... args) { - static_assert(std::is_base_of<plib::psource_t, S>::value, "S must inherit from plib::psource_t"); - - auto src(std::make_unique<S>(std::forward<Args>(args)...)); - m_sources.add_source(std::move(src)); + m_sources.add_source<S>(std::forward<Args>(args)...); } void register_source_proc(const pstring &name, nlsetup_func func); void truthtable_create(tt_desc &desc, const pstring &def_params, plib::source_location &&loc); - // handle namespace - - void namespace_push(const pstring &aname); - void namespace_pop(); - pstring namespace_prefix() const; - pstring build_fqn(const pstring &obj_name) const; - // include other files void include(const pstring &netlist_name); - // used from netlist.cpp (mame) - bool device_exists(const pstring &name) const; + // handle namespace + + void namespace_push(const pstring &aname); + void namespace_pop(); // FIXME: used by source_t - need a different approach at some time - bool parse_stream(plib::psource_t::stream_ptr &&istrm, const pstring &name); + bool parse_stream(plib::istream_uptr &&istrm, const pstring &name); bool parse_tokens(const parser_t::token_store &tokens, const pstring &name); template <typename S, typename... Args> void add_include(Args&&... args) { - static_assert(std::is_base_of<plib::psource_t, S>::value, "S must inherit from plib::psource_t"); - - auto src(std::make_unique<S>(std::forward<Args>(args)...)); - m_includes.add_source(std::move(src)); + m_includes.add_source<S>(std::forward<Args>(args)...); } void add_define(const pstring &def, const pstring &val) @@ -252,9 +243,6 @@ namespace netlist void add_define(const pstring &defstr); - // DEFPARAM support - void defparam(const pstring &name, const pstring &def); - // register a list of logs void register_dynamic_log_devices(const std::vector<pstring> &loglist); @@ -264,19 +252,24 @@ namespace netlist log_type &log() noexcept { return m_log; } const log_type &log() const noexcept { return m_log; } - plib::psource_t::stream_ptr get_data_stream(const pstring &name); + plib::istream_uptr get_data_stream(const pstring &name); private: + pstring namespace_prefix() const; + pstring build_fqn(const pstring &obj_name) const; + void register_param_fp(const pstring ¶m, nl_fptype value); + bool device_exists(const pstring &name) const; + // FIXME: stale? - remove later void remove_connections(const pstring &pin); plib::ppreprocessor::defines_map_type m_defines; - plib::psource_collection_t<> m_includes; + plib::psource_collection_t m_includes; std::stack<pstring> m_namespace_stack; - plib::psource_collection_t<> m_sources; + plib::psource_collection_t m_sources; detail::abstract_t & m_abstract; - std::unordered_map<pstring, parser_t::token_store> m_source_cache; + //std::unordered_map<pstring, parser_t::token_store> m_source_cache; log_type &m_log; unsigned m_frontier_cnt; }; diff --git a/src/lib/netlist/nltypes.h b/src/lib/netlist/nltypes.h index d22c634ab27..422a9ddfac4 100644 --- a/src/lib/netlist/nltypes.h +++ b/src/lib/netlist/nltypes.h @@ -32,7 +32,7 @@ namespace plib struct aligned_arena; class dynlib_base; - template<class T, bool debug_enabled> + template<bool debug_enabled> class plog_base; struct plog_level; @@ -164,36 +164,7 @@ namespace netlist plib::aligned_arena>; using host_arena = plib::aligned_arena; - /// \brief Interface definition for netlist callbacks into calling code - /// - /// A class inheriting from netlist_callbacks_t has to be passed to the netlist_t - /// constructor. Netlist does processing during construction and thus needs - /// the object passed completely constructed. - /// - class callbacks_t - { - public: - - callbacks_t() = default; - virtual ~callbacks_t() = default; - - PCOPYASSIGNMOVE(callbacks_t, default) - - /// \brief logging callback. - /// - virtual void vlog(const plib::plog_level &l, const pstring &ls) const noexcept = 0; - - /// \brief provide library with static solver implementations. - /// - /// By default no static solvers are provided since these are - /// determined by the specific use case. It is up to the implementor - /// of a callbacks_t implementation to optionally provide such a collection - /// of symbols. - /// - virtual std::unique_ptr<plib::dynlib_base> static_solver_lib() const; - }; - - using log_type = plib::plog_base<callbacks_t, NL_DEBUG>; + using log_type = plib::plog_base<NL_DEBUG>; //============================================================ // Types needed by various includes diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h index 2c2b0fc4270..2defe3bdfcb 100644 --- a/src/lib/netlist/plib/parray.h +++ b/src/lib/netlist/plib/parray.h @@ -11,13 +11,13 @@ #include "palloc.h" #include "pconfig.h" #include "pexception.h" -#include "pstrutil.h" #include <array> #include <memory> #include <type_traits> #include <utility> #include <vector> +#include <string> namespace plib { @@ -85,7 +85,7 @@ namespace plib { { if ((SIZE < 0 && size > SIZEABS()) || (SIZE > 0 && size != SIZEABS())) - throw pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZE)); + throw pexception(pfmt("parray: size error: {1} > {2}")(size, SIZE)); } template <int X = SIZE > @@ -94,7 +94,7 @@ namespace plib { { if ((SIZE < 0 && size > SIZEABS()) || (SIZE > 0 && size != SIZEABS())) - throw pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZE)); + throw pexception(pfmt("parray: size error: {1} > {2}")(size, SIZE)); m_a.fill(val); } diff --git a/src/lib/netlist/plib/pdynlib.cpp b/src/lib/netlist/plib/pdynlib.cpp index 6268ad450de..c33120049d5 100644 --- a/src/lib/netlist/plib/pdynlib.cpp +++ b/src/lib/netlist/plib/pdynlib.cpp @@ -30,7 +30,7 @@ dynlib::dynlib(const pstring &libname) #else //printf("loading <%s>\n", libname.c_str()); if (!libname.empty()) - m_lib = dlopen(libname.c_str(), RTLD_LAZY); + m_lib = dlopen(putf8string(libname).c_str(), RTLD_LAZY); else m_lib = dlopen(nullptr, RTLD_LAZY); #endif @@ -56,7 +56,7 @@ dynlib::dynlib(const pstring &path, const pstring &libname) #else //printf("loading <%s>\n", libname.c_str()); if (!libname.empty()) - m_lib = dlopen(libname.c_str(), RTLD_LAZY); + m_lib = dlopen(putf8string(libname).c_str(), RTLD_LAZY); else m_lib = dlopen(nullptr, RTLD_LAZY); #endif @@ -85,7 +85,7 @@ void *dynlib::getsym_p(const pstring &name) const noexcept #ifdef _WIN32 return (void *) GetProcAddress((HMODULE) m_lib, name.c_str()); #else - return dlsym(m_lib, name.c_str()); + return dlsym(m_lib, putf8string(name).c_str()); #endif } diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h index 91ec6e65cca..2023fb91c38 100644 --- a/src/lib/netlist/plib/pexception.h +++ b/src/lib/netlist/plib/pexception.h @@ -40,7 +40,7 @@ namespace plib { explicit pexception(const pstring &text); const pstring &text() const noexcept { return m_text; } - const char* what() const noexcept override { return m_text.c_str(); } + const char* what() const noexcept override { return putf8string(m_text).c_str(); } private: pstring m_text; diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h index 2c3773b1421..9f3ff382583 100644 --- a/src/lib/netlist/plib/pfmtlog.h +++ b/src/lib/netlist/plib/pfmtlog.h @@ -11,6 +11,7 @@ #include "penum.h" #include "pstring.h" #include "ptypes.h" +#include "ppmf.h" #include <limits> #include <locale> @@ -172,12 +173,39 @@ namespace plib { }; template<> + struct ptype_traits<const char16_t *> : ptype_traits_base<const char16_t *> + { + static char32_t fmt_spec() { return 's'; } + static inline void streamify(std::ostream &s, const char16_t *v) + { + const putf16string su16(v); + s << putf8string(su16).c_str(); + } + }; + + template<> struct ptype_traits<std::string> : ptype_traits_base<std::string> { static char32_t fmt_spec() { return 's'; } }; template<> + struct ptype_traits<putf8string> : ptype_traits_base<putf8string> + { + static char32_t fmt_spec() { return 's'; } + }; + + template<> + struct ptype_traits<putf16string> : ptype_traits_base<putf16string> + { + static char32_t fmt_spec() { return 's'; } + static inline void streamify(std::ostream &s, const putf16string &v) + { + s << putf8string(v).c_str(); + } + }; + + template<> struct ptype_traits<const void *> : ptype_traits_base<const void *> { static char32_t fmt_spec() { return 'p'; } @@ -255,7 +283,7 @@ namespace plib { friend std::ostream& operator<<(std::ostream &ostrm, const pfmt &fmt) { - ostrm << fmt.m_str; + ostrm << putf8string(fmt.m_str); return ostrm; } @@ -290,7 +318,7 @@ namespace plib { if (ret.ret>=0) { ptype_traits<typename std::decay<T>::type>::streamify(strm, std::forward<T>(v)); - const pstring ps(strm.str()); + const pstring ps(putf8string(strm.str())); m_str = m_str.substr(0, ret.p) + ps + m_str.substr(ret.p + ret.sl); } } while (ret.ret == 1); @@ -358,12 +386,16 @@ namespace plib { }; - template <class T, plog_level::E L, bool build_enabled = true> - class plog_channel : public pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled> + using plog_delegate = plib::pmfp<void, plog_level, const pstring &>; + + template <plog_level::E L, bool build_enabled = true> + class plog_channel : public pfmt_writer_t<plog_channel<L, build_enabled>, build_enabled> { - friend class pfmt_writer_t<plog_channel<T, L, build_enabled>, build_enabled>; + friend class pfmt_writer_t<plog_channel<L, build_enabled>, build_enabled>; public: - explicit plog_channel(T &b) : pfmt_writer_t<plog_channel, build_enabled>(), m_base(b) { } + explicit plog_channel(plog_delegate logger) + : pfmt_writer_t<plog_channel, build_enabled>() + , m_logger(logger) { } PCOPYASSIGNMOVE(plog_channel, delete) @@ -372,36 +404,36 @@ namespace plib { protected: void vdowrite(const pstring &ls) const noexcept { - m_base.vlog(L, ls); + m_logger(L, ls); } private: - T &m_base; + plog_delegate m_logger; }; - template<class T, bool debug_enabled> + template<bool debug_enabled> class plog_base { public: - explicit plog_base(T &proxy) - : debug(proxy), - info(proxy), - verbose(proxy), - warning(proxy), - error(proxy), - fatal(proxy) + explicit plog_base(plog_delegate logger) + : debug(logger), + info(logger), + verbose(logger), + warning(logger), + error(logger), + fatal(logger) {} PCOPYASSIGNMOVE(plog_base, default) virtual ~plog_base() noexcept = default; - plog_channel<T, plog_level::DEBUG, debug_enabled> debug; - plog_channel<T, plog_level::INFO> info; - plog_channel<T, plog_level::VERBOSE> verbose; - plog_channel<T, plog_level::WARNING> warning; - plog_channel<T, plog_level::ERROR> error; - plog_channel<T, plog_level::FATAL> fatal; + plog_channel<plog_level::DEBUG, debug_enabled> debug; + plog_channel<plog_level::INFO> info; + plog_channel<plog_level::VERBOSE> verbose; + plog_channel<plog_level::WARNING> warning; + plog_channel<plog_level::ERROR> error; + plog_channel<plog_level::FATAL> fatal; }; struct perrmsg diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp index 526243d4e90..5a00844becc 100644 --- a/src/lib/netlist/plib/pfunction.cpp +++ b/src/lib/netlist/plib/pfunction.cpp @@ -101,7 +101,7 @@ namespace plib { template <typename NT> void pfunction<NT>::compile_postfix(const pstring &expr, const inputs_container &inputs) noexcept(false) { - std::vector<pstring> cmds(plib::psplit(expr, " ")); + std::vector<pstring> cmds(plib::psplit(expr, ' ')); compile_postfix(inputs, cmds, expr); } diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp index c22076f6d0c..c8b99f12077 100644 --- a/src/lib/netlist/plib/poptions.cpp +++ b/src/lib/netlist/plib/poptions.cpp @@ -95,14 +95,14 @@ namespace plib { for (std::size_t i=1; i < argv.size(); ) { - putf8string arg(argv[i]); + pstring arg(argv[i]); option *opt = nullptr; - putf8string opt_arg; + pstring opt_arg; bool has_equal_arg = false; if (!seen_other_args && plib::startsWith(arg, "--")) { - auto v = psplit(arg.substr(2),"="); + auto v = psplit(arg.substr(2),'='); if (!v.empty() && !v[0].empty()) { opt = getopt_long(v[0]); @@ -171,13 +171,13 @@ namespace plib { pstring options::split_paragraphs(const pstring &text, unsigned width, unsigned indent, unsigned firstline_indent, const pstring &line_end) { - auto paragraphs = psplit(text,"\n"); + auto paragraphs = psplit(text,'\n'); pstring ret(""); for (auto &p : paragraphs) { pstring line = plib::rpad(pstring(""), pstring(" "), firstline_indent); - for (auto &s : psplit(p, " ")) + for (auto &s : psplit(p, ' ')) { if (line.length() + s.length() > width) { @@ -263,7 +263,7 @@ namespace plib { ex += split_paragraphs(example->help(), width, 4, 4) + "\n\n"; } } - if (ex.length() > 0) + if (!ex.empty()) { ret += "\n\nExamples:\n\n" + ex; } diff --git a/src/lib/netlist/plib/ppreprocessor.cpp b/src/lib/netlist/plib/ppreprocessor.cpp index 9daf9fa9836..320cbe23857 100644 --- a/src/lib/netlist/plib/ppreprocessor.cpp +++ b/src/lib/netlist/plib/ppreprocessor.cpp @@ -13,14 +13,12 @@ namespace plib { // A simple preprocessor // ---------------------------------------------------------------------------------------- - ppreprocessor::ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines) - : std::istream(new readbuffer(this)) - , m_sources(sources) + ppreprocessor::ppreprocessor(psource_collection_t &sources, defines_map_type *defines) + : m_sources(sources) , m_if_flag(0) , m_if_seen(0) , m_elif(0) , m_if_level(0) - , m_pos(0) , m_state(PROCESS) , m_comment(false) { @@ -88,7 +86,7 @@ namespace plib { /// /// \return next token /// - pstring next() + const pstring &next() { skip_ws(); if (m_pos >= m_tokens.size()) @@ -100,21 +98,21 @@ namespace plib { /// /// \return next token /// - pstring next_ws() + const pstring &next_ws() { if (m_pos >= m_tokens.size()) error("unexpected end of line"); return m_tokens[m_pos++]; } - pstring peek_ws() + const pstring &peek_ws() { if (m_pos >= m_tokens.size()) error("unexpected end of line"); return m_tokens[m_pos]; } - pstring last() + const pstring &last() { if (m_pos == 0) error("no last token at beginning of line"); @@ -128,12 +126,12 @@ namespace plib { return (m_pos >= m_tokens.size()); } - void error(pstring err) + void error(const pstring &err) { m_parent->error(err); } private: - L m_tokens; + const L m_tokens; PP *m_parent; std::size_t m_pos; }; @@ -294,7 +292,7 @@ namespace plib { bool ppreprocessor::is_valid_token(const pstring &str) { - if (str.length() == 0) + if (str.empty()) return false; pstring::value_type c(str.at(0)); return ((c>='a' && c<='z') || (c>='A' && c<='Z') || c == '_'); @@ -399,6 +397,7 @@ namespace plib { return ret; } +#if 0 pstring ppreprocessor::process_comments(pstring line) { bool in_string = false; @@ -440,12 +439,64 @@ namespace plib { } return ret; } +#else + pstring ppreprocessor::process_comments(const pstring &line) + { + bool in_string = false; - std::pair<pstring,bool> ppreprocessor::process_line(pstring line) + pstring ret = ""; + for (auto c = line.begin(); c != line.end(); ) + { + if (!m_comment) + { + if (*c == '"') + { + in_string = !in_string; + ret += *c; + } + else if (in_string && *c == '\\') + { + ret += *c; + ++c; + if (c == line.end()) + break; + ret += *c; + } + else if (!in_string && *c == '/') + { + ++c; + if (c == line.end()) + break; + if (*c == '*') + m_comment = true; + else if (*c == '/') + break; + else + ret += *c; + } + else + ret += *c; + } + else + if (*c == '*') + { + c++; + if (c == line.end()) + break; + if (*c == '/') + m_comment = false; + } + c++; + } + return ret; + } +#endif + + std::pair<pstring,bool> ppreprocessor::process_line(const pstring &line_in) { - bool line_cont = plib::right(line, 1) == "\\"; - if (line_cont) - line = plib::left(line, line.size() - 1); + bool line_cont = plib::right(line_in, 1) == "\\"; + + pstring line = line_cont ? plib::left(line_in, line_in.size() - 1) : line_in; if (m_state == LINE_CONTINUATION) m_line += line; @@ -462,10 +513,10 @@ namespace plib { line = process_comments(m_line); - pstring lt = plib::trim(plib::replace_all(line, "\t", " ")); + pstring lt = plib::trim(plib::replace_all(line, '\t', ' ')); if (plib::startsWith(lt, "#")) { - string_list lti(psplit(lt, " ", true)); + string_list lti(psplit(lt, ' ', true)); if (lti[0] == "#if") { m_if_level++; @@ -674,23 +725,23 @@ namespace plib { void ppreprocessor::push_out(const pstring &s) { - m_outbuf += decltype(m_outbuf)(s.c_str()); + m_outbuf += s; if (m_debug_out) - std::cerr << s; + std::cerr << putf8string(s); } void ppreprocessor::process_stack() { while (!m_stack.empty()) { - pstring line; + putf8string line; pstring linemarker = pfmt("# {1} \"{2}\"\n")(m_stack.back().m_lineno, m_stack.back().m_name); push_out(linemarker); bool last_skipped=false; while (m_stack.back().m_reader.readline(line)) { m_stack.back().m_lineno++; - auto r(process_line(line)); + auto r(process_line(pstring(line))); if (r.second) { if (last_skipped) diff --git a/src/lib/netlist/plib/ppreprocessor.h b/src/lib/netlist/plib/ppreprocessor.h index 4b460d42ec8..358fda53c51 100644 --- a/src/lib/netlist/plib/ppreprocessor.h +++ b/src/lib/netlist/plib/ppreprocessor.h @@ -11,7 +11,8 @@ #include "pstream.h" #include "pstring.h" -#include "putil.h" // psource_t +#include "psource.h" +#include "putil.h" #include <istream> #include <unordered_map> @@ -19,7 +20,7 @@ namespace plib { - class ppreprocessor : public std::istream + class ppreprocessor { public: @@ -41,32 +42,11 @@ namespace plib { using defines_map_type = std::unordered_map<pstring, define_t>; - explicit ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines = nullptr); - - PCOPYASSIGN(ppreprocessor, delete) - ppreprocessor &operator=(ppreprocessor &&src) = delete; - - ppreprocessor(ppreprocessor &&s) noexcept - : std::istream(new readbuffer(this)) - , m_defines(std::move(s.m_defines)) - , m_sources(s.m_sources) - , m_expr_sep(std::move(s.m_expr_sep)) - , m_if_flag(s.m_if_flag) - , m_if_level(s.m_if_level) - , m_stack(std::move(s.m_stack)) - , m_outbuf(std::move(s.m_outbuf)) - , m_pos(s.m_pos) - , m_state(s.m_state) - , m_line(std::move(s.m_line)) - , m_comment(s.m_comment) - , m_debug_out(s.m_debug_out) - { - } + explicit ppreprocessor(psource_collection_t &sources, defines_map_type *defines = nullptr); - ~ppreprocessor() override - { - delete rdbuf(); - } + PCOPYASSIGNMOVE(ppreprocessor, delete) + + ~ppreprocessor() = default; /// \brief process stream /// @@ -76,51 +56,16 @@ namespace plib { /// and pass this to ppreprocessor. /// template <typename T> - ppreprocessor & process(T &&istrm, const pstring &filename) + pstring process(T &&istrm, const pstring &filename) { + m_outbuf.clear(); m_stack.emplace_back(input_context(istrm.release_stream(),plib::util::path(filename), filename)); process_stack(); - return *this; + return m_outbuf; } [[noreturn]] void error(const pstring &err) noexcept(false); - protected: - - class readbuffer : public std::streambuf - { - public: - explicit readbuffer(ppreprocessor *strm) : m_strm(strm), m_buf() - { setg(nullptr, nullptr, nullptr); } - readbuffer(readbuffer &&rhs) noexcept : m_strm(rhs.m_strm), m_buf() {} - PCOPYASSIGN(readbuffer, delete) - readbuffer &operator=(readbuffer &&src) = delete; - ~readbuffer() override = default; - - int_type underflow() override - { - if (this->gptr() == this->egptr()) - { - // clang reports sign error - weird - std::size_t bytes = m_strm->m_outbuf.size() - narrow_cast<std::size_t>(m_strm->m_pos); - - if (bytes > m_buf.size()) - bytes = m_buf.size(); - std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data()); - this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes); - - m_strm->m_pos += narrow_cast<long>(bytes); - } - - return this->gptr() == this->egptr() - ? std::char_traits<char>::eof() - : std::char_traits<char>::to_int_type(*this->gptr()); - } - - private: - ppreprocessor *m_strm; - std::array<char_type, 1024> m_buf; - }; define_t *get_define(const pstring &name); pstring replace_macros(const pstring &line); @@ -139,11 +84,11 @@ namespace plib { string_list tokenize(const pstring &str, const string_list &sep, bool remove_ws, bool concat); static bool is_valid_token(const pstring &str); - std::pair<pstring,bool> process_line(pstring line); - pstring process_comments(pstring line); + std::pair<pstring,bool> process_line(const pstring &line_in); + pstring process_comments(const pstring &line); defines_map_type m_defines; - psource_collection_t<> &m_sources; + psource_collection_t &m_sources; string_list m_expr_sep; std::uint_least64_t m_if_flag; // 63 if levels @@ -169,8 +114,7 @@ namespace plib { // vector used as stack because we need to loop through stack std::vector<input_context> m_stack; - std::string m_outbuf; - std::istream::pos_type m_pos; + pstring m_outbuf; state_e m_state; pstring m_line; bool m_comment; diff --git a/src/lib/netlist/plib/psource.h b/src/lib/netlist/plib/psource.h new file mode 100644 index 00000000000..2db2feb78d4 --- /dev/null +++ b/src/lib/netlist/plib/psource.h @@ -0,0 +1,175 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +#ifndef PSOURCE_H_ +#define PSOURCE_H_ + +/// +/// \file putil.h +/// + +#include "palloc.h" +#include "pexception.h" +#include "pstring.h" +#include "pstream.h" + +#include <algorithm> +#include <initializer_list> +#include <sstream> +#include <vector> + + +#define PSOURCELOC() plib::source_location(__FILE__, __LINE__) + +namespace plib +{ + + /// \brief Source code locations. + /// + /// The c++20 draft for source locations is based on const char * strings. + /// It is thus only suitable for c++ source code and not for programmatic + /// parsing of files. This class is a replacement for dynamic use cases. + /// + struct source_location + { + source_location() noexcept + : m_file("unknown"), m_func(m_file), m_line(0), m_col(0) + { } + + source_location(pstring file, unsigned line) noexcept + : m_file(std::move(file)), m_func("unknown"), m_line(line), m_col(0) + { } + + source_location(pstring file, pstring func, unsigned line) noexcept + : m_file(std::move(file)), m_func(std::move(func)), m_line(line), m_col(0) + { } + + PCOPYASSIGNMOVE(source_location, default) + + ~source_location() = default; + + unsigned line() const noexcept { return m_line; } + unsigned column() const noexcept { return m_col; } + pstring file_name() const noexcept { return m_file; } + pstring function_name() const noexcept { return m_func; } + + source_location &operator ++() noexcept + { + ++m_line; + return *this; + } + + private: + pstring m_file; + pstring m_func; + unsigned m_line; + unsigned m_col; + }; + + /// \brief Base source class. + /// + /// Pure virtual class all other source implementations are based on. + /// Sources provide an abstraction to read input from a variety of + /// sources, e.g. files, memory, remote locations. + /// + class psource_t + { + public: + + psource_t() noexcept = default; + + PCOPYASSIGNMOVE(psource_t, delete) + + virtual ~psource_t() noexcept = default; + + virtual istream_uptr stream(const pstring &name) = 0; + private: + }; + + /// \brief Generic string source. + /// + /// Will return the given string when name matches. + /// Is used in preprocessor code to eliminate inclusion of certain files. + /// + class psource_str_t : public psource_t + { + public: + psource_str_t(pstring name, pstring str) + : m_name(std::move(name)), m_str(std::move(str)) + {} + + PCOPYASSIGNMOVE(psource_str_t, delete) + ~psource_str_t() noexcept override = default; + + istream_uptr stream(const pstring &name) override + { + if (name == m_name) + return istream_uptr(std::make_unique<std::stringstream>(putf8string(m_str)), name); + + return istream_uptr(); + } + private: + pstring m_name; + pstring m_str; + }; + + /// \brief Generic sources collection. + /// + class psource_collection_t + { + public: + using source_ptr = std::unique_ptr<psource_t>; + using list_t = std::vector<source_ptr>; + + psource_collection_t() noexcept = default; + + PCOPYASSIGNMOVE(psource_collection_t, delete) + virtual ~psource_collection_t() noexcept = default; + + template <typename S, typename... Args> + void add_source(Args&&... args) + { + static_assert(std::is_base_of<psource_t, S>::value, "S must inherit from plib::psource_t"); + + auto src(std::make_unique<S>(std::forward<Args>(args)...)); + m_collection.push_back(std::move(src)); + } + + template <typename S = psource_t> + istream_uptr get_stream(pstring name) + { + for (auto &s : m_collection) + { + auto *source(dynamic_cast<S *>(s.get())); + if (source) + { + auto strm = source->stream(name); + if (!strm.empty()) + return strm; + } + } + return istream_uptr(); + } + + template <typename S, typename F> + bool for_all(F lambda) + { + for (auto &s : m_collection) + { + auto *source(dynamic_cast<S *>(s.get())); + if (source) + { + if (lambda(source)) + return true; + } + } + return false; + } + + private: + list_t m_collection; + }; + +} // namespace plib + +#endif // PSOURCE_H_ diff --git a/src/lib/netlist/plib/pstonum.h b/src/lib/netlist/plib/pstonum.h index c4bf692d177..b3e0df5504e 100644 --- a/src/lib/netlist/plib/pstonum.h +++ b/src/lib/netlist/plib/pstonum.h @@ -97,7 +97,8 @@ namespace plib template<typename T, typename S> T pstonum(const S &arg, const std::locale &loc = std::locale::classic()) noexcept(false) { - decltype(arg.c_str()) cstr = arg.c_str(); + putf8string u8arg(arg); + decltype(u8arg.c_str()) cstr(u8arg.c_str()); std::size_t idx(0); auto ret = pstonum_helper<T>()(loc, cstr, &idx); using ret_type = decltype(ret); diff --git a/src/lib/netlist/plib/pstream.h b/src/lib/netlist/plib/pstream.h index ebaacfcfb73..a636d325541 100644 --- a/src/lib/netlist/plib/pstream.h +++ b/src/lib/netlist/plib/pstream.h @@ -47,6 +47,44 @@ namespace plib { return os.write(reinterpret_cast<const ct *>(data), gsl::narrow<std::streamsize>(len * sizeof(T))); } + /// \brief a named istream pointer container + /// + /// This moveable object allows to pass istream unique pointers with + /// information about the origin (filename). This is useful in error + /// reporting where the source of the stream has to be logged. + /// + struct istream_uptr + { + explicit istream_uptr() = default; + + istream_uptr(std::unique_ptr<std::istream> &&strm, const pstring &filename) + : m_strm(std::move(strm)) + , m_filename(filename) + { + } + istream_uptr(const istream_uptr &) = delete; + istream_uptr &operator=(const istream_uptr &) = delete; + istream_uptr(istream_uptr &&rhs) /*noexcept*/ + { + m_strm = std::move(rhs.m_strm); + m_filename = rhs.m_filename; + } + istream_uptr &operator=(istream_uptr &&) /*noexcept*/ = delete; + + std::istream * operator ->() noexcept { return m_strm.get(); } + std::istream & operator *() noexcept { return *m_strm; } + pstring filename() { return m_filename; } + + bool empty() { return m_strm == nullptr; } + + // FIXME: workaround input context should accept stream_ptr + + std::unique_ptr<std::istream> release_stream() { return std::move(m_strm); } + private: + std::unique_ptr<std::istream> m_strm; + pstring m_filename; + }; + /// /// /// putf8reader_t digests linux & dos/windows text files @@ -61,7 +99,6 @@ public: putf8_reader(putf8_reader &&rhs) noexcept : m_strm(std::move(rhs.m_strm)) - , m_linebuf(std::move(rhs.m_linebuf)) { } @@ -81,13 +118,12 @@ public: /// \param line pstring reference to the result /// \returns Returns false if at end of file /// - bool readline(pstring &line) + bool readline(putf8string &line) { putf8string::code_t c = 0; - m_linebuf = putf8string(""); + line = ""; if (!this->readcode(c)) { - line = ""; return false; } while (true) @@ -95,11 +131,10 @@ public: if (c == 10) break; if (c != 13) // ignore CR - m_linebuf += putf8string(1, c); + line += putf8string(1, c); if (!this->readcode(c)) break; } - line = m_linebuf; return true; } @@ -110,25 +145,23 @@ public: /// \param line pstring reference to the result /// \returns Returns false if at end of file /// - bool readline_lf(pstring &line) + bool readline_lf(putf8string &line) { putf8string::code_t c = 0; - m_linebuf = putf8string(""); + line = ""; if (!this->readcode(c)) { - line = ""; return false; } while (true) { if (c != 13) // ignore CR - m_linebuf += putf8string(1, c); + line += putf8string(1, c); if (c == 10) break; if (!this->readcode(c)) break; } - line = m_linebuf; return true; } @@ -164,7 +197,6 @@ public: std::istream &stream() { return *m_strm; } private: std::unique_ptr<std::istream> m_strm; - putf8string m_linebuf; }; // ----------------------------------------------------------------------------- @@ -194,7 +226,7 @@ public: // NOLINTNEXTLINE(performance-unnecessary-copy-initialization) const putf8string conv_utf8(text); //m_strm->write(conv_utf8.c_str(), static_cast<std::streamsize>(plib::strlen(conv_utf8.c_str() ))); - ostream_write(*m_strm, conv_utf8.c_str(), string_info<pstring>::mem_size(conv_utf8)); + ostream_write(*m_strm, conv_utf8.c_str(), string_info<putf8string>::mem_size(conv_utf8)); } void write(const pstring::value_type c) const @@ -255,7 +287,8 @@ public: void write(const pstring &s) { const auto *sm = s.c_str(); - const auto sl(std::char_traits<pstring::mem_t>::length(sm)); + //const auto sl(std::char_traits<pstring::mem_t>::length(sm)); + const auto sl(string_info<pstring>::mem_size(s)); write(sl); ostream_write(m_strm, sm, sl); } @@ -293,7 +326,7 @@ public: { std::size_t sz = 0; read(sz); - std::vector<plib::string_info<pstring>::mem_t> buf(sz+1); + std::vector<plib::string_info<putf8string>::mem_t> buf(sz+1); m_strm.read(buf.data(), static_cast<std::streamsize>(sz)); buf[sz] = 0; s = pstring(buf.data()); @@ -338,6 +371,11 @@ public: : std::ifstream(filename_type(name).c_str(), mode) { } + + explicit ifstream(const std::string name, ios_base::openmode mode = ios_base::in) + : std::ifstream(filename_type(name).c_str(), mode) + { + } }; /// @@ -354,6 +392,11 @@ public: : std::ofstream(filename_type(name).c_str(), mode) { } + + explicit ofstream(const std::string name, ios_base::openmode mode = ios_base::out | ios_base::trunc) + : std::ofstream(filename_type(name).c_str(), mode) + { + } }; diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp index b0dc3d313c6..f25b669c8ad 100644 --- a/src/lib/netlist/plib/pstring.cpp +++ b/src/lib/netlist/plib/pstring.cpp @@ -11,48 +11,73 @@ template<typename F> int pstring_t<F>::compare(const pstring_t &right) const noexcept { - if (mem_t_size() == 0 && right.mem_t_size() == 0) - return 0; - if (right.mem_t_size() == 0) - return 1; - if (mem_t_size() == 0) - return -1; - +#if 0 + return m_str.compare(right.m_str); +#else auto si = this->begin(); auto ri = right.begin(); - while (si != this->end() && ri != right.end() && *si == *ri) + const auto se = this->end(); + const auto re = right.end(); + + while (si != se && ri != re && *si == *ri) { ++ri; ++si; } - if (si != this->end() && ri != right.end()) + if (si != se && ri != re) return plib::narrow_cast<int>(*si) - plib::narrow_cast<int>(*ri); - if (this->mem_t_size() > right.mem_t_size()) + if (si != se) return 1; - if (this->mem_t_size() < right.mem_t_size()) + if (ri != re) return -1; return 0; +#endif } template<typename F> pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const { pstring_t ret; + auto ps = begin(); + while (ps != end() && start > 0) + { + ++ps; + --start; + } //FIXME: throw ? - const size_type l = length(); - if (start < l) + if (ps != end()) { - if (nlen == npos || start + nlen > l) - nlen = l - start; - auto ps = std::next(begin(), plib::narrow_cast<difference_type>(start)); - auto pe = std::next(ps, plib::narrow_cast<difference_type>(nlen)); + auto pe = ps; + while (pe != end() && nlen > 0) + { + ++pe; + --nlen; + } ret.m_str.assign(ps.p, pe.p); } return ret; } template<typename F> +pstring_t<F> pstring_t<F>::substr(size_type start) const +{ + pstring_t ret; + auto ps = begin(); + while (ps != end() && start > 0) + { + ++ps; + --start; + } + //FIXME: throw ? + if (ps != end()) + { + ret.m_str.assign(ps.p, end().p); + } + return ret; +} + +template<typename F> typename pstring_t<F>::size_type pstring_t<F>::find(const pstring_t &search, size_type start) const noexcept { auto istart = std::next(begin(), static_cast<difference_type>(start)); @@ -75,9 +100,14 @@ typename pstring_t<F>::size_type pstring_t<F>::find(const pstring_t &search, siz template<typename F> typename pstring_t<F>::size_type pstring_t<F>::find(code_t search, size_type start) const noexcept { - pstring_t ss; - traits_type::encode(search, ss.m_str); - return find(ss, start); + auto i = std::next(begin(), static_cast<difference_type>(start)); + for (; i != end(); ++i) + { + if (*i == search) + return start; + ++start; + } + return npos; } // ---------------------------------------------------------------------------------------- diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h index 4cd19c47d08..c9c07ab738d 100644 --- a/src/lib/netlist/plib/pstring.h +++ b/src/lib/netlist/plib/pstring.h @@ -74,6 +74,9 @@ public: using size_type = std::size_t; using difference_type = std::ptrdiff_t; using string_type = typename traits_type::string_type; + // no non-const const_iterator for now + using iterator = pstring_const_iterator<pstring_t<F> >; + using const_iterator = pstring_const_iterator<pstring_t<F> >; // FIXME: this is ugly struct ref_value_type final @@ -120,10 +123,21 @@ public: m_str.assign(string, N - 1); } + // interpret other string as putf8strings + template <typename C, + class = std::enable_if_t<std::is_same<std::remove_const_t<C>, char>::value + && !std::is_same<std::remove_const_t<C>, mem_t>::value>> + pstring_t(C *string); + explicit pstring_t(const string_type &string) : m_str(string) { } + pstring_t(iterator first, iterator last) + { + m_str.assign(first.p, last.p); + } + pstring_t(const pstring_t &string) = default; pstring_t(pstring_t &&string) noexcept = default; pstring_t &operator=(const pstring_t &string) = default; @@ -146,7 +160,6 @@ public: operator string_type () const { return m_str; } - template <typename T, class = std::enable_if_t<!std::is_same<T, pstring_t::traits_type>::value>> pstring_t &operator=(const pstring_t<T> &string) @@ -157,10 +170,6 @@ public: return *this; } - // no non-const const_iterator for now - using iterator = pstring_const_iterator<pstring_t<F> >; - using const_iterator = pstring_const_iterator<pstring_t<F> >; - iterator begin() noexcept { return iterator(m_str.begin()); } iterator end() noexcept { return iterator(m_str.end()); } const_iterator begin() const noexcept { return const_iterator(m_str.begin()); } @@ -175,8 +184,10 @@ public: size_type length() const noexcept { return traits_type::len(m_str); } size_type size() const noexcept { return traits_type::len(m_str); } bool empty() const noexcept { return m_str.empty(); } + void clear() noexcept { m_str.clear(); } - pstring_t substr(size_type start, size_type nlen = npos) const; + pstring_t substr(size_type start, size_type nlen) const; + pstring_t substr(size_type start) const; int compare(const pstring_t &right) const noexcept; size_type find(const pstring_t &search, size_type start = 0) const noexcept; @@ -190,8 +201,8 @@ public: friend pstring_t operator+(code_t lhs, const pstring_t &rhs) { return pstring_t(1, lhs) += rhs; } // comparison operators - bool operator==(const pstring_t &string) const noexcept { return (compare(string) == 0); } - bool operator!=(const pstring_t &string) const noexcept { return (compare(string) != 0); } + bool operator==(const pstring_t &string) const noexcept { return m_str == string.m_str; } + bool operator!=(const pstring_t &string) const noexcept { return m_str != string.m_str; } bool operator<(const pstring_t &string) const noexcept { return (compare(string) < 0); } bool operator<=(const pstring_t &string) const noexcept { return (compare(string) <= 0); } @@ -223,10 +234,10 @@ struct pu8_traits using string_type = std::string; static std::size_t len(const string_type &p) noexcept { return p.size(); } static std::size_t codelen(const mem_t *p) noexcept { plib::unused_var(p); return 1; } - static std::size_t codelen(const code_t c) noexcept { plib::unused_var(c); return 1; } + static std::size_t codelen(code_t c) noexcept { plib::unused_var(c); return 1; } static code_t code(const mem_t *p) noexcept { return *p; } static void encode(const code_t c, string_type &s) { s += static_cast<mem_t>(c); } - static const mem_t *nthcode(const mem_t *p, const std::size_t n) noexcept { return &(p[n]); } + static const mem_t *nthcode(const mem_t *p, std::size_t n) noexcept { return &(p[n]); } }; // No checking, this may deliver invalid codes @@ -248,52 +259,37 @@ struct putf_traits<1, CT> std::size_t ret = 0; for (const auto &c : p) { - if (!((c & 0xC0) == 0x80)) // NOLINT - ret++; + ret += (!((c & 0xC0) == 0x80)); // NOLINT } return ret; } - static std::size_t codelen(const mem_t *p) noexcept + static constexpr std::size_t codelen(const mem_t *p) noexcept { const auto *p1 = reinterpret_cast<const unsigned char *>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret - if ((*p1 & 0xE0) == 0xC0) // NOLINT - return 2; - if ((*p1 & 0xF0) == 0xE0) // NOLINT - return 3; - if ((*p1 & 0xF8) == 0xF0) // NOLINT - return 4; - - // valid utf8: ((*p1 & 0x80) == 0x00) - // However, we return 1 here. - return 1; + return ((*p1 & 0x80) == 0x00) ? 1 : // NOLINT + ((*p1 & 0xE0) == 0xC0) ? 2 : // NOLINT + ((*p1 & 0xF0) == 0xE0) ? 3 : // NOLINT + ((*p1 & 0xF8) == 0xF0) ? 4 : // NOLINT + 1; // Invalid UTF8 code - ignore } - static std::size_t codelen(const code_t c) noexcept + static constexpr std::size_t codelen(code_t c) noexcept { - if (c < 0x0080) // NOLINT - return 1; - if (c < 0x800) // NOLINT - return 2; - if (c < 0x10000) // NOLINT - return 3; - // U+10000 U+1FFFFF - return 4; // no checks + return (c < 0x00080) ? 1 : // NOLINT + (c < 0x00800) ? 2 : // NOLINT + (c < 0x10000) ? 3 : // NOLINT + 4; // U+10000 U+1FFFFF } - static code_t code(const mem_t *p) noexcept + static constexpr code_t code(const mem_t *p) noexcept { - const auto *p1 = reinterpret_cast<const unsigned char *>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret - if ((*p1 & 0x80) == 0x00) // NOLINT - return *p1; - if ((*p1 & 0xE0) == 0xC0) // NOLINT - return static_cast<code_t>(((p1[0] & 0x3f) << 6) | (p1[1] & 0x3f)); // NOLINT - if ((*p1 & 0xF0) == 0xE0) // NOLINT - return static_cast<code_t>(((p1[0] & 0x1f) << 12) | ((p1[1] & 0x3f) << 6) | ((p1[2] & 0x3f) << 0)); // NOLINT - if ((*p1 & 0xF8) == 0xF0) // NOLINT - return static_cast<code_t>(((p1[0] & 0x0f) << 18) | ((p1[1] & 0x3f) << 12) | ((p1[2] & 0x3f) << 6) | ((p1[3] & 0x3f) << 0)); // NOLINT - - return 0xFFFD; // NOLINT: unicode-replacement character + const auto *p1 = reinterpret_cast<const unsigned char *>(p); // NOLINT(cppcoreguidelines-pro-type-reinterpret) + return ((*p1 & 0x80) == 0x00) ? *p1 : // NOLINT + ((*p1 & 0xE0) == 0xC0) ? static_cast<code_t>(((p1[0] & 0x3f) << 6) | (p1[1] & 0x3f)) : // NOLINT + ((*p1 & 0xF0) == 0xE0) ? static_cast<code_t>(((p1[0] & 0x1f) << 12) | ((p1[1] & 0x3f) << 6) | ((p1[2] & 0x3f) << 0)) : // NOLINT + ((*p1 & 0xF8) == 0xF0) ? static_cast<code_t>(((p1[0] & 0x0f) << 18) | ((p1[1] & 0x3f) << 12) | ((p1[2] & 0x3f) << 6) | ((p1[3] & 0x3f) << 0)) : // NOLINT + 0xFFFD; // NOLINT: unicode-replacement character } static void encode(const code_t c, string_type &s) @@ -322,7 +318,7 @@ struct putf_traits<1, CT> } } - static const mem_t *nthcode(const mem_t *p, const std::size_t n) noexcept + static const mem_t *nthcode(const mem_t *p, std::size_t n) noexcept { const mem_t *p1 = p; std::size_t i = n; @@ -360,7 +356,7 @@ struct putf_traits<2, CT> auto c = static_cast<uint16_t>(*p); return ((c & 0xd800) == 0xd800) ? 2 : 1; // NOLINT } - static std::size_t codelen(const code_t c) noexcept + static std::size_t codelen(code_t c) noexcept { return (c < 0x10000) ? 1 : 2; // NOLINT: U+10000 U+1FFFFF } @@ -389,7 +385,7 @@ struct putf_traits<2, CT> s += static_cast<mem_t>(cu); } } - static const mem_t *nthcode(const mem_t *p, const std::size_t n) noexcept + static const mem_t *nthcode(const mem_t *p, std::size_t n) noexcept { std::size_t i = n; while (i-- > 0) @@ -417,7 +413,7 @@ struct putf_traits<4, CT> return 1; } - static std::size_t codelen(const code_t c) noexcept + static std::size_t codelen(code_t c) noexcept { plib::unused_var(c); return 1; @@ -432,7 +428,7 @@ struct putf_traits<4, CT> { s += static_cast<mem_t>(c); } - static const mem_t *nthcode(const mem_t *p, const std::size_t n) noexcept + static const mem_t *nthcode(const mem_t *p, std::size_t n) noexcept { return p + n; } @@ -460,6 +456,17 @@ using putf16string = pstring_t<putf16_traits>; using putf32string = pstring_t<putf32_traits>; using pwstring = pstring_t<pwchar_traits>; +// interpret other string as putf8strings +template <typename F> +template <typename C, class> +pstring_t<F>::pstring_t(C *string) +{ + m_str.clear(); + putf8string utf8(string); + for (auto &c : utf8) + *this += c; +} + namespace plib { template<class T> @@ -478,14 +485,13 @@ namespace plib struct string_info<std::basic_string<T>> { using mem_t = T; - static std::size_t mem_size(const std::string &s) { return s.size(); } + static std::size_t mem_size(const std::basic_string<T> &s) { return s.size(); } }; } // namespace plib // custom specialization of std::hash can be injected in namespace std namespace std { - template<typename T> struct hash<pstring_t<T>> { diff --git a/src/lib/netlist/plib/pstrutil.h b/src/lib/netlist/plib/pstrutil.h index 46424de618d..0010bc2e7f9 100644 --- a/src/lib/netlist/plib/pstrutil.h +++ b/src/lib/netlist/plib/pstrutil.h @@ -18,13 +18,14 @@ #include <stdexcept> #include <string> #include <type_traits> +#include <vector> namespace plib { template<typename T> pstring to_string(const T &v) { - return pstring(std::to_string(v)); + return pstring(putf8string(std::to_string(v))); } template<typename T> @@ -177,6 +178,18 @@ namespace plib } template<typename T> + T lcase(const T &str) + { + T ret; + for (const auto &c : str) + if (c >= 'A' && c <= 'Z') + ret += (c - 'A' + 'a'); + else + ret += c; + return ret; + } + + template<typename T> T rpad(const T &str, const T &ws, const typename T::size_type cnt) { // FIXME: pstringbuffer ret(*this); @@ -189,6 +202,15 @@ namespace plib } template<typename T> + T replace_all(const T &str, typename T::value_type search, typename T::value_type replace) + { + T ret; + for (auto &c : str) + ret += (c == search) ? replace : c; + return ret; + } + + template<typename T> T replace_all(const T &str, const T &search, const T &replace) { T ret; @@ -208,11 +230,128 @@ namespace plib } template<typename T, typename T1, typename T2> - T replace_all(const T &str, const T1 &search, const T2 &replace) + std::enable_if_t<!std::is_integral<T1>::value, T> + replace_all(const T &str, const T1 &search, const T2 &replace) { return replace_all(str, static_cast<T>(search), static_cast<T>(replace)); } + template <typename T> + std::vector<T> psplit(const T &str, const T &onstr, bool ignore_empty = false) + { + std::vector<T> ret; + + auto p = str.begin(); + auto pn = std::search(p, str.end(), onstr.begin(), onstr.end()); + auto ol = onstr.length(); + + while (pn != str.end()) + { + if (!ignore_empty || p != pn) + ret.emplace_back(p, pn); + p = std::next(pn, ol); + pn = std::search(p, str.end(), onstr.begin(), onstr.end()); + } + if (p != str.end()) + { + ret.emplace_back(p, str.end()); + } + return ret; + } + + template <typename T> + std::vector<T> psplit(const T &str, const typename T::value_type &onstr, bool ignore_empty = false) + { + std::vector<T> ret; + + auto p = str.begin(); + auto pn = std::find(p, str.end(), onstr); + + while (pn != str.end()) + { + if (!ignore_empty || p != pn) + ret.emplace_back(p, pn); + p = std::next(pn, 1); + pn = std::find(p, str.end(), onstr); + } + if (p != str.end()) + { + ret.emplace_back(p, str.end()); + } + return ret; + } + + template <typename T> + std::vector<T> psplit_r(const T &stri, + const T &token, + const std::size_t maxsplit) + { + T str(stri); + std::vector<T> result; + std::size_t splits = 0; + + while(!str.empty()) + { + std::size_t index = str.rfind(token); + bool found = index!=T::npos; + if (found) + splits++; + if ((splits <= maxsplit || maxsplit == 0) && found) + { + result.push_back(str.substr(index+token.size())); + str = str.substr(0, index); + if (str.empty()) + result.push_back(str); + } + else + { + result.push_back(str); + str.clear(); + } + } + return result; + } + + template <typename T> + std::vector<T> psplit(const T &str, const std::vector<T> &onstrl) + { + T col = ""; + std::vector<T> ret; + + auto i = str.begin(); + while (i != str.end()) + { + auto p = T::npos; + for (std::size_t j=0; j < onstrl.size(); j++) + { + if (std::equal(onstrl[j].begin(), onstrl[j].end(), i)) + { + p = j; + break; + } + } + if (p != T::npos) + { + if (!col.empty()) + ret.push_back(col); + + col.clear(); + ret.push_back(onstrl[p]); + i = std::next(i, narrow_cast<typename T::difference_type>(onstrl[p].length())); + } + else + { + typename T::value_type c = *i; + col += c; + i++; + } + } + if (!col.empty()) + ret.push_back(col); + + return ret; + } + } // namespace plib #endif // PSTRUTIL_H_ diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h index fe60fadb75f..dc8db7c9bcc 100644 --- a/src/lib/netlist/plib/ptimed_queue.h +++ b/src/lib/netlist/plib/ptimed_queue.h @@ -340,3 +340,4 @@ namespace plib { } // namespace plib #endif // PTIMED_QUEUE_H_ +#include <cstdlib> diff --git a/src/lib/netlist/plib/ptokenizer.cpp b/src/lib/netlist/plib/ptokenizer.cpp index ab4b0444e42..1e63e79d758 100644 --- a/src/lib/netlist/plib/ptokenizer.cpp +++ b/src/lib/netlist/plib/ptokenizer.cpp @@ -4,7 +4,7 @@ #include "palloc.h" #include "pstonum.h" #include "ptokenizer.h" -#include "putil.h" +#include "pstrutil.h" namespace plib { @@ -48,8 +48,10 @@ namespace plib { if (m_px == m_cur_line.end()) { //++m_source_location.back(); - if (m_strm->readline_lf(m_cur_line)) + putf8string line; + if (m_strm->readline_lf(line)) { + m_cur_line = pstring(line); m_px = m_cur_line.begin(); if (*m_px != '#') m_token_queue->push_back(token_t(token_type::SOURCELINE, m_cur_line)); @@ -138,6 +140,52 @@ namespace plib { return ret; } + bool ptoken_reader::process_line_token(const token_t &tok) + { + if (tok.is_type(token_type::LINEMARKER)) + { + bool benter(false); + bool bexit(false); + pstring file; + unsigned lineno(0); + + auto sp = psplit(tok.str(), ' '); + //printf("%d %s\n", (int) sp.size(), ret.str().c_str()); + + bool err = false; + lineno = pstonum_ne<unsigned>(sp[1], err); + if (err) + error(MF_EXPECTED_LINENUM_GOT_1(tok.str())); + if (sp[2].substr(0,1) != "\"") + error(MF_EXPECTED_FILENAME_GOT_1(tok.str())); + file = sp[2].substr(1, sp[2].length() - 2); + + for (std::size_t i = 3; i < sp.size(); i++) + { + if (sp[i] == "1") + benter = true; + if (sp[i] == "2") + bexit = true; + // FIXME: process flags; actually only 1 (file enter) and 2 (after file exit) + } + if (bexit) // pop the last location + m_source_location.pop_back(); + if (!benter) // new location! + m_source_location.pop_back(); + m_source_location.emplace_back(plib::source_location(file, lineno)); + return true; + } + + if (tok.is_type(token_type::SOURCELINE)) + { + m_line = tok.str(); + ++m_source_location.back(); + return true; + } + + return false; + } + ptoken_reader::token_t ptoken_reader::get_token() { token_t ret = get_token_queue(); @@ -147,41 +195,8 @@ namespace plib { return ret; //printf("%s\n", ret.str().c_str()); - if (ret.is_type(token_type::LINEMARKER)) - { - bool benter(false); - bool bexit(false); - pstring file; - unsigned lineno(0); - - ret = get_token_queue(); - if (!ret.is_type(token_type::NUMBER)) - error(MF_EXPECTED_LINENUM_GOT_1(ret.str())); - lineno = pstonum<unsigned>(ret.str()); - ret = get_token_queue(); - if (!ret.is_type(token_type::STRING)) - error(MF_EXPECTED_FILENAME_GOT_1(ret.str())); - file = ret.str(); - ret = get_token_queue(); - while (ret.is_type(token_type::NUMBER)) - { - if (ret.str() == "1") - benter = true; - if (ret.str() == "2") - bexit = true; - // FIXME: process flags; actually only 1 (file enter) and 2 (after file exit) - ret = get_token_queue(); - } - if (bexit) // pop the last location - m_source_location.pop_back(); - if (!benter) // new location! - m_source_location.pop_back(); - m_source_location.emplace_back(plib::source_location(file, lineno - 1)); - } - else if (ret.is_type(token_type::SOURCELINE)) + if (process_line_token(ret)) { - m_line = ret.str(); - ++m_source_location.back(); ret = get_token_queue(); } else @@ -191,6 +206,13 @@ namespace plib { } } + ptoken_reader::token_t ptoken_reader::get_token_raw() + { + token_t ret = get_token_queue(); + process_line_token(ret); + return ret; + } + ptoken_reader::token_t ptokenizer::get_token_internal() { // skip ws @@ -204,8 +226,18 @@ namespace plib { } } if (m_support_line_markers && c == '#') - return token_t(token_type::LINEMARKER, "#"); - + { + pstring lm("#"); + do + { + c = getc(); + if (eof()) + return token_t(token_type::ENDOFFILE); + if (c == '\r' || c == '\n') + return token_t(token_type::LINEMARKER, lm); + lm += c; + } while (true); + } if (m_number_chars_start.find(c) != pstring::npos) { // read number while we receive number or identifier chars diff --git a/src/lib/netlist/plib/ptokenizer.h b/src/lib/netlist/plib/ptokenizer.h index 9d67c297296..056f62dbc29 100644 --- a/src/lib/netlist/plib/ptokenizer.h +++ b/src/lib/netlist/plib/ptokenizer.h @@ -12,7 +12,7 @@ #include "pstring.h" #include "penum.h" -#include "putil.h" // psource_t +#include "psource.h" #include <unordered_map> #include <vector> @@ -58,8 +58,11 @@ namespace plib { : m_id(id) , m_name(name) {} + + PCOPYASSIGNMOVE(token_id_t, default) + std::size_t id() const { return m_id; } - pstring name() const { return m_name; } + const pstring & name() const { return m_name; } private: std::size_t m_id; pstring m_name; @@ -84,6 +87,8 @@ namespace plib { { } + PCOPYASSIGNMOVE(token_t, default) + bool is(const token_id_t &tok_id) const noexcept { return m_id == tok_id.id(); } bool is_not(const token_id_t &tok_id) const noexcept { return !is(tok_id); } @@ -91,7 +96,7 @@ namespace plib { token_type type() const noexcept { return m_type; } - pstring str() const noexcept { return m_token; } + const pstring &str() const noexcept { return m_token; } private: token_type m_type; @@ -212,6 +217,7 @@ namespace plib { // tokenizer stuff follows ... token_t get_token(); + token_t get_token_raw(); // includes line information pstring get_string(); pstring get_identifier(); pstring get_identifier_or_number(); @@ -225,10 +231,14 @@ namespace plib { void error(const perrmsg &errs); plib::source_location sourceloc() { return m_source_location.back(); } + + pstring current_line() const { return m_line; } protected: virtual void verror(const pstring &msg) = 0; private: + bool process_line_token(const token_t &tok); + token_t get_token_queue() { if (m_idx < m_token_store->size()) diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp index 60eab248c9d..b86431633d1 100644 --- a/src/lib/netlist/plib/putil.cpp +++ b/src/lib/netlist/plib/putil.cpp @@ -8,7 +8,7 @@ #include "ptypes.h" #include <algorithm> -#include <cstdlib> // needed for getenv ... +// needed for getenv ... #include <initializer_list> namespace plib @@ -59,109 +59,16 @@ namespace plib pstring environment(const pstring &var, const pstring &default_val) { - return (std::getenv(var.c_str()) == nullptr) ? default_val - : pstring(std::getenv(var.c_str())); + putf8string varu8(var); + return (std::getenv(varu8.c_str()) == nullptr) ? default_val + : pstring(std::getenv(varu8.c_str())); } } // namespace util - std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty) - { - std::vector<pstring> ret; - - pstring::size_type p = 0; - pstring::size_type pn = str.find(onstr, p); - - while (pn != pstring::npos) - { - pstring t = str.substr(p, pn - p); - if (!ignore_empty || t.length() != 0) - ret.push_back(t); - p = pn + onstr.length(); - pn = str.find(onstr, p); - } - if (p < str.length()) - { - pstring t = str.substr(p); - if (!ignore_empty || t.length() != 0) - ret.push_back(t); - } - return ret; - } - - std::vector<std::string> psplit_r(const std::string &stri, - const std::string &token, - const std::size_t maxsplit) - { - std::string str(stri); - std::vector<std::string> result; - std::size_t splits = 0; - - while(!str.empty()) - { - std::size_t index = str.rfind(token); - bool found = index!=std::string::npos; - if (found) - splits++; - if ((splits <= maxsplit || maxsplit == 0) && found) - { - result.push_back(str.substr(index+token.size())); - str = str.substr(0, index); - if (str.empty()) - result.push_back(str); - } - else - { - result.push_back(str); - str = ""; - } - } - return result; - } - - std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl) - { - pstring col = ""; - std::vector<pstring> ret; - - auto i = str.begin(); - while (i != str.end()) - { - auto p = pstring::npos; - for (std::size_t j=0; j < onstrl.size(); j++) - { - if (std::equal(onstrl[j].begin(), onstrl[j].end(), i)) - { - p = j; - break; - } - } - if (p != pstring::npos) - { - if (!col.empty()) - ret.push_back(col); - - col = ""; - ret.push_back(onstrl[p]); - i = std::next(i, narrow_cast<pstring::difference_type>(onstrl[p].length())); - } - else - { - pstring::value_type c = *i; - col += c; - i++; - } - } - if (!col.empty()) - ret.push_back(col); - - return ret; - } - - int penum_base::from_string_int(const pstring &str, const pstring &x) { int cnt = 0; - for (auto &s : psplit(str, ",", false)) + for (auto &s : psplit(str, ',', false)) { if (trim(s) == x) return cnt; @@ -172,6 +79,6 @@ namespace plib pstring penum_base::nthstr(std::size_t n, const pstring &str) { - return psplit(str, ",", false)[n]; + return psplit(str, ',', false)[n]; } } // namespace plib diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h index 7cc855e2802..4ba761fc642 100644 --- a/src/lib/netlist/plib/putil.h +++ b/src/lib/netlist/plib/putil.h @@ -102,184 +102,6 @@ namespace plib { - /// \brief Source code locations. - /// - /// The c++20 draft for source locations is based on const char * strings. - /// It is thus only suitable for c++ source code and not for programmatic - /// parsing of files. This class is a replacement for dynamic use cases. - /// - struct source_location - { - source_location() noexcept - : m_file("unknown"), m_func(m_file), m_line(0), m_col(0) - { } - - source_location(pstring file, unsigned line) noexcept - : m_file(std::move(file)), m_func("unknown"), m_line(line), m_col(0) - { } - - source_location(pstring file, pstring func, unsigned line) noexcept - : m_file(std::move(file)), m_func(std::move(func)), m_line(line), m_col(0) - { } - - PCOPYASSIGNMOVE(source_location, default) - - ~source_location() = default; - - unsigned line() const noexcept { return m_line; } - unsigned column() const noexcept { return m_col; } - pstring file_name() const noexcept { return m_file; } - pstring function_name() const noexcept { return m_func; } - - source_location &operator ++() noexcept - { - ++m_line; - return *this; - } - - private: - pstring m_file; - pstring m_func; - unsigned m_line; - unsigned m_col; - }; - - /// \brief Base source class. - /// - /// Pure virtual class all other source implementations are based on. - /// Sources provide an abstraction to read input from a variety of - /// sources, e.g. files, memory, remote locations. - /// - class psource_t - { - public: - - struct stream_ext - { - explicit stream_ext() = default; - - stream_ext(std::unique_ptr<std::istream> &&strm, const pstring &filename) - : m_strm(std::move(strm)) - , m_filename(filename) - { - } - stream_ext(const stream_ext &) = delete; - stream_ext &operator=(const stream_ext &) = delete; - stream_ext(stream_ext &&rhs) /*noexcept*/ - { - m_strm = std::move(rhs.m_strm); - m_filename = rhs.m_filename; - } - stream_ext &operator=(stream_ext &&) /*noexcept*/ = delete; - - std::istream &stream() noexcept { return *m_strm; } - pstring filename() { return m_filename; } - - bool empty() { return m_strm == nullptr; } - - // FIXME: workaround input context should accept stream_ptr - - std::unique_ptr<std::istream> release_stream() { return std::move(m_strm); } - private: - std::unique_ptr<std::istream> m_strm; - pstring m_filename; - }; - - using stream_ptr = stream_ext; //FIXME: rename to stream_type - - psource_t() noexcept = default; - - PCOPYASSIGNMOVE(psource_t, delete) - - virtual ~psource_t() noexcept = default; - - virtual stream_ptr stream(const pstring &name) = 0; - private: - }; - - /// \brief Generic string source. - /// - /// Will return the given string when name matches. - /// Is used in preprocessor code to eliminate inclusion of certain files. - /// - class psource_str_t : public psource_t - { - public: - psource_str_t(pstring name, pstring str) - : m_name(std::move(name)), m_str(std::move(str)) - {} - - PCOPYASSIGNMOVE(psource_str_t, delete) - ~psource_str_t() noexcept override = default; - - typename psource_t::stream_ptr stream(const pstring &name) override - { - if (name == m_name) - return stream_ptr(std::make_unique<std::stringstream>(m_str), name); - - return psource_t::stream_ptr(); - } - private: - pstring m_name; - pstring m_str; - }; - - /// \brief Generic sources collection. - /// - /// \tparam ARENA memory arena, defaults to aligned_arena - /// - template <typename ARENA = aligned_arena> - class psource_collection_t - { - public: - using source_type = std::unique_ptr<psource_t>; - using list_t = std::vector<source_type>; - - psource_collection_t() noexcept = default; - - PCOPYASSIGNMOVE(psource_collection_t, delete) - virtual ~psource_collection_t() noexcept = default; - - void add_source(source_type &&src) - { - m_collection.push_back(std::move(src)); - } - - template <typename S = psource_t> - typename psource_t::stream_ptr get_stream(pstring name) - { - for (auto &s : m_collection) - { - auto *source(dynamic_cast<S *>(s.get())); - if (source) - { - auto strm = source->stream(name); - if (!strm.empty()) - return strm; - } - } - return typename S::stream_ptr(); - } - - template <typename S, typename F> - bool for_all(F lambda) - { - for (auto &s : m_collection) - { - auto *source(dynamic_cast<S *>(s.get())); - if (source) - { - if (lambda(source)) - return true; - } - } - return false; - } - - private: - list_t m_collection; - }; - namespace util { pstring basename(const pstring &filename, const pstring &suffix = ""); @@ -320,26 +142,6 @@ namespace plib } } // namespace container - template <class C> - struct indexed_compare - { - explicit indexed_compare(const C& target): m_target(target) {} - - bool operator()(int a, int b) const { return m_target[a] < m_target[b]; } - - const C& m_target; - }; - - // ---------------------------------------------------------------------------------------- - // string list - // ---------------------------------------------------------------------------------------- - - std::vector<pstring> psplit(const pstring &str, const pstring &onstr, bool ignore_empty = false); - std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl); - std::vector<std::string> psplit_r(const std::string &stri, - const std::string &token, - std::size_t maxsplit); - // ---------------------------------------------------------------------------------------- // simple hash // ---------------------------------------------------------------------------------------- diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp index 3336a39fdad..bf09654fc42 100644 --- a/src/lib/netlist/prg/nltool.cpp +++ b/src/lib/netlist/prg/nltool.cpp @@ -108,7 +108,7 @@ public: void poutprefix(const pstring &prefix, const pstring &fmt, ARGS&&... args) { pstring res = plib::pfmt(fmt)(std::forward<ARGS>(args)...); - auto lines(plib::psplit(res, "\n", false)); + auto lines(plib::psplit(res, '\n', false)); if (lines.empty()) pout(prefix + "\n"); else @@ -174,6 +174,8 @@ private: using compile_map = std::map<pstring, compile_map_entry>; + void logger(plib::plog_level l, const pstring &ls); + void run_with_progress(netlist_tool_t &nt, netlist::netlist_time_ext nlstart, netlist::netlist_time_ext ttr); void run(); @@ -213,14 +215,14 @@ public: { } - stream_ptr stream(const pstring &file) override + plib::istream_uptr stream(const pstring &file) override { pstring name = m_folder + "/" + file; - stream_ptr strm(std::make_unique<plib::ifstream>(plib::filesystem::u8path(name)), plib::filesystem::u8path(name)); - if (strm.stream().fail()) - return stream_ptr(); + plib::istream_uptr strm(std::make_unique<plib::ifstream>(plib::filesystem::u8path(name)), plib::filesystem::u8path(name)); + if (strm->fail()) + return plib::istream_uptr(); - strm.stream().imbue(std::locale::classic()); + strm->imbue(std::locale::classic()); return strm; } @@ -228,40 +230,22 @@ private: pstring m_folder; }; -class netlist_tool_callbacks_t : public netlist::callbacks_t -{ -public: - explicit netlist_tool_callbacks_t(tool_app_t &app, const pstring &boostlib) - : m_app(app), m_boostlib(boostlib) - { } - - void vlog(const plib::plog_level &l, const pstring &ls) const noexcept override; - - std::unique_ptr<plib::dynlib_base> static_solver_lib() const override - { - if (m_boostlib == "builtin") - return std::make_unique<plib::dynlib_static>(nl_static_solver_syms); - if (m_boostlib == "generic") - return std::make_unique<plib::dynlib_static>(nullptr); - if (NL_DISABLE_DYNAMIC_LOAD) - throw netlist::nl_exception("Dynamic library loading not supported due to project security concerns."); - - //pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); - return std::make_unique<plib::dynlib>(m_boostlib); - } - -private: - tool_app_t &m_app; - pstring m_boostlib; -}; - class netlist_tool_t : public netlist::netlist_state_t { public: - netlist_tool_t(tool_app_t &app, const pstring &name, const pstring &boostlib) - : netlist::netlist_state_t(name, plib::make_unique<netlist_tool_callbacks_t, netlist::host_arena>(app, boostlib)) + netlist_tool_t(plib::plog_delegate logger, const pstring &name, const pstring &boostlib) + : netlist::netlist_state_t(name, logger) { + if (boostlib == "builtin") + set_static_solver_lib(std::make_unique<plib::dynlib_static>(nl_static_solver_syms)); + else if (boostlib == "generic") + set_static_solver_lib(std::make_unique<plib::dynlib_static>(nullptr)); + else if (NL_DISABLE_DYNAMIC_LOAD) + throw netlist::nl_exception("Dynamic library loading not supported due to project security concerns."); + else + //pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); + set_static_solver_lib(std::make_unique<plib::dynlib>(boostlib)); } void read_netlist(const pstring &filename, const pstring &name, @@ -341,21 +325,10 @@ protected: private: }; -void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls) const noexcept -{ - pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str()); - if (l == plib::plog_level::WARNING) - m_app.m_warnings++; - if (l == plib::plog_level::ERROR) - m_app.m_errors++; - if (l == plib::plog_level::FATAL) - m_app.m_errors++; - m_app.pout("{}", err); -} struct input_t { - input_t(const netlist::setup_t &setup, const pstring &line) + input_t(const netlist::setup_t &setup, const putf8string &line) : m_value(netlist::nlconst::zero()) { std::array<char, 400> buf; // NOLINT(cppcoreguidelines-pro-type-member-init) @@ -404,7 +377,7 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstr if (r.stream().fail()) throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(fname)); r.stream().imbue(std::locale::classic()); - pstring l; + putf8string l; while (r.readline(l)) { if (!l.empty()) @@ -447,6 +420,18 @@ void tool_app_t::run_with_progress(netlist_tool_t &nt, netlist::netlist_time_ext } } +void tool_app_t::logger(plib::plog_level l, const pstring &ls) +{ + pstring err = plib::pfmt("{}: {}\n")(l.name())(ls.c_str()); + if (l == plib::plog_level::WARNING) + m_warnings++; + if (l == plib::plog_level::ERROR) + m_errors++; + if (l == plib::plog_level::FATAL) + m_errors++; + pout("{}", err); +} + void tool_app_t::run() { plib::chrono::timer<plib::chrono::system_ticks> t; @@ -461,7 +446,7 @@ void tool_app_t::run() t.start(); - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); nt.exec().enable_stats(opt_stats()); @@ -549,7 +534,7 @@ void tool_app_t::run() void tool_app_t::validate() { - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); if (opt_files().size() != 1) throw netlist::nl_exception("nltool: validate needs exactly one file"); @@ -593,7 +578,7 @@ void tool_app_t::compile_one_and_add_to_map(const pstring &file, { try { - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); nt.log().verbose.set_enabled(false); nt.log().info.set_enabled(false); @@ -657,7 +642,7 @@ void tool_app_t::static_compile() for (auto &e : mp) { plib::ofstream sout(opt_dir() + "/" + e.first + ".c" ); - sout << e.second.m_code; + sout << putf8string(e.second.m_code); } } else @@ -675,12 +660,12 @@ void tool_app_t::static_compile() if (r.stream().fail()) throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(f)); r.stream().imbue(std::locale::classic()); - pstring line; + putf8string line; while (r.readline(line)) { if (plib::startsWith(line, "//NL_CONTAINS ")) { - auto sp = plib::psplit(plib::trim(line.substr(13)), " ", true); + auto sp = plib::psplit(pstring(plib::trim(line.substr(13))), ' ', true); for (auto &e : sp) names.push_back(e); } @@ -710,15 +695,15 @@ void tool_app_t::static_compile() sout << "#include \"plib/pdynlib.h\"\n\n"; for (auto &e : map) { - sout << "// " << e.second.m_module << "\n"; - sout << e.second.m_code; + sout << "// " << putf8string(e.second.m_module) << "\n"; + sout << putf8string(e.second.m_code); } sout << "extern const plib::dynlib_static_sym nl_static_solver_syms[];\n"; sout << "const plib::dynlib_static_sym nl_static_solver_syms[] = {\n"; for (auto &e : map) { - sout << "// " << e.second.m_module << "\n"; - sout << "\t{\"" << e.first << "\", reinterpret_cast<void *>(&" << e.first << ")},\n"; + sout << "// " << putf8string(e.second.m_module) << "\n"; + sout << "\t{\"" << putf8string(e.first) << "\", reinterpret_cast<void *>(&" << putf8string(e.first) << ")},\n"; } sout << "{\"\", nullptr}\n"; sout << "};\n"; @@ -760,7 +745,7 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id) r.stream().imbue(std::locale::classic()); doc_ext ret; - pstring l; + putf8string l; if (!r.readline(l)) return ret; do @@ -771,9 +756,9 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id) l = plib::trim(l.substr(3)); if (!l.empty()) { - auto a(plib::psplit(l, ":", true)); + auto a(plib::psplit(pstring(l), ':', true)); if (a.empty() || (a.size() > 2)) - throw netlist::nl_exception(l+" size mismatch"); + throw netlist::nl_exception(pstring(l) + " size mismatch"); pstring n(plib::trim(a[0])); pstring v(a.size() < 2 ? "" : plib::trim(a[1])); pstring v2(v); @@ -792,12 +777,12 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id) if (!(plib::startsWith(l, "//- ") || plib::startsWith(l, "//-\t")) && !(plib::rtrim(l) == "//-")) break; - v = v + "\n" + l.substr(3); + v = v + "\n" + pstring(l.substr(3)); } if (n == "Title") ret.title = plib::trim(v); else if (n == "Pinalias") - ret.pinalias = plib::psplit(plib::trim(v),",",true); + ret.pinalias = plib::psplit(plib::trim(v),',',true); else if (n == "Description") ret.description = v; else if (n == "Package") @@ -812,7 +797,7 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id) ret.params.emplace_back(v2, plib::trim(v.substr(v2.length()))); else if (n == "Example") { - ret.example = plib::psplit(plib::trim(v),",",true); + ret.example = plib::psplit(plib::trim(v),',',true); if (ret.example.size() != 2 && !ret.example.empty()) throw netlist::nl_exception("Example requires 2 parameters, but found {1}", ret.example.size()); } @@ -856,7 +841,7 @@ void tool_app_t::mac_out(const pstring &s, const bool cont) void tool_app_t::header_entry(const netlist::factory::element_t *e) { - auto v = plib::psplit(e->param_desc(), ","); + auto v = plib::psplit(e->param_desc(), ','); pstring vs; pstring avs; for (const auto &s : v) @@ -876,7 +861,7 @@ void tool_app_t::header_entry(const netlist::factory::element_t *e) void tool_app_t::mac(const netlist::factory::element_t *e) { - auto v = plib::psplit(e->param_desc(), ","); + auto v = plib::psplit(e->param_desc(), ','); pstring vs; for (const auto &s : v) if (!plib::startsWith(s, "@")) @@ -905,7 +890,7 @@ void tool_app_t::create_header() if (!opt_files().empty()) throw netlist::nl_exception("Header doesn't support input files, but {1} where given", opt_files().size()); - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); nt.log().verbose.set_enabled(false); nt.log().info.set_enabled(false); @@ -954,7 +939,7 @@ void tool_app_t::create_header() void tool_app_t::create_docheader() { - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); nt.log().verbose.set_enabled(false); nt.log().info.set_enabled(false); @@ -1109,7 +1094,7 @@ void tool_app_t::create_docheader() void tool_app_t::listdevices() { - netlist_tool_t nt(*this, "netlist", opt_boostlib()); + netlist_tool_t nt(plib::plog_delegate(&tool_app_t::logger, this), "netlist", opt_boostlib()); nt.log().verbose.set_enabled(false); nt.log().info.set_enabled(false); @@ -1137,7 +1122,7 @@ void tool_app_t::listdevices() std::vector<pstring> terms(nt.setup().get_terminals_for_device_name(d->name())); out += "," + f->param_desc(); - for (const auto &p : plib::psplit(f->param_desc(),",") ) + for (const auto &p : plib::psplit(f->param_desc(),',') ) { if (plib::startsWith(p, "+")) { @@ -1163,7 +1148,6 @@ void tool_app_t::listdevices() void tool_app_t::convert() { - pstring contents; std::stringstream ostrm; ostrm.imbue(std::locale::classic()); @@ -1182,7 +1166,8 @@ void tool_app_t::convert() strm.imbue(std::locale::classic()); plib::copystream(ostrm, strm); } - contents = pstring(ostrm.str()); + + pstring contents(putf8string(ostrm.str())); pstring result; if (opt_type.as_string() == "spice") diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp index d506fb31f5b..82e543d9228 100755 --- a/src/lib/netlist/prg/nlwav.cpp +++ b/src/lib/netlist/prg/nlwav.cpp @@ -200,7 +200,7 @@ public: { if (m_e[i].need_more) { - pstring line; + putf8string line; m_e[i].eof = !r[i].readline(line); if (!m_e[i].eof) { @@ -248,6 +248,7 @@ public: } } + private: callback_type m_cb; std::vector<elem> m_e; @@ -490,7 +491,8 @@ public: private: void write(const pstring &line) { - m_fo.write(line.c_str(), static_cast<std::streamsize>(plib::strlen(line.c_str()))); + const putf8string u8line(line); + m_fo.write(u8line.c_str(), static_cast<std::streamsize>(plib::strlen(u8line.c_str()))); } std::size_t m_channels; @@ -552,7 +554,8 @@ public: private: void write(const pstring &line) { - m_fo.write(line.c_str(), static_cast<std::streamsize>(plib::strlen(line.c_str()))); + const putf8string u8line(line); + m_fo.write(u8line.c_str(), static_cast<std::streamsize>(plib::strlen(u8line.c_str()))); } double m_last_time; diff --git a/src/lib/netlist/solver/nld_ms_gcr.h b/src/lib/netlist/solver/nld_ms_gcr.h index 53bf9208649..61bfa012fa7 100644 --- a/src/lib/netlist/solver/nld_ms_gcr.h +++ b/src/lib/netlist/solver/nld_ms_gcr.h @@ -98,10 +98,10 @@ namespace solver // During extended validation there is no reason to check for // differences in the generated code since during // extended validation this will be different (and non-functional) - if (!this->state().is_extended_validation() && this->state().lib().isLoaded()) + if (!this->state().is_extended_validation() && this->state().static_solver_lib().isLoaded()) { pstring symname = static_compile_name(); - m_proc.load(this->state().lib(), symname); + m_proc.load(this->state().static_solver_lib(), symname); if (m_proc.resolved()) { this->state().log().info("External static solver {1} found ...", symname); @@ -313,7 +313,7 @@ namespace solver generate_code(strm); strm.writeline("}\n"); // some compilers (_WIN32, _WIN64, mac osx) need an explicit cast - return std::pair<pstring, pstring>(name, pstring(t.str())); + return std::pair<pstring, pstring>(name, putf8string(t.str())); } template <typename FT, int SIZE> diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 34e1ae16cb3..78493c64d2b 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -59,7 +59,7 @@ namespace devices plib::uninitialised_array<netlist_time, config::MAX_SOLVER_QUEUE_SIZE::value> nt; std::size_t p=0; - while (m_queue.size() > 0) + while (!m_queue.empty()) { auto t = m_queue.top().exec_time(); auto o = m_queue.top().object(); @@ -112,7 +112,7 @@ namespace devices tmp[i]->update_inputs(); } } - if (m_queue.size() > 0) + if (!m_queue.empty()) m_Q_step.net().toggle_and_push_to_queue(m_queue.top().exec_time() - now); } diff --git a/src/lib/netlist/tests/test_pstring.cpp b/src/lib/netlist/tests/test_pstring.cpp new file mode 100644 index 00000000000..097889f3407 --- /dev/null +++ b/src/lib/netlist/tests/test_pstring.cpp @@ -0,0 +1,19 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud + +/// +/// \file test_pstring.cpp +/// +/// tests for pstring +/// + +#include "plib/ptests.h" + +#include "plib/pexception.h" +#include "plib/pstring.h" + +PTEST(pstring, conversion) +{ + PEXPECT_EQ( putf8string("Общая ком"), putf8string(putf16string(putf8string("Общая ком")))); + PEXPECT_EQ( putf8string("Общая ком"), putf8string(putf16string("Общая ком"))); +} diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp index 013de026df5..72338ac0dda 100644 --- a/src/lib/netlist/tools/nl_convert.cpp +++ b/src/lib/netlist/tools/nl_convert.cpp @@ -50,13 +50,13 @@ using lib_map_t = std::unordered_map<pstring, lib_map_entry>; static lib_map_t read_lib_map(const pstring &lm) { - auto reader = plib::putf8_reader(std::make_unique<std::istringstream>(lm)); + auto reader = plib::putf8_reader(std::make_unique<std::istringstream>(putf8string(lm))); reader.stream().imbue(std::locale::classic()); lib_map_t m; - pstring line; + putf8string line; while (reader.readline(line)) { - std::vector<pstring> split(plib::psplit(line, ",")); + std::vector<pstring> split(plib::psplit(pstring(line), ',')); m[plib::trim(split[0])] = { plib::trim(split[1]), plib::trim(split[2]) }; } return m; @@ -342,7 +342,7 @@ void nl_convert_spice_t::convert_block(const str_list &contents) void nl_convert_spice_t::convert(const pstring &contents) { - std::vector<pstring> spnl(plib::psplit(contents, "\n")); + std::vector<pstring> spnl(plib::psplit(contents, '\n')); std::vector<pstring> after_linecontinuation; // Add gnd net @@ -441,7 +441,7 @@ void nl_convert_spice_t::process_line(const pstring &line) if (!line.empty()) { //printf("// %s\n", line.c_str()); - std::vector<pstring> tt(plib::psplit(line, " ", true)); + std::vector<pstring> tt(plib::psplit(line, ' ', true)); double val = 0.0; switch (tt[0].at(0)) { @@ -492,7 +492,7 @@ void nl_convert_spice_t::process_line(const pstring &line) model = tt[5]; else model = tt[4]; - std::vector<pstring> m(plib::psplit(model,"{")); + std::vector<pstring> m(plib::psplit(model, '{')); if (m.size() == 2) { if (m[1].length() != 4) @@ -559,7 +559,7 @@ void nl_convert_spice_t::process_line(const pstring &line) { pstring devname = plib::pfmt("{}{}")(tt[0], i); pstring nextnet = (i<static_cast<std::size_t>(n)-1) ? plib::pfmt("{}a{}")(tt[1], i) : tt[2]; - auto net2 = plib::psplit(plib::replace_all(plib::replace_all(tt[sce+i],")",""),"(",""),","); + auto net2 = plib::psplit(plib::replace_all(plib::replace_all(tt[sce+i],")",""),"(",""),','); add_device("VCVS", devname, get_sp_val(tt[scoeff+i])); add_term(lastnet, devname, 0); add_term(nextnet, devname, 1); @@ -762,7 +762,7 @@ void nl_convert_eagle_t::convert(const pstring &contents) tokenizer tok(*this); tokenizer::token_store tokstor; - plib::putf8_reader u8reader(std::make_unique<std::istringstream>(contents)); + plib::putf8_reader u8reader(std::make_unique<std::istringstream>(putf8string(contents))); tok.append_to_store(&u8reader, tokstor); tok.set_token_source(&tokstor); @@ -914,7 +914,7 @@ void nl_convert_rinf_t::convert(const pstring &contents) tokenizer tok(*this); tokenizer::token_store tokstor; - plib::putf8_reader u8reader(std::make_unique<std::istringstream>(contents)); + plib::putf8_reader u8reader(std::make_unique<std::istringstream>(putf8string(contents))); tok.append_to_store(&u8reader, tokstor); tok.set_token_source(&tokstor); diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h index 31be680c11b..97c5200e6bc 100755 --- a/src/lib/netlist/tools/nl_convert.h +++ b/src/lib/netlist/tools/nl_convert.h @@ -37,7 +37,7 @@ public: virtual ~nl_convert_base_t(); - pstring result() { return pstring(m_buf.str()); } + pstring result() { return pstring(putf8string(m_buf.str())); } virtual void convert(const pstring &contents) = 0; |