summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/devices/machine/netlist.cpp190
-rw-r--r--src/devices/machine/netlist.h1
-rw-r--r--src/lib/netlist/analog/nld_generic_models.h2
-rw-r--r--src/lib/netlist/core/netlist_state.h14
-rw-r--r--src/lib/netlist/core/param.h19
-rw-r--r--src/lib/netlist/core/setup.h16
-rw-r--r--src/lib/netlist/devices/nld_system.cpp98
-rw-r--r--src/lib/netlist/devices/nlid_system.h94
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp16
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx_lib.cpp2
-rw-r--r--src/lib/netlist/nl_base.cpp19
-rw-r--r--src/lib/netlist/nl_factory.h2
-rw-r--r--src/lib/netlist/nl_parser.cpp22
-rw-r--r--src/lib/netlist/nl_parser.h4
-rw-r--r--src/lib/netlist/nl_setup.cpp72
-rw-r--r--src/lib/netlist/nl_setup.h55
-rw-r--r--src/lib/netlist/nltypes.h33
-rw-r--r--src/lib/netlist/plib/parray.h6
-rw-r--r--src/lib/netlist/plib/pdynlib.cpp6
-rw-r--r--src/lib/netlist/plib/pexception.h2
-rw-r--r--src/lib/netlist/plib/pfmtlog.h76
-rw-r--r--src/lib/netlist/plib/pfunction.cpp2
-rw-r--r--src/lib/netlist/plib/poptions.cpp12
-rw-r--r--src/lib/netlist/plib/ppreprocessor.cpp93
-rw-r--r--src/lib/netlist/plib/ppreprocessor.h84
-rw-r--r--src/lib/netlist/plib/psource.h175
-rw-r--r--src/lib/netlist/plib/pstonum.h3
-rw-r--r--src/lib/netlist/plib/pstream.h73
-rw-r--r--src/lib/netlist/plib/pstring.cpp70
-rw-r--r--src/lib/netlist/plib/pstring.h108
-rw-r--r--src/lib/netlist/plib/pstrutil.h143
-rw-r--r--src/lib/netlist/plib/ptimed_queue.h1
-rw-r--r--src/lib/netlist/plib/ptokenizer.cpp108
-rw-r--r--src/lib/netlist/plib/ptokenizer.h16
-rw-r--r--src/lib/netlist/plib/putil.cpp105
-rw-r--r--src/lib/netlist/plib/putil.h198
-rw-r--r--src/lib/netlist/prg/nltool.cpp129
-rwxr-xr-xsrc/lib/netlist/prg/nlwav.cpp9
-rw-r--r--src/lib/netlist/solver/nld_ms_gcr.h6
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp4
-rw-r--r--src/lib/netlist/tests/test_pstring.cpp19
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp18
-rwxr-xr-xsrc/lib/netlist/tools/nl_convert.h2
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 &param, const nl_fptype value)
+ void nlparse_t::register_param_fp(const pstring &param, 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 &param, const pstring &value);
- void register_param(const pstring &param, 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 &param, T value)
+ register_param(const pstring &param, 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 &param, 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;