summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/netlist/analog/nld_bjt.cpp2
-rw-r--r--src/lib/netlist/analog/nld_mosfet.cpp1
-rw-r--r--src/lib/netlist/build/makefile5
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.cpp36
-rw-r--r--src/lib/netlist/devices/nlid_truthtable.h61
-rw-r--r--src/lib/netlist/nl_base.h8
-rw-r--r--src/lib/netlist/nl_parser.cpp2
-rw-r--r--src/lib/netlist/nl_parser.h2
-rw-r--r--src/lib/netlist/nl_setup.cpp6
-rw-r--r--src/lib/netlist/nl_setup.h6
-rw-r--r--src/lib/netlist/plib/mat_cr.h82
-rw-r--r--src/lib/netlist/plib/palloc.h33
-rw-r--r--src/lib/netlist/plib/parray.h16
-rw-r--r--src/lib/netlist/plib/pchrono.h30
-rw-r--r--src/lib/netlist/plib/pexception.h2
-rw-r--r--src/lib/netlist/plib/pfmtlog.cpp8
-rw-r--r--src/lib/netlist/plib/pfmtlog.h2
-rw-r--r--src/lib/netlist/plib/pfunction.cpp4
-rw-r--r--src/lib/netlist/plib/pfunction.h4
-rw-r--r--src/lib/netlist/plib/plists.h38
-rw-r--r--src/lib/netlist/plib/pmempool.h2
-rw-r--r--src/lib/netlist/plib/pomp.h10
-rw-r--r--src/lib/netlist/plib/poptions.h2
-rw-r--r--src/lib/netlist/plib/pparser.cpp919
-rw-r--r--src/lib/netlist/plib/pparser.h318
-rw-r--r--src/lib/netlist/plib/ppreprocessor.cpp628
-rw-r--r--src/lib/netlist/plib/ppreprocessor.h173
-rw-r--r--src/lib/netlist/plib/ptokenizer.cpp301
-rw-r--r--src/lib/netlist/plib/ptokenizer.h169
-rw-r--r--src/lib/netlist/plib/putil.cpp4
-rw-r--r--src/lib/netlist/plib/putil.h47
-rw-r--r--src/lib/netlist/plib/vector_ops.h24
-rw-r--r--src/lib/netlist/solver/nld_ms_direct.h18
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp2
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp4
-rw-r--r--src/lib/netlist/tools/nl_convert.h2
36 files changed, 1507 insertions, 1464 deletions
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index 666165d81f6..17d8405588a 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -304,6 +304,7 @@ namespace analog
NETLIB_UPDATE(QBJT_switch)
{
+ // FIXME: this should never be called
if (!m_RB.m_P.net().isRailNet())
m_RB.m_P.solve_now(); // Basis
else if (!m_RB.m_N.net().isRailNet())
@@ -367,6 +368,7 @@ namespace analog
NETLIB_UPDATE(QBJT_EB)
{
+ // FIXME: this should never be called
if (!m_D_EB.m_P.net().isRailNet())
m_D_EB.m_P.solve_now(); // Basis
else if (!m_D_EB.m_N.net().isRailNet())
diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp
index 21157086353..6349029e65c 100644
--- a/src/lib/netlist/analog/nld_mosfet.cpp
+++ b/src/lib/netlist/analog/nld_mosfet.cpp
@@ -431,6 +431,7 @@ namespace analog
NETLIB_UPDATE(MOSFET)
{
+ // FIXME: This should never be called
if (!m_SG.m_P.net().isRailNet())
m_SG.m_P.solve_now(); // Basis
else if (!m_SG.m_N.net().isRailNet())
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 189a486aff6..072192860e0 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -86,7 +86,8 @@ POBJS := \
$(POBJ)/pfunction.o \
$(POBJ)/pfmtlog.o \
$(POBJ)/poptions.o \
- $(POBJ)/pparser.o \
+ $(POBJ)/ppreprocessor.o \
+ $(POBJ)/ptokenizer.o \
$(POBJ)/putil.o \
PMAIN := $(POBJ)/pmain.o
@@ -237,7 +238,7 @@ gcc9:
$(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
clang:
- $(MAKE) CC=clang++-10 LD=clang++-10 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors"
+ $(MAKE) CC=clang++-10 LD=clang++-10 CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Werror -Wno-padded -Wno-weak-vtables -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors"
clang-5:
$(MAKE) CC=clang++-5.0 LD=clang++-5.0 CEXTRAFLAGS="-march=native -Weverything -Werror -Wno-inconsistent-missing-destructor-override -Wno-unreachable-code -Wno-padded -Wno-weak-vtables -Wno-missing-variable-declarations -Wconversion -Wno-c++98-compat -Wno-float-equal -Wno-global-constructors -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-weak-template-vtables -Wno-exit-time-destructors"
diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp
index cd8e9e1ed1b..2d3b1fcd2e2 100644
--- a/src/lib/netlist/devices/nlid_truthtable.cpp
+++ b/src/lib/netlist/devices/nlid_truthtable.cpp
@@ -141,12 +141,15 @@ namespace netlist
struct truthtable_parser
{
- truthtable_parser(unsigned NO, unsigned NI, bool *initialized,
+ truthtable_parser(unsigned NO, unsigned NI,
packed_int outs, uint_least8_t *timing, netlist_time *timing_nt)
- : m_NO(NO), m_NI(NI), m_initialized(initialized),
- m_out_state(outs), m_timing(timing), m_timing_nt(timing_nt),
- m_num_bits(m_NI),
- m_size(1 << (m_num_bits))
+ : m_NO(NO)
+ , m_NI(NI)
+ , m_out_state(outs)
+ , m_timing(timing)
+ , m_timing_nt(timing_nt)
+ , m_num_bits(m_NI)
+ , m_size(1 << (m_num_bits))
{
}
@@ -160,7 +163,6 @@ namespace netlist
unsigned m_NO;
unsigned m_NI;
- bool *m_initialized;
packed_int m_out_state;
uint_least8_t *m_timing;
netlist_time *m_timing_nt;
@@ -226,11 +228,16 @@ namespace netlist
unique_pool_ptr<device_t> Create(netlist_state_t &anetlist, const pstring &name) override
{
using tt_type = nld_truthtable_t<m_NI, m_NO>;
- truthtable_parser desc_s(m_NO, m_NI, &m_ttbl.m_initialized,
- packed_int(m_ttbl.m_out_state.data(), sizeof(m_ttbl.m_out_state[0]) * 8),
- m_ttbl.m_timing_index.data(), m_ttbl.m_timing_nt.data());
- desc_s.parse(m_desc);
+ if (!m_ttbl)
+ {
+ m_ttbl = pool().make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>();
+ truthtable_parser desc_s(m_NO, m_NI,
+ packed_int(m_ttbl->m_out_state.data(), sizeof(m_ttbl->m_out_state[0]) * 8),
+ m_ttbl->m_timing_index.data(), m_ttbl->m_timing_nt.data());
+
+ desc_s.parse(m_desc);
+ }
/* update truthtable family definitions */
if (m_family_name != "")
@@ -239,10 +246,10 @@ namespace netlist
if (m_family_desc == nullptr)
throw nl_exception("family description not found for {1}", m_family_name);
- return pool().make_unique<tt_type>(anetlist, name, m_family_desc, m_ttbl, m_desc);
+ return pool().make_unique<tt_type>(anetlist, name, m_family_desc, *m_ttbl, m_desc);
}
private:
- typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
+ unique_pool_ptr<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t> m_ttbl;
};
tt_bitset truthtable_parser::calculate_ignored_inputs(tt_bitset state)
@@ -359,9 +366,6 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
{
unsigned line = 0;
- if (*m_initialized)
- return;
-
pstring ttline(truthtable[line]);
line++;
ttline = truthtable[line];
@@ -448,8 +452,6 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
throw nl_exception(plib::pfmt("truthtable: found element not set {1}\n").x(i) );
m_out_state.set(i, m_out_state[i] | (ign[i] << m_NO));
}
- *m_initialized = true;
-
}
netlist_base_factory_truthtable_t::netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
diff --git a/src/lib/netlist/devices/nlid_truthtable.h b/src/lib/netlist/devices/nlid_truthtable.h
index 564bb16451b..ed7c39fae24 100644
--- a/src/lib/netlist/devices/nlid_truthtable.h
+++ b/src/lib/netlist/devices/nlid_truthtable.h
@@ -3,8 +3,6 @@
/*
* nld_truthtable.h
*
- * Created on: 19 Jun 2014
- * Author: andre
*/
#ifndef NLID_TRUTHTABLE_H_
@@ -37,31 +35,6 @@ namespace devices
template<> struct uint_for_size<4> { using type = uint_least32_t; };
template<> struct uint_for_size<8> { using type = uint_least64_t; };
- template<std::size_t NUM, typename R>
- struct aa
- {
- template<typename T>
- R f(T &arr, const R ign)
- {
- R r = aa<NUM-1, R>().f(arr, ign);
- if (ign & (1 << (NUM-1)))
- arr[NUM-1].activate();
- return r | (arr[NUM-1]() << (NUM-1));
- }
- };
-
- template<typename R>
- struct aa<1, R>
- {
- template<typename T>
- R f(T &arr, const R ign)
- {
- if ((ign & 1))
- arr[0].activate();
- return arr[0]();
- }
- };
-
template<std::size_t m_NI, std::size_t m_NO>
NETLIB_OBJECT(truthtable_t)
{
@@ -79,13 +52,11 @@ namespace devices
{
truthtable_t()
: m_timing_index{0}
- , m_initialized(false)
{}
std::array<type_t, m_size> m_out_state;
std::array<uint_least8_t, m_size * m_NO> m_timing_index;
std::array<netlist_time, 16> m_timing_nt;
- bool m_initialized;
};
template <class C>
@@ -141,40 +112,28 @@ namespace devices
private:
template<bool doOUT>
- void process()
+ void process() noexcept
{
netlist_time mt(netlist_time::zero());
type_t nstate(0);
type_t ign(m_ign);
-#if 1
- if (!doOUT)
+
+ if (doOUT)
+ {
+ for (auto I = m_I.begin(); ign != 0; ign >>= 1, ++I)
+ if (ign & 1)
+ I->activate();
for (std::size_t i = 0; i < m_NI; i++)
- {
- m_I[i].activate();
- //nstate |= (m_I[i]() ? (1 << i) : 0);
nstate |= (m_I[i]() << i);
- mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
- }
+ }
else
for (std::size_t i = 0; i < m_NI; i++)
{
- if ((ign & 1))
- m_I[i].activate();
- //nstate |= (m_I[i]() ? (1 << i) : 0);
+ m_I[i].activate();
nstate |= (m_I[i]() << i);
- ign >>= 1;
+ mt = std::max(this->m_I[i].net().next_scheduled_time(), mt);
}
-#else
- if (!doOUT)
- {
- nstate = aa<m_NI, type_t>().f(m_I, ~0);
- for (std::size_t i = 0; i < m_NI; i++)
- mt = std::max(this->m_I[i].net().time(), mt);
- }
- else
- nstate = aa<m_NI, type_t>().f(m_I, ign);
-#endif
const type_t outstate(m_ttp.m_out_state[nstate]);
type_t out(outstate & m_outmask);
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index f732c7cd1e2..93fb9ac64a3 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -666,7 +666,7 @@ namespace netlist
void rebuild_list(); /* rebuild m_list after a load */
void move_connections(net_t &dest_net);
- std::vector<core_terminal_t *> &core_terms() { return m_core_terms; }
+ std::vector<core_terminal_t *> &core_terms() noexcept { return m_core_terms; }
#if NL_USE_COPY_INSTEAD_OF_REFERENCE
void update_inputs() noexcept
{
@@ -731,7 +731,7 @@ namespace netlist
std::vector<core_terminal_t *> m_core_terms; // save post-start m_list ...
template <bool KEEP_STATS, typename T>
- void process(const T mask, netlist_sig_t sig);
+ void process(const T mask, netlist_sig_t sig) noexcept;
};
} // namespace detail
@@ -1686,7 +1686,7 @@ namespace netlist
if (found)
{
bool err = false;
- auto vald = plib::pstonum_ne<T, true>(p, err);
+ auto vald = plib::pstonum_ne<T>(p, err);
if (err)
device.state().log().fatal(MF_INVALID_NUMBER_CONVERSION_1_2(name, p));
m_param = vald;
@@ -1925,7 +1925,7 @@ namespace netlist
// -----------------------------------------------------------------------------
template <bool KEEP_STATS, typename T>
- inline void detail::net_t::process(const T mask, netlist_sig_t sig)
+ inline void detail::net_t::process(const T mask, netlist_sig_t sig) noexcept
{
m_cur_Q = sig;
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index f9fc102abb8..8a3ea3fa027 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -429,7 +429,7 @@ nl_double parser_t::eval_param(const token_t &tok)
else
{
bool err(false);
- ret = plib::pstonum_ne<nl_double, true>(tok.str(), err);
+ ret = plib::pstonum_ne<nl_double>(tok.str(), err);
if (err)
error(plib::pfmt("Parameter value <{1}> not double \n")(tok.str()));
}
diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h
index 310a00a5fb2..3140fad6138 100644
--- a/src/lib/netlist/nl_parser.h
+++ b/src/lib/netlist/nl_parser.h
@@ -9,7 +9,7 @@
#define NL_PARSER_H_
#include "nl_setup.h"
-#include "plib/pparser.h"
+#include "plib/ptokenizer.h"
namespace netlist
{
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 597962bea3b..4ab250c16d4 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -96,7 +96,7 @@ namespace netlist
}
log().fatal(MF_NOT_FOUND_IN_SOURCE_COLLECTION(netlist_name));
#endif
- if (m_sources.for_all<source_netlist_t>(netlist_name, [this, &netlist_name] (auto &src)
+ if (m_sources.for_all<source_netlist_t>([this, &netlist_name] (auto &src)
{
return src->parse(*this, netlist_name);
}))
@@ -963,7 +963,7 @@ nl_double models_t::value(const pstring &model, const pstring &entity)
// FIXME: check for errors
//printf("%s %s %e %e\n", entity.c_str(), tmp.c_str(), plib::pstonum<nl_double>(tmp), factor);
bool err(false);
- auto val = plib::pstonum_ne<nl_double, true>(tmp, err);
+ auto val = plib::pstonum_ne<nl_double>(tmp, err);
if (err)
throw nl_exception(MF_MODEL_NUMBER_CONVERSION_ERROR(entity, tmp, "double", model));
return val * factor;
@@ -1124,7 +1124,7 @@ void setup_t::prepare_to_run()
{
//FIXME: check for errors ...
bool err(false);
- auto v = plib::pstonum_ne<double, true>(p->second, err);
+ auto v = plib::pstonum_ne<double>(p->second, err);
if (err || std::abs(v - std::floor(v)) > 1e-6 )
log().fatal(MF_HND_VAL_NOT_SUPPORTED(p->second));
d.second->set_hint_deactivate(v == 0.0);
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 21f786c90f5..a42b10047d4 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -8,7 +8,7 @@
#ifndef NLSETUP_H_
#define NLSETUP_H_
-#include "plib/pparser.h"
+#include "plib/ppreprocessor.h"
#include "plib/pstream.h"
#include "plib/pstring.h"
#include "plib/putil.h"
@@ -181,7 +181,7 @@ namespace netlist
{}
COPYASSIGNMOVE(source_netlist_t, delete)
- virtual ~source_netlist_t() noexcept = default;
+ ~source_netlist_t() noexcept override = default;
virtual bool parse(nlparse_t &setup, const pstring &name);
};
@@ -197,7 +197,7 @@ namespace netlist
{}
COPYASSIGNMOVE(source_data_t, delete)
- virtual ~source_data_t() noexcept = default;
+ ~source_data_t() noexcept override = default;
};
// ----------------------------------------------------------------------------------------
diff --git a/src/lib/netlist/plib/mat_cr.h b/src/lib/netlist/plib/mat_cr.h
index b21c53671a2..3a6c59f24ab 100644
--- a/src/lib/netlist/plib/mat_cr.h
+++ b/src/lib/netlist/plib/mat_cr.h
@@ -27,9 +27,6 @@
namespace plib
{
- // FIXME: causes a crash with GMRES handler
- // template<typename T, int N, typename C = std::size_t>
-
template<typename T, int N, typename C = uint16_t>
struct pmatrix_cr_t
{
@@ -51,9 +48,9 @@ namespace plib
parray<index_type, NSQ> col_idx; // column index array nz_num, initially (n * n)
parray<value_type, NSQ> A; // Matrix elements nz_num, initially (n * n)
- index_type nz_num;
+ std::size_t nz_num;
- explicit pmatrix_cr_t(const index_type n)
+ explicit pmatrix_cr_t(std::size_t n)
: diag(n)
, row_idx(n+1)
, col_idx(n*n)
@@ -63,7 +60,7 @@ namespace plib
, nzbd(n)
, m_size(n)
{
- for (index_type i=0; i<n+1; i++)
+ for (std::size_t i=0; i<n+1; i++)
{
row_idx[i] = 0;
}
@@ -71,22 +68,22 @@ namespace plib
~pmatrix_cr_t() = default;
- constexpr index_type size() const { return static_cast<index_type>((N>0) ? N : m_size); }
+ constexpr std::size_t size() const noexcept { return (N>0) ? static_cast<std::size_t>(N) : m_size; }
- void clear()
+ void clear() noexcept
{
nz_num = 0;
- for (index_type i=0; i < size() + 1; i++)
+ for (std::size_t i=0; i < size() + 1; i++)
row_idx[i] = 0;
}
- void set_scalar(const T scalar)
+ void set_scalar(T scalar) noexcept
{
- for (index_type i=0, e=nz_num; i<e; i++)
+ for (std::size_t i=0, e=nz_num; i<e; i++)
A[i] = scalar;
}
- void set(C r, C c, T val)
+ void set(C r, C c, T val) noexcept
{
C ri = row_idx[r];
while (ri < row_idx[r+1] && col_idx[ri] < c)
@@ -148,18 +145,18 @@ namespace plib
}
template <typename VTV, typename VTR>
- void mult_vec(VTR & res, const VTV & x)
+ void mult_vec(VTR & res, const VTV & x) const noexcept
{
/*
* res = A * x
*/
#if 0
//plib::omp::set_num_threads(4);
- plib::omp::for_static(0, constants<index_type>::zero(), m_size, [this, &res, &x](index_type row)
+ plib::omp::for_static(0, constants<std::size_t>::zero(), m_size, [this, &res, &x](std::size_t row)
{
T tmp(0.0);
- const index_type e(row_idx[row+1]);
- for (index_type k = row_idx[row]; k < e; k++)
+ const std::size_t e(row_idx[row+1]);
+ for (std::size_t k = row_idx[row]; k < e; k++)
tmp += A[k] * x[col_idx[k]];
res[row] = tmp;
});
@@ -181,7 +178,7 @@ namespace plib
/* throws error if P(source)>P(destination) */
template <typename LUMAT>
- void slim_copy_from(LUMAT & src)
+ void slim_copy_from(LUMAT & src) noexcept
{
for (std::size_t r=0; r<src.size(); r++)
{
@@ -203,10 +200,10 @@ namespace plib
/* only copies common elements */
template <typename LUMAT>
- void reduction_copy_from(LUMAT & src)
+ void reduction_copy_from(LUMAT & src) noexcept
{
C sp(0);
- for (index_type r=0; r<src.size(); r++)
+ for (std::size_t r=0; r<src.size(); r++)
{
C dp(row_idx[r]);
while(sp < src.row_idx[r+1])
@@ -227,9 +224,9 @@ namespace plib
/* no checks at all - may crash */
template <typename LUMAT>
- void raw_copy_from(LUMAT & src)
+ void raw_copy_from(LUMAT & src) noexcept
{
- for (index_type k = 0; k < nz_num; k++)
+ for (std::size_t k = 0; k < nz_num; k++)
A[k] = src.A[k];
}
@@ -237,7 +234,7 @@ namespace plib
parray<std::vector<index_type>, N > nzbd; // Support for gaussian elimination
private:
//parray<C, N < 0 ? -N * (N-1) / 2 : N * (N+1) / 2 > nzbd; // Support for gaussian elimination
- index_type m_size;
+ std::size_t m_size;
};
template<typename B>
@@ -248,7 +245,7 @@ namespace plib
COPYASSIGNMOVE(pGEmatrix_cr_t, default)
- explicit pGEmatrix_cr_t(const index_type n)
+ explicit pGEmatrix_cr_t(std::size_t n)
: B(n)
{
}
@@ -419,10 +416,10 @@ namespace plib
void build_parallel_gaussian_execution_scheme(const M &fill)
{
// calculate parallel scheme for gaussian elimination
- std::vector<std::vector<index_type>> rt(base::size());
- for (index_type k = 0; k < base::size(); k++)
+ std::vector<std::vector<std::size_t>> rt(base::size());
+ for (std::size_t k = 0; k < base::size(); k++)
{
- for (index_type j = k+1; j < base::size(); j++)
+ for (std::size_t j = k+1; j < base::size(); j++)
{
if (fill[j][k] < base::FILL_INFINITY)
{
@@ -431,15 +428,15 @@ namespace plib
}
}
- std::vector<index_type> levGE(base::size(), 0);
- index_type cl = 0;
+ std::vector<std::size_t> levGE(base::size(), 0);
+ std::size_t cl = 0;
- for (index_type k = 0; k < base::size(); k++ )
+ for (std::size_t k = 0; k < base::size(); k++ )
{
if (levGE[k] >= cl)
{
- std::vector<index_type> t = rt[k];
- for (index_type j = k+1; j < base::size(); j++ )
+ std::vector<std::size_t> t = rt[k];
+ for (std::size_t j = k+1; j < base::size(); j++ )
{
bool overlap = false;
// is there overlap
@@ -466,13 +463,12 @@ namespace plib
m_ge_par.clear();
m_ge_par.resize(cl+1);
- for (index_type k = 0; k < base::size(); k++)
+ for (std::size_t k = 0; k < base::size(); k++)
m_ge_par[levGE[k]].push_back(k);
//for (std::size_t k = 0; k < m_ge_par.size(); k++)
// printf("%d %d\n", (int) k, (int) m_ge_par[k].size());
}
- // contains elimination rows below the diagonal
- std::vector<std::vector<index_type>> m_ge_par; // parallel execution support for Gauss
+ std::vector<std::vector<std::size_t>> m_ge_par; // parallel execution support for Gauss
};
template<typename B>
@@ -483,7 +479,7 @@ namespace plib
COPYASSIGNMOVE(pLUmatrix_cr_t, default)
- explicit pLUmatrix_cr_t(const index_type n)
+ explicit pLUmatrix_cr_t(std::size_t n)
: B(n)
, ilu_rows(n+1)
, m_ILUp(0)
@@ -495,7 +491,7 @@ namespace plib
template <typename M>
void build(M &fill, std::size_t ilup)
{
- index_type p(0);
+ std::size_t p(0);
/* build ilu_rows */
for (decltype(fill.size()) i=1; i < fill.size(); i++)
{
@@ -554,7 +550,7 @@ namespace plib
else
this->reduction_copy_from(mat);
- index_type p(0);
+ std::size_t p(0);
while (auto i = ilu_rows[p++]) // NOLINT(bugprone-infinite-loop)
{
const auto p_i_end = base::row_idx[i + 1];
@@ -567,13 +563,13 @@ namespace plib
const auto p_k_end(base::row_idx[k + 1]);
const typename base::value_type LUp_i_k = base::A[i_k] = base::A[i_k] / base::A[base::diag[k]];
- index_type k_j(base::diag[k] + 1);
- index_type i_j(i_k + 1);
+ std::size_t k_j(base::diag[k] + 1);
+ std::size_t i_j(i_k + 1);
while (i_j < p_i_end && k_j < p_k_end ) // pj = (i, j)
{
// we can assume that within a row ja increases continuously */
- const index_type c_i_j(base::col_idx[i_j]); // row i, column j
+ const std::size_t c_i_j(base::col_idx[i_j]); // row i, column j
const auto c_k_j(base::col_idx[k_j]); // row k, column j
if (c_k_j == c_i_j)
@@ -610,7 +606,7 @@ namespace plib
* This can be solved for x using backwards elimination in U.
*
*/
- for (index_type i = 1; i < base::size(); ++i )
+ for (std::size_t i = 1; i < base::size(); ++i )
{
typename base::value_type tmp(0);
const auto j1(base::row_idx[i]);
@@ -621,12 +617,12 @@ namespace plib
r[i] -= tmp;
}
// i now is equal to n;
- for (index_type i = base::size(); i-- > 0; )
+ for (std::size_t i = base::size(); i-- > 0; )
{
typename base::value_type tmp(0);
const auto di(base::diag[i]);
const auto j2(base::row_idx[i+1]);
- for (index_type j = di + 1; j < j2; j++ )
+ for (std::size_t j = di + 1; j < j2; j++ )
tmp += base::A[j] * r[base::col_idx[j]];
r[i] = (r[i] - tmp) / base::A[di];
}
diff --git a/src/lib/netlist/plib/palloc.h b/src/lib/netlist/plib/palloc.h
index aa1aac5544d..5189d86f476 100644
--- a/src/lib/netlist/plib/palloc.h
+++ b/src/lib/netlist/plib/palloc.h
@@ -36,29 +36,31 @@ namespace plib {
using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
template <typename X, typename Y = void>
- typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
+ typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) const noexcept
+ { return *x;}
template <typename X, typename Y = void *>
typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
- getref(X &x, Y y = nullptr)
+ getref(X &x, Y y = nullptr) const noexcept
{
unused_var(y);
return x;
}
- constexpr arena_deleter(arena_storage_type a = arena_storage_type())
+ constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept
: m_a(a) { }
#if 1
template<typename U, typename = typename
std::enable_if<std::is_convertible< U*, T*>::value>::type>
- arena_deleter(const arena_deleter<P, U> &rhs) : m_a(rhs.m_a) { }
+ arena_deleter(const arena_deleter<P, U> &rhs) noexcept
+ : m_a(rhs.m_a) { }
#else
template<typename PU, typename U, typename = typename
std::enable_if<std::is_convertible< U*, T*>::value>::type>
arena_deleter(const arena_deleter<PU, U> &rhs) : m_a(rhs.m_a) { }
#endif
- void operator()(T *p) //const
+ void operator()(T *p) noexcept //const
{
/* call destructor */
p->~T();
@@ -202,19 +204,20 @@ namespace plib {
: m_a(arena_type::instance())
{ }
- ~arena_allocator() noexcept = default;
+ //~arena_allocator() noexcept = default;
arena_allocator(arena_type & a) noexcept : m_a(a)
{
}
template <class U>
- arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs)
+ arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept
: m_a(rhs.m_a)
{
}
- template <class U> struct rebind
+ template <class U>
+ struct rebind
{
using other = arena_allocator<ARENA, U, ALIGN>;
};
@@ -224,7 +227,7 @@ namespace plib {
return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
}
- void deallocate(T* p, std::size_t n)
+ void deallocate(T* p, std::size_t n) noexcept
{
unused_var(n);
m_a.deallocate(p);
@@ -234,7 +237,9 @@ namespace plib {
friend bool operator==(const arena_allocator<AR1, T1, A1>& lhs,
const arena_allocator<AR2, T2, A2>& rhs) noexcept;
- template <class AU, class U, std::size_t A> friend class arena_allocator;
+ template <class AU, class U, std::size_t A>
+ friend class arena_allocator;
+
private:
arena_type &m_a;
};
@@ -268,7 +273,7 @@ namespace plib {
template <typename T>
using owned_pool_ptr = plib::owned_ptr<T, arena_deleter<aligned_arena, T>>;
- static inline aligned_arena &instance()
+ static inline aligned_arena &instance() noexcept
{
static aligned_arena s_arena;
return s_arena;
@@ -294,7 +299,7 @@ namespace plib {
#endif
}
- static inline void deallocate( void *ptr )
+ static inline void deallocate( void *ptr ) noexcept
{
#if (PUSE_ALIGNED_ALLOCATION)
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
@@ -336,7 +341,7 @@ namespace plib {
}
}
- bool operator ==(const aligned_arena &rhs) const
+ bool operator ==(const aligned_arena &rhs) const noexcept
{
plib::unused_var(rhs);
return true;
@@ -380,7 +385,7 @@ namespace plib {
}
template<typename T>
- inline void pdelete(T *ptr)
+ inline void pdelete(T *ptr) noexcept
{
ptr->~T();
aligned_arena::deallocate(ptr);
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h
index d8f7a441f6f..c1196e1e7d4 100644
--- a/src/lib/netlist/plib/parray.h
+++ b/src/lib/netlist/plib/parray.h
@@ -82,9 +82,20 @@ namespace plib {
parray(const parray &rhs) : m_a(rhs.m_a), m_size(rhs.m_size) {}
parray(parray &&rhs) noexcept : m_a(std::move(rhs.m_a)), m_size(std::move(rhs.m_size)) {}
- parray &operator=(const parray &rhs) { m_a = rhs.m_a; m_size = rhs.m_size; return *this; }
+ parray &operator=(const parray &rhs) noexcept
+ {
+ if (this != &rhs)
+ {
+ m_a = rhs.m_a;
+ m_size = rhs.m_size;
+ }
+ return *this;
+ }
+
parray &operator=(parray &&rhs) noexcept { std::swap(m_a,rhs.m_a); std::swap(m_size, rhs.m_size); return *this; }
+ ~parray() noexcept = default;
+
template <int X = SIZE >
parray(size_type size, typename std::enable_if<(X != 0), int>::type = 0)
: m_size(size)
@@ -137,6 +148,9 @@ namespace plib {
}
COPYASSIGNMOVE(parray2D, default)
+
+ ~parray2D() noexcept = default;
+
};
} // namespace plib
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
index 4e0bb071431..8eb2e64d358 100644
--- a/src/lib/netlist/plib/pchrono.h
+++ b/src/lib/netlist/plib/pchrono.h
@@ -35,7 +35,7 @@ namespace plib {
struct base_ticks
{
using ret_type = R;
- static ret_type per_second()
+ static ret_type per_second() noexcept
{
static ret_type persec = 0;
if (persec == 0)
@@ -179,9 +179,9 @@ namespace plib {
struct counter<false>
{
using type = uint_least64_t;
- constexpr type operator()() const { return 0; }
- void inc() const { }
- void reset() const { }
+ constexpr type operator()() const noexcept { return 0; }
+ void inc() const noexcept { }
+ void reset() const noexcept { }
constexpr static bool enabled = false;
};
@@ -212,14 +212,14 @@ namespace plib {
type operator()() const { return m_time; }
void reset() { m_time = 0; m_count = 0; }
- type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
- type total() const { return m_time; }
- ctype count() const { return m_count; }
+ type average() const noexcept { return (m_count == 0) ? 0 : m_time / m_count; }
+ type total() const noexcept { return m_time; }
+ ctype count() const noexcept { return m_count; }
- double as_seconds() const { return static_cast<double>(total())
+ double as_seconds() const noexcept { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
- guard_t guard() { return guard_t(*this); }
+ guard_t guard() noexcept { return guard_t(*this); }
private:
type m_time;
ctype m_count;
@@ -242,12 +242,12 @@ namespace plib {
~guard_t() { }
};
- constexpr type operator()() const { return 0; }
- void reset() const { }
- constexpr type average() const { return 0; }
- constexpr type total() const { return 0; }
- constexpr ctype count() const { return 0; }
- constexpr double as_seconds() const { return 0.0; }
+ constexpr type operator()() const noexcept { return 0; }
+ void reset() const noexcept { }
+ constexpr type average() const noexcept { return 0; }
+ constexpr type total() const noexcept { return 0; }
+ constexpr ctype count() const noexcept { return 0; }
+ constexpr double as_seconds() const noexcept { return 0.0; }
constexpr static bool enabled = false;
guard_t guard() { return guard_t(); }
};
diff --git a/src/lib/netlist/plib/pexception.h b/src/lib/netlist/plib/pexception.h
index 28a3ac1adf1..e6c350a04b3 100644
--- a/src/lib/netlist/plib/pexception.h
+++ b/src/lib/netlist/plib/pexception.h
@@ -34,7 +34,7 @@ namespace plib {
public:
explicit pexception(const pstring &text);
- const pstring &text() { return m_text; }
+ const pstring &text() const noexcept { return m_text; }
const char* what() const noexcept override { return m_text.c_str(); }
private:
diff --git a/src/lib/netlist/plib/pfmtlog.cpp b/src/lib/netlist/plib/pfmtlog.cpp
index 250ead34cb3..2158d10cb2d 100644
--- a/src/lib/netlist/plib/pfmtlog.cpp
+++ b/src/lib/netlist/plib/pfmtlog.cpp
@@ -108,14 +108,14 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec)
auto pdot(fmt.find('.'));
if (pdot==0)
- strm << std::setprecision(pstonum<int>(fmt.substr(1)));
+ strm << std::setprecision(pstonum_ne_def<int>(fmt.substr(1), 6));
else if (pdot != pstring::npos)
{
- strm << std::setprecision(pstonum<int>(fmt.substr(pdot + 1)));
- r.width = pstonum<int>(left(fmt,pdot));
+ strm << std::setprecision(pstonum_ne_def<int>(fmt.substr(pdot + 1), 6));
+ r.width = pstonum_ne_def<int>(left(fmt,pdot), 0);
}
else if (fmt != "")
- r.width = pstonum<int>(fmt);
+ r.width = pstonum_ne_def<int>(fmt, 0);
switch (r.pend)
{
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index 7bf10173857..13ec2396a8a 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -248,7 +248,7 @@ protected:
strm << std::forward<T>(val);
const pstring ps(strm.str());
pstring pad("");
- std::size_t aw(std::abs(ret.width));
+ auto aw(static_cast<std::size_t>(std::abs(ret.width)));
if (aw > ps.length())
pad = pstring(aw - ps.length(), ' ');
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 6ad2627f0db..e4ea2d57163 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -73,7 +73,7 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
{
rc.m_cmd = PUSH_CONST;
bool err(false);
- rc.m_param = plib::pstonum_ne<decltype(rc.m_param), true>(cmd, err);
+ rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
if (err)
throw plib::pexception(plib::pfmt("pfunction: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
stk += 1;
@@ -188,7 +188,7 @@ case OP: \
stack[ptr-1] = (EXPR); \
break;
-double pfunction::evaluate(const std::vector<double> &values)
+double pfunction::evaluate(const std::vector<double> &values) noexcept
{
std::array<double, 20> stack = { 0 };
unsigned ptr = 0;
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index bc81ef0c5a6..8c6d71f33e4 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -91,14 +91,14 @@ namespace plib {
* @param values for input variables, e.g. {1.1, 2.2}
* @return value of expression
*/
- double evaluate(const std::vector<double> &values);
+ double evaluate(const std::vector<double> &values) noexcept;
private:
void compile_postfix(const std::vector<pstring> &inputs,
const std::vector<pstring> &cmds, const pstring &expr);
- double lfsr_random()
+ double lfsr_random() noexcept
{
std::uint16_t lsb = m_lfsr & 1;
m_lfsr >>= 1;
diff --git a/src/lib/netlist/plib/plists.h b/src/lib/netlist/plib/plists.h
index 4b2b7d41471..7a9e0cb0edb 100644
--- a/src/lib/netlist/plib/plists.h
+++ b/src/lib/netlist/plib/plists.h
@@ -35,8 +35,17 @@ namespace plib {
{
public:
- using iterator = C *;
- using const_iterator = const C *;
+ typedef C value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
//uninitialised_array_t() noexcept = default;
uninitialised_array_t() noexcept
@@ -48,24 +57,24 @@ namespace plib {
~uninitialised_array_t() noexcept
{
if (m_initialized>=N)
- for (std::size_t i=0; i<N; i++)
+ for (size_type i=0; i<N; i++)
(*this)[i].~C();
}
- size_t size() const { return N; }
+ size_t size() const noexcept { return N; }
- C& operator[](const std::size_t &index) noexcept
+ reference operator[](size_type index) noexcept
{
- return *reinterpret_cast<C *>(&m_buf[index]);
+ return *reinterpret_cast<pointer>(&m_buf[index]);
}
- const C& operator[](const std::size_t &index) const noexcept
+ const_reference operator[](size_type index) const noexcept
{
- return *reinterpret_cast<const C *>(&m_buf[index]);
+ return *reinterpret_cast<const_pointer>(&m_buf[index]);
}
template<typename... Args>
- void emplace(const std::size_t index, Args&&... args)
+ void emplace(size_type index, Args&&... args)
{
m_initialized++;
// allocate on buffer
@@ -125,7 +134,14 @@ namespace plib {
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
- iter_t& operator=(const iter_t &rhs) noexcept { if (this != &rhs) p = rhs.p; return *this; }
+
+ iter_t& operator=(const iter_t &rhs) noexcept
+ {
+ if (this != &rhs)
+ p = rhs.p;
+ return *this;
+ }
+
iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
~iter_t() = default;
@@ -386,7 +402,7 @@ namespace plib {
const T *listptr() const noexcept { return &m_list[1]; }
std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); }
- const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; }
+ const T & operator[](std::size_t index) const noexcept { return m_list[ 1 + index]; }
private:
using mutex_type = pspin_mutex<TS>;
using lock_guard_type = std::lock_guard<mutex_type>;
diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h
index a4ac4fd393f..562b4a15625 100644
--- a/src/lib/netlist/plib/pmempool.h
+++ b/src/lib/netlist/plib/pmempool.h
@@ -226,7 +226,7 @@ namespace plib {
}
}
- bool operator ==(const mempool &rhs) { return this == &rhs; }
+ bool operator ==(const mempool &rhs) noexcept { return this == &rhs; }
};
diff --git a/src/lib/netlist/plib/pomp.h b/src/lib/netlist/plib/pomp.h
index 79fa0f4bf9b..26e037bca1d 100644
--- a/src/lib/netlist/plib/pomp.h
+++ b/src/lib/netlist/plib/pomp.h
@@ -22,7 +22,7 @@ namespace plib {
namespace omp {
template <typename I, class T>
-void for_static(std::size_t numops, const I start, const I end, const T &what)
+void for_static(std::size_t numops, const I start, const I end, const T &what) noexcept(noexcept(what))
{
if (numops>1000)
{
@@ -38,7 +38,7 @@ void for_static(std::size_t numops, const I start, const I end, const T &what)
}
template <typename I, class T>
-void for_static(const I start, const I end, const T &what)
+void for_static(const I start, const I end, const T &what) noexcept(noexcept(what))
{
#if PHAS_OPENMP && PUSE_OPENMP
#pragma omp parallel for schedule(static)
@@ -48,14 +48,14 @@ void for_static(const I start, const I end, const T &what)
}
template <typename I, class T>
-void for_static_np(const I start, const I end, const T &what)
+void for_static_np(const I start, const I end, const T &what) noexcept(noexcept(what))
{
for (I i = start; i < end; i++)
what(i);
}
-inline void set_num_threads(const std::size_t threads)
+inline void set_num_threads(const std::size_t threads) noexcept
{
#if PHAS_OPENMP && PUSE_OPENMP
omp_set_num_threads(threads);
@@ -64,7 +64,7 @@ inline void set_num_threads(const std::size_t threads)
#endif
}
-inline std::size_t get_max_threads()
+inline std::size_t get_max_threads() noexcept
{
#if PHAS_OPENMP && PUSE_OPENMP
return omp_get_max_threads();
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index e3ab42b060f..4a92f721e76 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -185,7 +185,7 @@ protected:
int parse(const pstring &argument) override
{
bool err(false);
- m_val = pstonum_ne<T, true>(argument, err);
+ m_val = pstonum_ne<T>(argument, err);
return (err ? 1 : (m_val < m_min || m_val > m_max));
}
diff --git a/src/lib/netlist/plib/pparser.cpp b/src/lib/netlist/plib/pparser.cpp
deleted file mode 100644
index 3480a8e3bea..00000000000
--- a/src/lib/netlist/plib/pparser.cpp
+++ /dev/null
@@ -1,919 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * pparser.c
- *
- */
-
-#include "pparser.h"
-#include "palloc.h"
-#include "putil.h"
-
-
-namespace plib {
-// ----------------------------------------------------------------------------------------
-// A simple tokenizer
-// ----------------------------------------------------------------------------------------
-
-pstring ptokenizer::currentline_str()
-{
- return m_cur_line;
-}
-
-void ptokenizer::skipeol()
-{
- pstring::value_type c = getc();
- while (c)
- {
- if (c == 10)
- {
- c = getc();
- if (c != 13)
- ungetc(c);
- return;
- }
- c = getc();
- }
-}
-
-pstring::value_type ptokenizer::getc()
-{
- if (m_unget != 0)
- {
- pstring::value_type c = m_unget;
- m_unget = 0;
- return c;
- }
- if (m_px == m_cur_line.end())
- {
- ++m_source_location.back();
- if (m_strm.readline(m_cur_line))
- m_px = m_cur_line.begin();
- else
- return 0;
- return '\n';
- }
- pstring::value_type c = *(m_px++);
- return c;
-}
-
-void ptokenizer::ungetc(pstring::value_type c)
-{
- m_unget = c;
-}
-
-void ptokenizer::require_token(const token_id_t &token_num)
-{
- require_token(get_token(), token_num);
-}
-
-void ptokenizer::require_token(const token_t &tok, const token_id_t &token_num)
-{
- if (!tok.is(token_num))
- {
- pstring val("");
- for (auto &i : m_tokens)
- if (i.second.id() == token_num.id())
- val = i.first;
- error(pfmt("Expected token <{1}> got <{2}>")(val)(tok.str()) );
- }
-}
-
-pstring ptokenizer::get_string()
-{
- token_t tok = get_token();
- if (!tok.is_type(STRING))
- {
- error(pfmt("Expected a string, got <{1}>")(tok.str()) );
- }
- return tok.str();
-}
-
-pstring ptokenizer::get_identifier()
-{
- token_t tok = get_token();
- if (!tok.is_type(IDENTIFIER))
- {
- error(pfmt("Expected an identifier, got <{1}>")(tok.str()) );
- }
- return tok.str();
-}
-
-pstring ptokenizer::get_identifier_or_number()
-{
- token_t tok = get_token();
- if (!(tok.is_type(IDENTIFIER) || tok.is_type(NUMBER)))
- {
- error(pfmt("Expected an identifier or number, got <{1}>")(tok.str()) );
- }
- return tok.str();
-}
-
-// FIXME: combine into template
-double ptokenizer::get_number_double()
-{
- token_t tok = get_token();
- if (!tok.is_type(NUMBER))
- {
- error(pfmt("Expected a number, got <{1}>")(tok.str()) );
- }
- bool err(false);
- auto ret = plib::pstonum_ne<double, true>(tok.str(), err);
- if (err)
- error(pfmt("Expected a number, got <{1}>")(tok.str()) );
- return ret;
-}
-
-long ptokenizer::get_number_long()
-{
- token_t tok = get_token();
- if (!tok.is_type(NUMBER))
- {
- error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
- }
- bool err(false);
- auto ret = plib::pstonum_ne<long, true>(tok.str(), err);
- if (err)
- error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
- return ret;
-}
-
-ptokenizer::token_t ptokenizer::get_token()
-{
- token_t ret = get_token_internal();
- while (true)
- {
- if (ret.is_type(ENDOFFILE))
- return ret;
- else if (m_support_line_markers && ret.is_type(LINEMARKER))
- {
- bool benter(false);
- bool bexit(false);
- pstring file;
- unsigned lineno;
-
- ret = get_token_internal();
- if (!ret.is_type(NUMBER))
- error(pfmt("Expected line number after line marker but got <{1}>")(ret.str()) );
- lineno = pstonum<unsigned>(ret.str());
- ret = get_token_internal();
- if (!ret.is_type(STRING))
- error(pfmt("Expected file name after line marker but got <{1}>")(ret.str()) );
- file = ret.str();
- ret = get_token_internal();
- while (ret.is_type(NUMBER))
- {
- if (ret.str() == "1")
- benter = true;
- if (ret.str() == "2")
- bexit = false;
- // FIXME: process flags; actually only 1 (file enter) and 2 (after file exit)
- ret = get_token_internal();
- }
- 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));
- }
- else if (ret.is(m_tok_comment_start))
- {
- do {
- ret = get_token_internal();
- } while (ret.is_not(m_tok_comment_end));
- ret = get_token_internal();
- }
- else if (ret.is(m_tok_line_comment))
- {
- skipeol();
- ret = get_token_internal();
- }
- else
- {
- return ret;
- }
- }
-}
-
-ptokenizer::token_t ptokenizer::get_token_internal()
-{
- /* skip ws */
- pstring::value_type c = getc();
- while (m_whitespace.find(c) != pstring::npos)
- {
- c = getc();
- if (eof())
- {
- return token_t(ENDOFFILE);
- }
- }
- if (m_support_line_markers && c == '#')
- return token_t(LINEMARKER, "#");
- else if (m_number_chars_start.find(c) != pstring::npos)
- {
- /* read number while we receive number or identifier chars
- * treat it as an identifier when there are identifier chars in it
- *
- */
- token_type ret = NUMBER;
- pstring tokstr = "";
- while (true) {
- if (m_identifier_chars.find(c) != pstring::npos && m_number_chars.find(c) == pstring::npos)
- ret = IDENTIFIER;
- else if (m_number_chars.find(c) == pstring::npos)
- break;
- tokstr += c;
- c = getc();
- }
- ungetc(c);
- return token_t(ret, tokstr);
- }
- else if (m_identifier_chars.find(c) != pstring::npos)
- {
- /* read identifier till non identifier char */
- pstring tokstr = "";
- while (m_identifier_chars.find(c) != pstring::npos)
- {
- tokstr += c;
- c = getc();
- }
- ungetc(c);
- auto id = m_tokens.find(tokstr);
- if (id != m_tokens.end())
- return token_t(id->second, tokstr);
- else
- return token_t(IDENTIFIER, tokstr);
- }
- else if (c == m_string)
- {
- pstring tokstr = "";
- c = getc();
- while (c != m_string)
- {
- tokstr += c;
- c = getc();
- }
- return token_t(STRING, tokstr);
- }
- else
- {
- /* read identifier till first identifier char or ws */
- pstring tokstr = "";
- while ((m_identifier_chars.find(c) == pstring::npos) && (m_whitespace.find(c) == pstring::npos))
- {
- tokstr += c;
- /* expensive, check for single char tokens */
- if (tokstr.length() == 1)
- {
- auto id = m_tokens.find(tokstr);
- if (id != m_tokens.end())
- return token_t(id->second, tokstr);
- }
- c = getc();
- }
- ungetc(c);
- auto id = m_tokens.find(tokstr);
- if (id != m_tokens.end())
- return token_t(id->second, tokstr);
- else
- return token_t(UNKNOWN, tokstr);
- }
-}
-
-void ptokenizer::error(const pstring &errs)
-{
- pstring s("");
- pstring trail (" from ");
- pstring trail_first("In file included from ");
- pstring e = plib::pfmt("{1}:{2}:0: error: {3}\n")
- (m_source_location.back().file_name(), m_source_location.back().line(), errs);
- m_source_location.pop_back();
- while (m_source_location.size() > 0)
- {
- if (m_source_location.size() == 1)
- trail = trail_first;
- s = trail + plib::pfmt("{1}:{2}:0\n")(m_source_location.back().file_name(), m_source_location.back().line()) + s;
- m_source_location.pop_back();
- }
- verror("\n" + s + e + " " + currentline_str() + "\n");
-}
-
-
-// ----------------------------------------------------------------------------------------
-// A simple preprocessor
-// ----------------------------------------------------------------------------------------
-
-ppreprocessor::ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines)
-: std::istream(new readbuffer(this))
-, m_sources(sources)
-, m_if_flag(0)
-, m_if_level(0)
-, m_pos(0)
-, m_state(PROCESS)
-, m_comment(false)
-{
- m_expr_sep.emplace_back("!");
- m_expr_sep.emplace_back("(");
- m_expr_sep.emplace_back(")");
- m_expr_sep.emplace_back("+");
- m_expr_sep.emplace_back("-");
- m_expr_sep.emplace_back("*");
- m_expr_sep.emplace_back("/");
- m_expr_sep.emplace_back("&&");
- m_expr_sep.emplace_back("||");
- m_expr_sep.emplace_back("==");
- m_expr_sep.emplace_back(",");
- m_expr_sep.emplace_back(";");
- m_expr_sep.emplace_back(".");
- m_expr_sep.emplace_back("##");
- m_expr_sep.emplace_back("#");
- m_expr_sep.emplace_back(" ");
- m_expr_sep.emplace_back("\t");
- m_expr_sep.emplace_back("\"");
-
- if (defines != nullptr)
- m_defines = *defines;
- m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")});
- auto idx = m_defines.find("__PREPROCESSOR_DEBUG__");
- m_debug_out = idx != m_defines.end();
-
-}
-
-void ppreprocessor::error(const pstring &err)
-{
- pstring s("");
- pstring trail (" from ");
- pstring trail_first("In file included from ");
- pstring e = plib::pfmt("{1}:{2}:0: error: {3}\n")
- (m_stack.back().m_name, m_stack.back().m_lineno, err);
- m_stack.pop_back();
- while (m_stack.size() > 0)
- {
- if (m_stack.size() == 1)
- trail = trail_first;
- s = trail + plib::pfmt("{1}:{2}:0\n")(m_stack.back().m_name, m_stack.back().m_lineno) + s;
- m_stack.pop_back();
- }
- throw pexception("\n" + s + e + " " + m_line + "\n");
-}
-
-
-
-template <typename PP, typename L = ppreprocessor::string_list>
-struct simple_iter
-{
- simple_iter(PP *parent, const L &tokens)
- : m_tokens(tokens), m_parent(parent), m_pos(0)
- {}
-
- /**! skip white space in token list
- *
- */
- void skip_ws()
- {
- while (m_pos < m_tokens.size() && (m_tokens[m_pos] == " " || m_tokens[m_pos] == "\t"))
- m_pos++;
- }
-
- /**! return next token skipping white space
- *
- * @return next token
- */
- pstring next()
- {
- skip_ws();
- if (m_pos >= m_tokens.size())
- error("unexpected end of line");
- return m_tokens[m_pos++];
- }
-
- /**! return next token including white space
- *
- * @return next token
- */
- pstring next_ws()
- {
- if (m_pos >= m_tokens.size())
- error("unexpected end of line");
- return m_tokens[m_pos++];
- }
-
- pstring peek_ws()
- {
- if (m_pos >= m_tokens.size())
- error("unexpected end of line");
- return m_tokens[m_pos];
- }
-
- pstring last()
- {
- if (m_pos == 0)
- error("no last token at beginning of line");
- if (m_pos > m_tokens.size())
- error("unexpected end of line");
- return m_tokens[m_pos-1];
- }
-
- bool eod()
- {
- return (m_pos >= m_tokens.size());
- }
-
- void error(pstring err)
- {
- m_parent->error(err);
- }
-private:
- L m_tokens;
- PP *m_parent;
- std::size_t m_pos;
-};
-
-#define CHECKTOK2(p_op, p_prio) \
- else if (tok == # p_op) \
- { \
- if (!has_val) \
- { sexpr.error("parsing error!"); return 1;} \
- if (prio < (p_prio)) \
- return val; \
- sexpr.next(); \
- const auto v2 = prepro_expr(sexpr, (p_prio)); \
- val = (val p_op v2); \
- } \
-
-// Operator precedence see https://en.cppreference.com/w/cpp/language/operator_precedence
-
-template <typename PP>
-static int prepro_expr(simple_iter<PP> &sexpr, int prio)
-{
- int val(0);
- bool has_val(false);
-
- pstring tok=sexpr.peek_ws();
- if (tok == "(")
- {
- sexpr.next();
- val = prepro_expr(sexpr, 255);
- if (sexpr.next() != ")")
- sexpr.error("expected ')'");
- has_val = true;
- }
- while (!sexpr.eod())
- {
- tok = sexpr.peek_ws();
- if (tok == ")")
- {
- if (!has_val)
- sexpr.error("Found ')' but have no value computed");
- else
- return val;
- }
- else if (tok == "!")
- {
- if (prio < 3)
- {
- if (!has_val)
- sexpr.error("parsing error!");
- else
- return val;
- }
- sexpr.next();
- val = !prepro_expr(sexpr, 3);
- has_val = true;
- }
- CHECKTOK2(*, 5)
- CHECKTOK2(/, 5) // NOLINT(clang-analyzer-core.DivideZero)
- CHECKTOK2(+, 6)
- CHECKTOK2(-, 6)
- CHECKTOK2(==, 10)
- CHECKTOK2(&&, 14)
- CHECKTOK2(||, 15)
- else
- {
- val = plib::pstonum<decltype(val)>(tok);
- has_val = true;
- sexpr.next();
- }
- }
- if (!has_val)
- sexpr.error("No value computed. Empty expression ?");
- return val;
-}
-
-ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
-{
- auto idx = m_defines.find(name);
- return (idx != m_defines.end()) ? &idx->second : nullptr;
-}
-
-ppreprocessor::string_list ppreprocessor::tokenize(const pstring &str,
- const string_list &sep, bool remove_ws, bool concat)
-{
- const pstring STR = "\"";
- string_list tmpret;
- string_list tmp(psplit(str, sep));
- std::size_t pi(0);
-
- while (pi < tmp.size())
- {
- if (tmp[pi] == STR)
- {
- pstring s(STR);
- pi++;
- // FIXME : \"
- while (pi < tmp.size() && tmp[pi] != STR)
- {
- s += tmp[pi];
- pi++;
- }
- s += STR;
- tmpret.push_back(s);
- }
- else
- if (!remove_ws || (tmp[pi] != " " && tmp[pi] != "\t"))
- tmpret.push_back(tmp[pi]);
- pi++;
- }
- if (!concat)
- return tmpret;
- else
- {
- // FIXME: error if concat at beginning or end
- string_list ret;
- pi = 0;
- while (pi<tmpret.size())
- {
- if (tmpret[pi] == "##")
- {
- while (ret.back() == " " || ret.back() == "\t")
- ret.pop_back();
- pstring cc = ret.back();
- ret.pop_back();
- pi++;
- while (pi < tmpret.size() && (tmpret[pi] == " " || tmpret[pi] == "\t"))
- pi++;
- if (pi == tmpret.size())
- error("## found at end of sequence");
- ret.push_back(cc + tmpret[pi]);
- }
- else
- ret.push_back(tmpret[pi]);
- pi++;
- }
- return ret;
- }
-}
-
-bool ppreprocessor::is_valid_token(const pstring &str)
-{
- if (str.length() == 0)
- return false;
- char c = str.at(0);
- return ((c>='a' && c<='z') || (c>='A' && c<='Z') || c == '_');
-}
-
-pstring ppreprocessor::replace_macros(const pstring &line)
-{
- //std::vector<pstring> elems(psplit(line, m_expr_sep));
- bool repeat(false);
- pstring tmpret(line);
- do
- {
- repeat = false;
- auto elems(simple_iter<ppreprocessor>(this, tokenize(tmpret, m_expr_sep, false, true)));
- tmpret = "";
- while (!elems.eod())
- {
- auto token(elems.next_ws());
- define_t *def = get_define(token);
- if (def == nullptr)
- tmpret += token;
- else if (!def->m_has_params)
- {
- tmpret += def->m_replace;
- repeat = true;
- }
- else
- {
- token = elems.next();
- if (token != "(")
- error("expected '(' in macro expansion of " + def->m_name);
- string_list rep;
- token = elems.next();
- while (token != ")")
- {
- pstring par("");
- int pcnt(1);
- while (true)
- {
- if (pcnt==1 && token == ",")
- {
- token = elems.next();
- break;
- }
- if (token == "(")
- pcnt++;
- if (token == ")")
- if (--pcnt == 0)
- break;
- par += token;
- token = elems.next();
- }
- rep.push_back(par);
- }
- repeat = true;
- if (def->m_params.size() != rep.size())
- error(pfmt("Expected {1} parameters, got {2}")(def->m_params.size(), rep.size()));
- auto r(simple_iter<ppreprocessor>(this, tokenize(def->m_replace, m_expr_sep, false, false)));
- bool stringify_next = false;
- while (!r.eod())
- {
- pstring token(r.next());
- if (token == "#")
- stringify_next = true;
- else if (token != " " && token != "\t")
- {
- for (std::size_t i=0; i<def->m_params.size(); i++)
- if (def->m_params[i] == token)
- {
- if (stringify_next)
- {
- stringify_next = false;
- token = "\"" + rep[i] + "\"";
- }
- else
- token = rep[i];
- break;
- }
- if (stringify_next)
- error("'#' is not followed by a macro parameter");
- tmpret += token;
- tmpret += " "; // make sure this is not concatenated with next token
- }
- else
- tmpret += token;
- }
- }
- }
- } while (repeat);
-
- return tmpret;
-}
-
-static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, const pstring &sep)
-{
- pstring ret("");
- for (std::size_t i = start; i < elems.size(); i++)
- {
- ret += elems[i];
- ret += sep;
- }
- return ret;
-}
-
-pstring ppreprocessor::process_comments(pstring line)
-{
- bool in_string = false;
-
- std::size_t e = line.size();
- pstring ret = "";
- for (std::size_t i=0; i < e; )
- {
- pstring c = plib::left(line, 1);
- line = line.substr(1);
- if (!m_comment)
- {
- if (c=="\"")
- {
- in_string = !in_string;
- ret += c;
- }
- else if (in_string && c=="\\")
- {
- i++;
- ret += (c + plib::left(line, 1));
- line = line.substr(1);
- }
- else if (!in_string && c=="/" && plib::left(line,1) == "*")
- m_comment = true;
- else if (!in_string && c=="/" && plib::left(line,1) == "/")
- break;
- else
- ret += c;
- }
- else
- if (c=="*" && plib::left(line,1) == "/")
- {
- i++;
- line = line.substr(1);
- m_comment = false;
- }
- i++;
- }
- return ret;
-}
-
-std::pair<pstring,bool> ppreprocessor::process_line(pstring line)
-{
- bool line_cont = plib::right(line, 1) == "\\";
- if (line_cont)
- line = plib::left(line, line.size() - 1);
-
- if (m_state == LINE_CONTINUATION)
- m_line += line;
- else
- m_line = line;
-
- if (line_cont)
- {
- m_state = LINE_CONTINUATION;
- return {"", false};
- }
- else
- m_state = PROCESS;
-
- line = process_comments(m_line);
-
- pstring lt = plib::trim(plib::replace_all(line, "\t", " "));
- // FIXME ... revise and extend macro handling
- if (plib::startsWith(lt, "#"))
- {
- string_list lti(psplit(lt, " ", true));
- if (lti[0] == "#if")
- {
- m_if_level++;
- lt = replace_macros(lt);
- //std::vector<pstring> t(psplit(replace_all(lt.substr(3), " ", ""), m_expr_sep));
- auto t(simple_iter<ppreprocessor>(this, tokenize(lt.substr(3), m_expr_sep, true, true)));
- auto val = static_cast<int>(prepro_expr(t, 255));
- t.skip_ws();
- if (!t.eod())
- error("found unprocessed content at end of line");
- if (val == 0)
- m_if_flag |= (1 << m_if_level);
- }
- else if (lti[0] == "#ifdef")
- {
- m_if_level++;
- if (get_define(lti[1]) == nullptr)
- m_if_flag |= (1 << m_if_level);
- }
- else if (lti[0] == "#ifndef")
- {
- m_if_level++;
- if (get_define(lti[1]) != nullptr)
- m_if_flag |= (1 << m_if_level);
- }
- else if (lti[0] == "#else")
- {
- m_if_flag ^= (1 << m_if_level);
- }
- else if (lti[0] == "#endif")
- {
- m_if_flag &= ~(1 << m_if_level);
- m_if_level--;
- }
- else if (lti[0] == "#include")
- {
- if (m_if_flag == 0)
- {
- pstring arg("");
- for (std::size_t i=1; i<lti.size(); i++)
- arg += (lti[i] + " ");
-
- arg = plib::trim(arg);
-
- if (startsWith(arg, "\"") && endsWith(arg, "\""))
- {
- arg = arg.substr(1, arg.length() - 2);
- /* first try local context */
- auto l(plib::util::buildpath({m_stack.back().m_local_path, arg}));
- auto lstrm(m_sources.get_stream<>(l));
- if (lstrm)
- {
- m_stack.emplace_back(input_context(std::move(lstrm), plib::util::path(l), l));
- }
- else
- {
- auto strm(m_sources.get_stream<>(arg));
- if (strm)
- {
- m_stack.emplace_back(input_context(std::move(strm), plib::util::path(arg), arg));
- }
- else
- error("include not found:" + arg);
- }
- }
- else
- error("include misspelled:" + arg);
- pstring linemarker = pfmt("# {1} \"{2}\" 1\n")(m_stack.back().m_lineno, m_stack.back().m_name);
- push_out(linemarker);
- }
- }
- else if (lti[0] == "#pragma")
- {
- if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
- {
- if (lti[2] == "warning")
- error("NETLIST: " + catremainder(lti, 3, " "));
- }
- }
- else if (lti[0] == "#define")
- {
- if (m_if_flag == 0)
- {
- if (lti.size() < 2)
- error("define needs at least one argument");
- auto args(simple_iter<ppreprocessor>(this, tokenize(lt.substr(8), m_expr_sep, false, false)));
- pstring n = args.next();
- if (!is_valid_token(n))
- error("define expected identifier");
- if (args.next_ws() == "(")
- {
- define_t def(n);
- def.m_has_params = true;
- auto token(args.next());
- while (true)
- {
- if (token == ")")
- break;
- def.m_params.push_back(token);
- token = args.next();
- if (token != "," && token != ")")
- error(pfmt("expected , or ), found <{1}>")(token));
- if (token == ",")
- token = args.next();
- }
- pstring r;
- while (!args.eod())
- r += args.next_ws();
- def.m_replace = r;
- m_defines.insert({n, def});
- }
- else
- {
- pstring r;
- while (!args.eod())
- r += args.next_ws();
- m_defines.insert({n, define_t(n, r)});
- }
- }
- }
- else
- {
- if (m_if_flag == 0)
- error("unknown directive");
- }
- return { "", false };
- }
- else
- {
- if (m_if_flag == 0)
- return { replace_macros(lt), true };
- else
- return { "", false };
- }
-}
-
-void ppreprocessor::push_out(pstring s)
-{
- m_outbuf += decltype(m_outbuf)(s.c_str());
- if (m_debug_out)
- std::cerr << s;
-}
-
-
-void ppreprocessor::process_stack()
-{
- while (m_stack.size() > 0)
- {
- pstring 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));
- if (r.second)
- {
- if (last_skipped)
- push_out(pfmt("# {1} \"{2}\"\n")(m_stack.back().m_lineno, m_stack.back().m_name));
- push_out(r.first + "\n");
- last_skipped = false;
- }
- else
- last_skipped = true;
- }
- m_stack.pop_back();
- if (m_stack.size() > 0)
- {
- linemarker = pfmt("# {1} \"{2}\" 2\n")(m_stack.back().m_lineno, m_stack.back().m_name);
- push_out(linemarker);
- }
- }
-}
-
-
-
-} // namespace plib
diff --git a/src/lib/netlist/plib/pparser.h b/src/lib/netlist/plib/pparser.h
deleted file mode 100644
index ed67289dea8..00000000000
--- a/src/lib/netlist/plib/pparser.h
+++ /dev/null
@@ -1,318 +0,0 @@
-// license:GPL-2.0+
-// copyright-holders:Couriersud
-/*
- * pparser.h
- *
- */
-
-#ifndef PPARSER_H_
-#define PPARSER_H_
-
-#include "plists.h"
-#include "pstream.h"
-#include "pstring.h"
-
-#include "putil.h" // psource_t
-
-//#include <cstdint>
-#include <unordered_map>
-#include <vector>
-
-namespace plib {
-class ptokenizer
-{
-public:
- template <typename T>
- ptokenizer(T &&strm) // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
- : m_strm(std::forward<T>(strm))
- , m_cur_line("")
- , m_px(m_cur_line.begin())
- , m_unget(0)
- , m_string('"')
- , m_support_line_markers(true) // FIXME
- {
- // add a first entry to the stack
- m_source_location.emplace_back(plib::source_location("Unknown", 0));
- }
-
- COPYASSIGNMOVE(ptokenizer, delete)
-
- virtual ~ptokenizer() = default;
-
- enum token_type
- {
- IDENTIFIER,
- NUMBER,
- TOKEN,
- STRING,
- COMMENT,
- LINEMARKER,
- UNKNOWN,
- ENDOFFILE
- };
-
- struct token_id_t
- {
- public:
-
- static constexpr std::size_t npos = static_cast<std::size_t>(-1);
-
- token_id_t() : m_id(npos) {}
- explicit token_id_t(const std::size_t id) : m_id(id) {}
- std::size_t id() const { return m_id; }
- private:
- std::size_t m_id;
- };
-
- struct token_t
- {
- explicit token_t(token_type type)
- : m_type(type), m_id(), m_token("")
- {
- }
- token_t(token_type type, const pstring &str)
- : m_type(type), m_id(), m_token(str)
- {
- }
- token_t(const token_id_t &id, const pstring &str)
- : m_type(TOKEN), m_id(id), m_token(str)
- {
- }
-
- bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
- bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
-
- bool is_type(const token_type type) const { return m_type == type; }
-
- pstring str() const { return m_token; }
-
- private:
- token_type m_type;
- token_id_t m_id;
- pstring m_token;
- };
-
- pstring currentline_str();
-
- /* tokenizer stuff follows ... */
-
- token_t get_token();
- pstring get_string();
- pstring get_identifier();
- pstring get_identifier_or_number();
- double get_number_double();
- long get_number_long();
-
- void require_token(const token_id_t &token_num);
- void require_token(const token_t &tok, const token_id_t &token_num);
-
- token_id_t register_token(const pstring &token)
- {
- token_id_t ret(m_tokens.size());
- m_tokens.emplace(token, ret);
- return ret;
- }
-
- ptokenizer & identifier_chars(const pstring &s) { m_identifier_chars = s; return *this; }
- ptokenizer & number_chars(const pstring &st, const pstring & rem) { m_number_chars_start = st; m_number_chars = rem; return *this; }
- ptokenizer & string_char(pstring::value_type c) { m_string = c; return *this; }
- ptokenizer & whitespace(const pstring & s) { m_whitespace = s; return *this; }
- ptokenizer & comment(const pstring &start, const pstring &end, const pstring &line)
- {
- m_tok_comment_start = register_token(start);
- m_tok_comment_end = register_token(end);
- m_tok_line_comment = register_token(line);
- return *this;
- }
-
- token_t get_token_internal();
- void error(const pstring &errs);
-
- putf8_reader &stream() { return m_strm; }
-protected:
- virtual void verror(const pstring &msg) = 0;
-
-private:
- void skipeol();
-
- pstring::value_type getc();
- void ungetc(pstring::value_type c);
-
- bool eof() { return m_strm.eof(); }
-
- putf8_reader m_strm;
-
- pstring m_cur_line;
- pstring::const_iterator m_px;
- pstring::value_type m_unget;
-
- /* tokenizer stuff follows ... */
-
- pstring m_identifier_chars;
- pstring m_number_chars;
- pstring m_number_chars_start;
- std::unordered_map<pstring, token_id_t> m_tokens;
- pstring m_whitespace;
- pstring::value_type m_string;
-
- token_id_t m_tok_comment_start;
- token_id_t m_tok_comment_end;
- token_id_t m_tok_line_comment;
-
- /* source locations, vector used as stack because we need to loop through stack */
- bool m_support_line_markers;
- std::vector<plib::source_location> m_source_location;
-};
-
-
-class ppreprocessor : public std::istream
-{
-public:
-
- using string_list = std::vector<pstring>;
-
- struct define_t
- {
- define_t(const pstring &name, const pstring &replace)
- : m_name(name), m_replace(replace), m_has_params(false)
- {}
- define_t(const pstring &name)
- : m_name(name), m_replace(""), m_has_params(false)
- {}
- pstring m_name;
- pstring m_replace;
- bool m_has_params;
- string_list m_params;
- };
-
- using defines_map_type = std::unordered_map<pstring, define_t>;
-
- explicit ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines = nullptr);
-
- COPYASSIGN(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_outbuf(std::move(s.m_outbuf))
- , m_pos(s.m_pos)
- , m_state(s.m_state)
- , m_comment(s.m_comment)
- , m_debug_out(s.m_debug_out)
- {
- }
-
- ~ppreprocessor() override
- {
- delete rdbuf();
- }
-
- template <typename T>
- ppreprocessor & process(T &&istrm)
- {
- m_stack.emplace_back(input_context(std::forward<T>(istrm),"","<stream>"));
- process_stack();
- return *this;
- }
-
- void error(const pstring &err);
-
-protected:
-
- class readbuffer : public std::streambuf
- {
- public:
- readbuffer(ppreprocessor *strm) : m_strm(strm), m_buf() { setg(nullptr, nullptr, nullptr); }
- readbuffer(readbuffer &&rhs) noexcept : m_strm(rhs.m_strm), m_buf() {}
- COPYASSIGN(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 = pstring_mem_t_size(m_strm->m_outbuf) - static_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());
- //printf("%ld\n", (long int)bytes);
- this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
-
- m_strm->m_pos += static_cast</*pos_type*/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);
-
-private:
-
- enum state_e
- {
- PROCESS,
- LINE_CONTINUATION
- };
-
- void push_out(pstring s);
-
- void process_stack();
-
- string_list tokenize(const pstring &str, const string_list &sep, bool remove_ws, bool concat);
- bool is_valid_token(const pstring &str);
-
- std::pair<pstring,bool> process_line(pstring line);
- pstring process_comments(pstring line);
-
- defines_map_type m_defines;
- psource_collection_t<> &m_sources;
- string_list m_expr_sep;
-
- std::uint_least64_t m_if_flag; // 31 if levels
- int m_if_level;
-
- struct input_context
- {
- template <typename T>
- input_context(T &&istrm, const pstring &local_path, const pstring &name)
- : m_reader(std::forward<T>(istrm))
- , m_lineno(0)
- , m_local_path(local_path)
- , m_name(name)
- {}
-
- putf8_reader m_reader;
- int m_lineno;
- pstring m_local_path;
- pstring m_name;
- };
-
- /* vector used as stack because we need to loop through stack */
- std::vector<input_context> m_stack;
- pstring_t<pu8_traits> m_outbuf;
- std::istream::pos_type m_pos;
- state_e m_state;
- pstring m_line;
- bool m_comment;
- bool m_debug_out;
-
-};
-
-} // namespace plib
-
-#endif /* PPARSER_H_ */
diff --git a/src/lib/netlist/plib/ppreprocessor.cpp b/src/lib/netlist/plib/ppreprocessor.cpp
new file mode 100644
index 00000000000..e29be1757ed
--- /dev/null
+++ b/src/lib/netlist/plib/ppreprocessor.cpp
@@ -0,0 +1,628 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ppreprocessor.cpp
+ *
+ */
+
+#include "ppreprocessor.h"
+#include "palloc.h"
+#include "putil.h"
+
+namespace plib {
+
+ // ----------------------------------------------------------------------------------------
+ // A simple preprocessor
+ // ----------------------------------------------------------------------------------------
+
+ ppreprocessor::ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines)
+ : std::istream(new readbuffer(this))
+ , m_sources(sources)
+ , m_if_flag(0)
+ , m_if_level(0)
+ , m_pos(0)
+ , m_state(PROCESS)
+ , m_comment(false)
+ {
+ m_expr_sep.emplace_back("!");
+ m_expr_sep.emplace_back("(");
+ m_expr_sep.emplace_back(")");
+ m_expr_sep.emplace_back("+");
+ m_expr_sep.emplace_back("-");
+ m_expr_sep.emplace_back("*");
+ m_expr_sep.emplace_back("/");
+ m_expr_sep.emplace_back("&&");
+ m_expr_sep.emplace_back("||");
+ m_expr_sep.emplace_back("==");
+ m_expr_sep.emplace_back(",");
+ m_expr_sep.emplace_back(";");
+ m_expr_sep.emplace_back(".");
+ m_expr_sep.emplace_back("##");
+ m_expr_sep.emplace_back("#");
+ m_expr_sep.emplace_back(" ");
+ m_expr_sep.emplace_back("\t");
+ m_expr_sep.emplace_back("\"");
+
+ if (defines != nullptr)
+ m_defines = *defines;
+ m_defines.insert({"__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1")});
+ auto idx = m_defines.find("__PREPROCESSOR_DEBUG__");
+ m_debug_out = idx != m_defines.end();
+
+ }
+
+ void ppreprocessor::error(const pstring &err)
+ {
+ pstring s("");
+ pstring trail (" from ");
+ pstring trail_first("In file included from ");
+ pstring e = plib::pfmt("{1}:{2}:0: error: {3}\n")
+ (m_stack.back().m_name, m_stack.back().m_lineno, err);
+ m_stack.pop_back();
+ while (m_stack.size() > 0)
+ {
+ if (m_stack.size() == 1)
+ trail = trail_first;
+ s = trail + plib::pfmt("{1}:{2}:0\n")(m_stack.back().m_name, m_stack.back().m_lineno) + s;
+ m_stack.pop_back();
+ }
+ throw pexception("\n" + s + e + " " + m_line + "\n");
+ }
+
+ template <typename PP, typename L = ppreprocessor::string_list>
+ struct simple_iter
+ {
+ simple_iter(PP *parent, const L &tokens)
+ : m_tokens(tokens), m_parent(parent), m_pos(0)
+ {}
+
+ /**! skip white space in token list
+ *
+ */
+ void skip_ws()
+ {
+ while (m_pos < m_tokens.size() && (m_tokens[m_pos] == " " || m_tokens[m_pos] == "\t"))
+ m_pos++;
+ }
+
+ /**! return next token skipping white space
+ *
+ * @return next token
+ */
+ pstring next()
+ {
+ skip_ws();
+ if (m_pos >= m_tokens.size())
+ error("unexpected end of line");
+ return m_tokens[m_pos++];
+ }
+
+ /**! return next token including white space
+ *
+ * @return next token
+ */
+ pstring next_ws()
+ {
+ if (m_pos >= m_tokens.size())
+ error("unexpected end of line");
+ return m_tokens[m_pos++];
+ }
+
+ pstring peek_ws()
+ {
+ if (m_pos >= m_tokens.size())
+ error("unexpected end of line");
+ return m_tokens[m_pos];
+ }
+
+ pstring last()
+ {
+ if (m_pos == 0)
+ error("no last token at beginning of line");
+ if (m_pos > m_tokens.size())
+ error("unexpected end of line");
+ return m_tokens[m_pos-1];
+ }
+
+ bool eod()
+ {
+ return (m_pos >= m_tokens.size());
+ }
+
+ void error(pstring err)
+ {
+ m_parent->error(err);
+ }
+ private:
+ L m_tokens;
+ PP *m_parent;
+ std::size_t m_pos;
+ };
+
+ #define CHECKTOK2(p_op, p_prio) \
+ else if (tok == # p_op) \
+ { \
+ if (!has_val) \
+ { sexpr.error("parsing error!"); return 1;} \
+ if (prio < (p_prio)) \
+ return val; \
+ sexpr.next(); \
+ const auto v2 = prepro_expr(sexpr, (p_prio)); \
+ val = (val p_op v2); \
+ } \
+
+ // Operator precedence see https://en.cppreference.com/w/cpp/language/operator_precedence
+
+ template <typename PP>
+ static int prepro_expr(simple_iter<PP> &sexpr, int prio)
+ {
+ int val(0);
+ bool has_val(false);
+
+ pstring tok=sexpr.peek_ws();
+ if (tok == "(")
+ {
+ sexpr.next();
+ val = prepro_expr(sexpr, 255);
+ if (sexpr.next() != ")")
+ sexpr.error("expected ')'");
+ has_val = true;
+ }
+ while (!sexpr.eod())
+ {
+ tok = sexpr.peek_ws();
+ if (tok == ")")
+ {
+ if (!has_val)
+ sexpr.error("Found ')' but have no value computed");
+ else
+ return val;
+ }
+ else if (tok == "!")
+ {
+ if (prio < 3)
+ {
+ if (!has_val)
+ sexpr.error("parsing error!");
+ else
+ return val;
+ }
+ sexpr.next();
+ val = !prepro_expr(sexpr, 3);
+ has_val = true;
+ }
+ CHECKTOK2(*, 5)
+ CHECKTOK2(/, 5) // NOLINT(clang-analyzer-core.DivideZero)
+ CHECKTOK2(+, 6)
+ CHECKTOK2(-, 6)
+ CHECKTOK2(==, 10)
+ CHECKTOK2(&&, 14)
+ CHECKTOK2(||, 15)
+ else
+ {
+ val = plib::pstonum<decltype(val)>(tok);
+ has_val = true;
+ sexpr.next();
+ }
+ }
+ if (!has_val)
+ sexpr.error("No value computed. Empty expression ?");
+ return val;
+ }
+
+ ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
+ {
+ auto idx = m_defines.find(name);
+ return (idx != m_defines.end()) ? &idx->second : nullptr;
+ }
+
+ ppreprocessor::string_list ppreprocessor::tokenize(const pstring &str,
+ const string_list &sep, bool remove_ws, bool concat)
+ {
+ const pstring STR = "\"";
+ string_list tmpret;
+ string_list tmp(psplit(str, sep));
+ std::size_t pi(0);
+
+ while (pi < tmp.size())
+ {
+ if (tmp[pi] == STR)
+ {
+ pstring s(STR);
+ pi++;
+ // FIXME : \"
+ while (pi < tmp.size() && tmp[pi] != STR)
+ {
+ s += tmp[pi];
+ pi++;
+ }
+ s += STR;
+ tmpret.push_back(s);
+ }
+ else
+ if (!remove_ws || (tmp[pi] != " " && tmp[pi] != "\t"))
+ tmpret.push_back(tmp[pi]);
+ pi++;
+ }
+ if (!concat)
+ return tmpret;
+ else
+ {
+ // FIXME: error if concat at beginning or end
+ string_list ret;
+ pi = 0;
+ while (pi<tmpret.size())
+ {
+ if (tmpret[pi] == "##")
+ {
+ while (ret.back() == " " || ret.back() == "\t")
+ ret.pop_back();
+ pstring cc = ret.back();
+ ret.pop_back();
+ pi++;
+ while (pi < tmpret.size() && (tmpret[pi] == " " || tmpret[pi] == "\t"))
+ pi++;
+ if (pi == tmpret.size())
+ error("## found at end of sequence");
+ ret.push_back(cc + tmpret[pi]);
+ }
+ else
+ ret.push_back(tmpret[pi]);
+ pi++;
+ }
+ return ret;
+ }
+ }
+
+ bool ppreprocessor::is_valid_token(const pstring &str)
+ {
+ if (str.length() == 0)
+ return false;
+ pstring::value_type c(str.at(0));
+ return ((c>='a' && c<='z') || (c>='A' && c<='Z') || c == '_');
+ }
+
+ pstring ppreprocessor::replace_macros(const pstring &line)
+ {
+ //std::vector<pstring> elems(psplit(line, m_expr_sep));
+ bool repeat(false);
+ pstring tmpret(line);
+ do
+ {
+ repeat = false;
+ auto elems(simple_iter<ppreprocessor>(this, tokenize(tmpret, m_expr_sep, false, true)));
+ tmpret = "";
+ while (!elems.eod())
+ {
+ auto token(elems.next_ws());
+ define_t *def = get_define(token);
+ if (def == nullptr)
+ tmpret += token;
+ else if (!def->m_has_params)
+ {
+ tmpret += def->m_replace;
+ repeat = true;
+ }
+ else
+ {
+ token = elems.next();
+ if (token != "(")
+ error("expected '(' in macro expansion of " + def->m_name);
+ string_list rep;
+ token = elems.next();
+ while (token != ")")
+ {
+ pstring par("");
+ int pcnt(1);
+ while (true)
+ {
+ if (pcnt==1 && token == ",")
+ {
+ token = elems.next();
+ break;
+ }
+ if (token == "(")
+ pcnt++;
+ if (token == ")")
+ if (--pcnt == 0)
+ break;
+ par += token;
+ token = elems.next();
+ }
+ rep.push_back(par);
+ }
+ repeat = true;
+ if (def->m_params.size() != rep.size())
+ error(pfmt("Expected {1} parameters, got {2}")(def->m_params.size(), rep.size()));
+ auto r(simple_iter<ppreprocessor>(this, tokenize(def->m_replace, m_expr_sep, false, false)));
+ bool stringify_next = false;
+ while (!r.eod())
+ {
+ token = r.next();
+ if (token == "#")
+ stringify_next = true;
+ else if (token != " " && token != "\t")
+ {
+ for (std::size_t i=0; i<def->m_params.size(); i++)
+ if (def->m_params[i] == token)
+ {
+ if (stringify_next)
+ {
+ stringify_next = false;
+ token = "\"" + rep[i] + "\"";
+ }
+ else
+ token = rep[i];
+ break;
+ }
+ if (stringify_next)
+ error("'#' is not followed by a macro parameter");
+ tmpret += token;
+ tmpret += " "; // make sure this is not concatenated with next token
+ }
+ else
+ tmpret += token;
+ }
+ }
+ }
+ } while (repeat);
+
+ return tmpret;
+ }
+
+ static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, const pstring &sep)
+ {
+ pstring ret("");
+ for (std::size_t i = start; i < elems.size(); i++)
+ {
+ ret += elems[i];
+ ret += sep;
+ }
+ return ret;
+ }
+
+ pstring ppreprocessor::process_comments(pstring line)
+ {
+ bool in_string = false;
+
+ std::size_t e = line.size();
+ pstring ret = "";
+ for (std::size_t i=0; i < e; )
+ {
+ pstring c = plib::left(line, 1);
+ line = line.substr(1);
+ if (!m_comment)
+ {
+ if (c=="\"")
+ {
+ in_string = !in_string;
+ ret += c;
+ }
+ else if (in_string && c=="\\")
+ {
+ i++;
+ ret += (c + plib::left(line, 1));
+ line = line.substr(1);
+ }
+ else if (!in_string && c=="/" && plib::left(line,1) == "*")
+ m_comment = true;
+ else if (!in_string && c=="/" && plib::left(line,1) == "/")
+ break;
+ else
+ ret += c;
+ }
+ else
+ if (c=="*" && plib::left(line,1) == "/")
+ {
+ i++;
+ line = line.substr(1);
+ m_comment = false;
+ }
+ i++;
+ }
+ return ret;
+ }
+
+ std::pair<pstring,bool> ppreprocessor::process_line(pstring line)
+ {
+ bool line_cont = plib::right(line, 1) == "\\";
+ if (line_cont)
+ line = plib::left(line, line.size() - 1);
+
+ if (m_state == LINE_CONTINUATION)
+ m_line += line;
+ else
+ m_line = line;
+
+ if (line_cont)
+ {
+ m_state = LINE_CONTINUATION;
+ return {"", false};
+ }
+ else
+ m_state = PROCESS;
+
+ line = process_comments(m_line);
+
+ pstring lt = plib::trim(plib::replace_all(line, "\t", " "));
+ // FIXME ... revise and extend macro handling
+ if (plib::startsWith(lt, "#"))
+ {
+ string_list lti(psplit(lt, " ", true));
+ if (lti[0] == "#if")
+ {
+ m_if_level++;
+ lt = replace_macros(lt);
+ //std::vector<pstring> t(psplit(replace_all(lt.substr(3), " ", ""), m_expr_sep));
+ auto t(simple_iter<ppreprocessor>(this, tokenize(lt.substr(3), m_expr_sep, true, true)));
+ auto val = static_cast<int>(prepro_expr(t, 255));
+ t.skip_ws();
+ if (!t.eod())
+ error("found unprocessed content at end of line");
+ if (val == 0)
+ m_if_flag |= (1 << m_if_level);
+ }
+ else if (lti[0] == "#ifdef")
+ {
+ m_if_level++;
+ if (get_define(lti[1]) == nullptr)
+ m_if_flag |= (1 << m_if_level);
+ }
+ else if (lti[0] == "#ifndef")
+ {
+ m_if_level++;
+ if (get_define(lti[1]) != nullptr)
+ m_if_flag |= (1 << m_if_level);
+ }
+ else if (lti[0] == "#else")
+ {
+ m_if_flag ^= (1 << m_if_level);
+ }
+ else if (lti[0] == "#endif")
+ {
+ m_if_flag &= ~(1 << m_if_level);
+ m_if_level--;
+ }
+ else if (lti[0] == "#include")
+ {
+ if (m_if_flag == 0)
+ {
+ pstring arg("");
+ for (std::size_t i=1; i<lti.size(); i++)
+ arg += (lti[i] + " ");
+
+ arg = plib::trim(arg);
+
+ if (startsWith(arg, "\"") && endsWith(arg, "\""))
+ {
+ arg = arg.substr(1, arg.length() - 2);
+ /* first try local context */
+ auto l(plib::util::buildpath({m_stack.back().m_local_path, arg}));
+ auto lstrm(m_sources.get_stream<>(l));
+ if (lstrm)
+ {
+ m_stack.emplace_back(input_context(std::move(lstrm), plib::util::path(l), l));
+ }
+ else
+ {
+ auto strm(m_sources.get_stream<>(arg));
+ if (strm)
+ {
+ m_stack.emplace_back(input_context(std::move(strm), plib::util::path(arg), arg));
+ }
+ else
+ error("include not found:" + arg);
+ }
+ }
+ else
+ error("include misspelled:" + arg);
+ pstring linemarker = pfmt("# {1} \"{2}\" 1\n")(m_stack.back().m_lineno, m_stack.back().m_name);
+ push_out(linemarker);
+ }
+ }
+ else if (lti[0] == "#pragma")
+ {
+ if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
+ {
+ if (lti[2] == "warning")
+ error("NETLIST: " + catremainder(lti, 3, " "));
+ }
+ }
+ else if (lti[0] == "#define")
+ {
+ if (m_if_flag == 0)
+ {
+ if (lti.size() < 2)
+ error("define needs at least one argument");
+ auto args(simple_iter<ppreprocessor>(this, tokenize(lt.substr(8), m_expr_sep, false, false)));
+ pstring n = args.next();
+ if (!is_valid_token(n))
+ error("define expected identifier");
+ if (args.next_ws() == "(")
+ {
+ define_t def(n);
+ def.m_has_params = true;
+ auto token(args.next());
+ while (true)
+ {
+ if (token == ")")
+ break;
+ def.m_params.push_back(token);
+ token = args.next();
+ if (token != "," && token != ")")
+ error(pfmt("expected , or ), found <{1}>")(token));
+ if (token == ",")
+ token = args.next();
+ }
+ pstring r;
+ while (!args.eod())
+ r += args.next_ws();
+ def.m_replace = r;
+ m_defines.insert({n, def});
+ }
+ else
+ {
+ pstring r;
+ while (!args.eod())
+ r += args.next_ws();
+ m_defines.insert({n, define_t(n, r)});
+ }
+ }
+ }
+ else
+ {
+ if (m_if_flag == 0)
+ error("unknown directive");
+ }
+ return { "", false };
+ }
+ else
+ {
+ if (m_if_flag == 0)
+ return { replace_macros(lt), true };
+ else
+ return { "", false };
+ }
+ }
+
+ void ppreprocessor::push_out(const pstring &s)
+ {
+ m_outbuf += decltype(m_outbuf)(s.c_str());
+ if (m_debug_out)
+ std::cerr << s;
+ }
+
+ void ppreprocessor::process_stack()
+ {
+ while (m_stack.size() > 0)
+ {
+ pstring 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));
+ if (r.second)
+ {
+ if (last_skipped)
+ push_out(pfmt("# {1} \"{2}\"\n")(m_stack.back().m_lineno, m_stack.back().m_name));
+ push_out(r.first + "\n");
+ last_skipped = false;
+ }
+ else
+ last_skipped = true;
+ }
+ m_stack.pop_back();
+ if (m_stack.size() > 0)
+ {
+ linemarker = pfmt("# {1} \"{2}\" 2\n")(m_stack.back().m_lineno, m_stack.back().m_name);
+ push_out(linemarker);
+ }
+ }
+ }
+
+
+
+} // namespace plib
diff --git a/src/lib/netlist/plib/ppreprocessor.h b/src/lib/netlist/plib/ppreprocessor.h
new file mode 100644
index 00000000000..1df9c2e5975
--- /dev/null
+++ b/src/lib/netlist/plib/ppreprocessor.h
@@ -0,0 +1,173 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ppreprocessor.h
+ *
+ */
+
+#ifndef PPREPROCESSOR_H_
+#define PPREPROCESSOR_H_
+
+#include "plists.h"
+#include "pstream.h"
+#include "pstring.h"
+
+#include "putil.h" // psource_t
+
+#include <istream>
+#include <unordered_map>
+#include <vector>
+
+namespace plib {
+
+ class ppreprocessor : public std::istream
+ {
+ public:
+
+ using string_list = std::vector<pstring>;
+
+ struct define_t
+ {
+ define_t(const pstring &name, const pstring &replace)
+ : m_name(name), m_replace(replace), m_has_params(false)
+ {}
+ define_t(const pstring &name)
+ : m_name(name), m_replace(""), m_has_params(false)
+ {}
+ pstring m_name;
+ pstring m_replace;
+ bool m_has_params;
+ string_list m_params;
+ };
+
+ using defines_map_type = std::unordered_map<pstring, define_t>;
+
+ explicit ppreprocessor(psource_collection_t<> &sources, defines_map_type *defines = nullptr);
+
+ COPYASSIGN(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_outbuf(std::move(s.m_outbuf))
+ , m_pos(s.m_pos)
+ , m_state(s.m_state)
+ , m_comment(s.m_comment)
+ , m_debug_out(s.m_debug_out)
+ {
+ }
+
+ ~ppreprocessor() override
+ {
+ delete rdbuf();
+ }
+
+ template <typename T>
+ ppreprocessor & process(T &&istrm)
+ {
+ m_stack.emplace_back(input_context(std::forward<T>(istrm),"","<stream>"));
+ process_stack();
+ return *this;
+ }
+
+ [[noreturn]] void error(const pstring &err);
+
+ protected:
+
+ class readbuffer : public std::streambuf
+ {
+ public:
+ readbuffer(ppreprocessor *strm) : m_strm(strm), m_buf() { setg(nullptr, nullptr, nullptr); }
+ readbuffer(readbuffer &&rhs) noexcept : m_strm(rhs.m_strm), m_buf() {}
+ COPYASSIGN(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 = pstring_mem_t_size(m_strm->m_outbuf) - static_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());
+ //printf("%ld\n", (long int)bytes);
+ this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
+
+ m_strm->m_pos += static_cast</*pos_type*/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);
+
+ private:
+
+ enum state_e
+ {
+ PROCESS,
+ LINE_CONTINUATION
+ };
+
+ void push_out(const pstring &s);
+
+ void process_stack();
+
+ string_list tokenize(const pstring &str, const string_list &sep, bool remove_ws, bool concat);
+ bool is_valid_token(const pstring &str);
+
+ std::pair<pstring,bool> process_line(pstring line);
+ pstring process_comments(pstring line);
+
+ defines_map_type m_defines;
+ psource_collection_t<> &m_sources;
+ string_list m_expr_sep;
+
+ std::uint_least64_t m_if_flag; // 31 if levels
+ int m_if_level;
+
+ struct input_context
+ {
+ template <typename T>
+ input_context(T &&istrm, const pstring &local_path, const pstring &name)
+ : m_reader(std::forward<T>(istrm))
+ , m_lineno(0)
+ , m_local_path(local_path)
+ , m_name(name)
+ {}
+
+ putf8_reader m_reader;
+ int m_lineno;
+ pstring m_local_path;
+ pstring m_name;
+ };
+
+ /* vector used as stack because we need to loop through stack */
+ std::vector<input_context> m_stack;
+ pstring_t<pu8_traits> m_outbuf;
+ std::istream::pos_type m_pos;
+ state_e m_state;
+ pstring m_line;
+ bool m_comment;
+ bool m_debug_out;
+
+ };
+
+} // namespace plib
+
+#endif /* PPREPROCESSOR_H_ */
diff --git a/src/lib/netlist/plib/ptokenizer.cpp b/src/lib/netlist/plib/ptokenizer.cpp
new file mode 100644
index 00000000000..fbda60de458
--- /dev/null
+++ b/src/lib/netlist/plib/ptokenizer.cpp
@@ -0,0 +1,301 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ptokenizer.cpp
+ *
+ */
+
+#include "ptokenizer.h"
+#include "palloc.h"
+#include "putil.h"
+
+namespace plib {
+
+ // ----------------------------------------------------------------------------------------
+ // A simple tokenizer
+ // ----------------------------------------------------------------------------------------
+
+ pstring ptokenizer::currentline_str()
+ {
+ return m_cur_line;
+ }
+
+ void ptokenizer::skipeol()
+ {
+ pstring::value_type c = getc();
+ while (c)
+ {
+ if (c == 10)
+ {
+ c = getc();
+ if (c != 13)
+ ungetc(c);
+ return;
+ }
+ c = getc();
+ }
+ }
+
+ pstring::value_type ptokenizer::getc()
+ {
+ if (m_unget != 0)
+ {
+ pstring::value_type c = m_unget;
+ m_unget = 0;
+ return c;
+ }
+ if (m_px == m_cur_line.end())
+ {
+ ++m_source_location.back();
+ if (m_strm.readline(m_cur_line))
+ m_px = m_cur_line.begin();
+ else
+ return 0;
+ return '\n';
+ }
+ pstring::value_type c = *(m_px++);
+ return c;
+ }
+
+ void ptokenizer::ungetc(pstring::value_type c)
+ {
+ m_unget = c;
+ }
+
+ void ptokenizer::require_token(const token_id_t &token_num)
+ {
+ require_token(get_token(), token_num);
+ }
+
+ void ptokenizer::require_token(const token_t &tok, const token_id_t &token_num)
+ {
+ if (!tok.is(token_num))
+ {
+ pstring val("");
+ for (auto &i : m_tokens)
+ if (i.second.id() == token_num.id())
+ val = i.first;
+ error(pfmt("Expected token <{1}> got <{2}>")(val)(tok.str()) );
+ }
+ }
+
+ pstring ptokenizer::get_string()
+ {
+ token_t tok = get_token();
+ if (!tok.is_type(STRING))
+ {
+ error(pfmt("Expected a string, got <{1}>")(tok.str()) );
+ }
+ return tok.str();
+ }
+
+ pstring ptokenizer::get_identifier()
+ {
+ token_t tok = get_token();
+ if (!tok.is_type(IDENTIFIER))
+ {
+ error(pfmt("Expected an identifier, got <{1}>")(tok.str()) );
+ }
+ return tok.str();
+ }
+
+ pstring ptokenizer::get_identifier_or_number()
+ {
+ token_t tok = get_token();
+ if (!(tok.is_type(IDENTIFIER) || tok.is_type(NUMBER)))
+ {
+ error(pfmt("Expected an identifier or number, got <{1}>")(tok.str()) );
+ }
+ return tok.str();
+ }
+
+ // FIXME: combine into template
+ double ptokenizer::get_number_double()
+ {
+ token_t tok = get_token();
+ if (!tok.is_type(NUMBER))
+ {
+ error(pfmt("Expected a number, got <{1}>")(tok.str()) );
+ }
+ bool err(false);
+ auto ret = plib::pstonum_ne<double>(tok.str(), err);
+ if (err)
+ error(pfmt("Expected a number, got <{1}>")(tok.str()) );
+ return ret;
+ }
+
+ long ptokenizer::get_number_long()
+ {
+ token_t tok = get_token();
+ if (!tok.is_type(NUMBER))
+ {
+ error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
+ }
+ bool err(false);
+ auto ret = plib::pstonum_ne<long>(tok.str(), err);
+ if (err)
+ error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
+ return ret;
+ }
+
+ ptokenizer::token_t ptokenizer::get_token()
+ {
+ token_t ret = get_token_internal();
+ while (true)
+ {
+ if (ret.is_type(ENDOFFILE))
+ return ret;
+ else if (m_support_line_markers && ret.is_type(LINEMARKER))
+ {
+ bool benter(false);
+ bool bexit(false);
+ pstring file;
+ unsigned lineno;
+
+ ret = get_token_internal();
+ if (!ret.is_type(NUMBER))
+ error(pfmt("Expected line number after line marker but got <{1}>")(ret.str()) );
+ lineno = pstonum<unsigned>(ret.str());
+ ret = get_token_internal();
+ if (!ret.is_type(STRING))
+ error(pfmt("Expected file name after line marker but got <{1}>")(ret.str()) );
+ file = ret.str();
+ ret = get_token_internal();
+ while (ret.is_type(NUMBER))
+ {
+ if (ret.str() == "1")
+ benter = true;
+ if (ret.str() == "2")
+ bexit = false;
+ // FIXME: process flags; actually only 1 (file enter) and 2 (after file exit)
+ ret = get_token_internal();
+ }
+ 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));
+ }
+ else if (ret.is(m_tok_comment_start))
+ {
+ do {
+ ret = get_token_internal();
+ } while (ret.is_not(m_tok_comment_end));
+ ret = get_token_internal();
+ }
+ else if (ret.is(m_tok_line_comment))
+ {
+ skipeol();
+ ret = get_token_internal();
+ }
+ else
+ {
+ return ret;
+ }
+ }
+ }
+
+ ptokenizer::token_t ptokenizer::get_token_internal()
+ {
+ /* skip ws */
+ pstring::value_type c = getc();
+ while (m_whitespace.find(c) != pstring::npos)
+ {
+ c = getc();
+ if (eof())
+ {
+ return token_t(ENDOFFILE);
+ }
+ }
+ if (m_support_line_markers && c == '#')
+ return token_t(LINEMARKER, "#");
+ else if (m_number_chars_start.find(c) != pstring::npos)
+ {
+ /* read number while we receive number or identifier chars
+ * treat it as an identifier when there are identifier chars in it
+ *
+ */
+ token_type ret = NUMBER;
+ pstring tokstr = "";
+ while (true) {
+ if (m_identifier_chars.find(c) != pstring::npos && m_number_chars.find(c) == pstring::npos)
+ ret = IDENTIFIER;
+ else if (m_number_chars.find(c) == pstring::npos)
+ break;
+ tokstr += c;
+ c = getc();
+ }
+ ungetc(c);
+ return token_t(ret, tokstr);
+ }
+ else if (m_identifier_chars.find(c) != pstring::npos)
+ {
+ /* read identifier till non identifier char */
+ pstring tokstr = "";
+ while (m_identifier_chars.find(c) != pstring::npos)
+ {
+ tokstr += c;
+ c = getc();
+ }
+ ungetc(c);
+ auto id = m_tokens.find(tokstr);
+ if (id != m_tokens.end())
+ return token_t(id->second, tokstr);
+ else
+ return token_t(IDENTIFIER, tokstr);
+ }
+ else if (c == m_string)
+ {
+ pstring tokstr = "";
+ c = getc();
+ while (c != m_string)
+ {
+ tokstr += c;
+ c = getc();
+ }
+ return token_t(STRING, tokstr);
+ }
+ else
+ {
+ /* read identifier till first identifier char or ws */
+ pstring tokstr = "";
+ while ((m_identifier_chars.find(c) == pstring::npos) && (m_whitespace.find(c) == pstring::npos))
+ {
+ tokstr += c;
+ /* expensive, check for single char tokens */
+ if (tokstr.length() == 1)
+ {
+ auto id = m_tokens.find(tokstr);
+ if (id != m_tokens.end())
+ return token_t(id->second, tokstr);
+ }
+ c = getc();
+ }
+ ungetc(c);
+ auto id = m_tokens.find(tokstr);
+ if (id != m_tokens.end())
+ return token_t(id->second, tokstr);
+ else
+ return token_t(UNKNOWN, tokstr);
+ }
+ }
+
+ void ptokenizer::error(const pstring &errs)
+ {
+ pstring s("");
+ pstring trail (" from ");
+ pstring trail_first("In file included from ");
+ pstring e = plib::pfmt("{1}:{2}:0: error: {3}\n")
+ (m_source_location.back().file_name(), m_source_location.back().line(), errs);
+ m_source_location.pop_back();
+ while (m_source_location.size() > 0)
+ {
+ if (m_source_location.size() == 1)
+ trail = trail_first;
+ s = trail + plib::pfmt("{1}:{2}:0\n")(m_source_location.back().file_name(), m_source_location.back().line()) + s;
+ m_source_location.pop_back();
+ }
+ verror("\n" + s + e + " " + currentline_str() + "\n");
+}
+
+} // namespace plib
diff --git a/src/lib/netlist/plib/ptokenizer.h b/src/lib/netlist/plib/ptokenizer.h
new file mode 100644
index 00000000000..5a6b886a2a2
--- /dev/null
+++ b/src/lib/netlist/plib/ptokenizer.h
@@ -0,0 +1,169 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * ptokenizer.h
+ *
+ */
+
+#ifndef PTOKENIZER_H_
+#define PTOKENIZER_H_
+
+#include "plists.h"
+#include "pstream.h"
+#include "pstring.h"
+
+#include "putil.h" // psource_t
+
+#include <unordered_map>
+#include <vector>
+
+namespace plib {
+
+ class ptokenizer
+ {
+ public:
+ template <typename T>
+ ptokenizer(T &&strm) // NOLINT(misc-forwarding-reference-overload, bugprone-forwarding-reference-overload)
+ : m_strm(std::forward<T>(strm))
+ , m_cur_line("")
+ , m_px(m_cur_line.begin())
+ , m_unget(0)
+ , m_string('"')
+ , m_support_line_markers(true) // FIXME
+ {
+ // add a first entry to the stack
+ m_source_location.emplace_back(plib::source_location("Unknown", 0));
+ }
+
+ COPYASSIGNMOVE(ptokenizer, delete)
+
+ virtual ~ptokenizer() = default;
+
+ enum token_type
+ {
+ IDENTIFIER,
+ NUMBER,
+ TOKEN,
+ STRING,
+ COMMENT,
+ LINEMARKER,
+ UNKNOWN,
+ ENDOFFILE
+ };
+
+ struct token_id_t
+ {
+ public:
+
+ static constexpr std::size_t npos = static_cast<std::size_t>(-1);
+
+ token_id_t() : m_id(npos) {}
+ explicit token_id_t(const std::size_t id) : m_id(id) {}
+ std::size_t id() const { return m_id; }
+ private:
+ std::size_t m_id;
+ };
+
+ struct token_t
+ {
+ explicit token_t(token_type type)
+ : m_type(type), m_id(), m_token("")
+ {
+ }
+ token_t(token_type type, const pstring &str)
+ : m_type(type), m_id(), m_token(str)
+ {
+ }
+ token_t(const token_id_t &id, const pstring &str)
+ : m_type(TOKEN), m_id(id), m_token(str)
+ {
+ }
+
+ bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
+ bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
+
+ bool is_type(const token_type type) const { return m_type == type; }
+
+ pstring str() const { return m_token; }
+
+ private:
+ token_type m_type;
+ token_id_t m_id;
+ pstring m_token;
+ };
+
+ pstring currentline_str();
+
+ /* tokenizer stuff follows ... */
+
+ token_t get_token();
+ pstring get_string();
+ pstring get_identifier();
+ pstring get_identifier_or_number();
+ double get_number_double();
+ long get_number_long();
+
+ void require_token(const token_id_t &token_num);
+ void require_token(const token_t &tok, const token_id_t &token_num);
+
+ token_id_t register_token(const pstring &token)
+ {
+ token_id_t ret(m_tokens.size());
+ m_tokens.emplace(token, ret);
+ return ret;
+ }
+
+ ptokenizer & identifier_chars(const pstring &s) { m_identifier_chars = s; return *this; }
+ ptokenizer & number_chars(const pstring &st, const pstring & rem) { m_number_chars_start = st; m_number_chars = rem; return *this; }
+ ptokenizer & string_char(pstring::value_type c) { m_string = c; return *this; }
+ ptokenizer & whitespace(const pstring & s) { m_whitespace = s; return *this; }
+ ptokenizer & comment(const pstring &start, const pstring &end, const pstring &line)
+ {
+ m_tok_comment_start = register_token(start);
+ m_tok_comment_end = register_token(end);
+ m_tok_line_comment = register_token(line);
+ return *this;
+ }
+
+ token_t get_token_internal();
+ void error(const pstring &errs);
+
+ putf8_reader &stream() { return m_strm; }
+ protected:
+ virtual void verror(const pstring &msg) = 0;
+
+ private:
+ void skipeol();
+
+ pstring::value_type getc();
+ void ungetc(pstring::value_type c);
+
+ bool eof() { return m_strm.eof(); }
+
+ putf8_reader m_strm;
+
+ pstring m_cur_line;
+ pstring::const_iterator m_px;
+ pstring::value_type m_unget;
+
+ /* tokenizer stuff follows ... */
+
+ pstring m_identifier_chars;
+ pstring m_number_chars;
+ pstring m_number_chars_start;
+ std::unordered_map<pstring, token_id_t> m_tokens;
+ pstring m_whitespace;
+ pstring::value_type m_string;
+
+ token_id_t m_tok_comment_start;
+ token_id_t m_tok_comment_end;
+ token_id_t m_tok_line_comment;
+
+ /* source locations, vector used as stack because we need to loop through stack */
+ bool m_support_line_markers;
+ std::vector<plib::source_location> m_source_location;
+ };
+
+} // namespace plib
+
+#endif /* PTOKENIZER_H_ */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index f6eed734a3e..457e3c62ca1 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -19,7 +19,7 @@ namespace plib
static constexpr const char PATH_SEP = '/';
#endif
- pstring basename(pstring filename)
+ pstring basename(const pstring &filename)
{
auto p=find_last_of(filename, pstring(1, PATH_SEP));
if (p == pstring::npos)
@@ -28,7 +28,7 @@ namespace plib
return filename.substr(p+1);
}
- pstring path(pstring filename)
+ pstring path(const pstring &filename)
{
auto p=find_last_of(filename, pstring(1, PATH_SEP));
if (p == pstring::npos)
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 9b1d8ec7f84..9a21a223ba9 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -8,9 +8,9 @@
#ifndef PUTIL_H_
#define PUTIL_H_
+#include "palloc.h"
#include "pexception.h"
#include "pstring.h"
-#include "palloc.h"
#include <algorithm>
#include <initializer_list>
@@ -33,7 +33,7 @@ namespace plib
*
* 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 dynamic use cases.
+ * parsing of files. This class is a replacement for dynamic use cases.
*
*/
struct source_location
@@ -43,11 +43,11 @@ namespace plib
{ }
source_location(pstring file, unsigned line) noexcept
- : m_file(file), m_func("unknown"), m_line(line), m_col(0)
+ : 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(file), m_func(func), m_line(line), m_col(0)
+ : m_file(std::move(file)), m_func(func), m_line(line), m_col(0)
{ }
unsigned line() const noexcept { return m_line; }
@@ -55,7 +55,7 @@ namespace plib
pstring file_name() const noexcept { return m_file; }
pstring function_name() const noexcept { return m_func; }
- source_location &operator ++()
+ source_location &operator ++() noexcept
{
++m_line;
return *this;
@@ -81,8 +81,7 @@ namespace plib
using stream_ptr = plib::unique_ptr<std::istream>;
- psource_t()
- {}
+ psource_t() noexcept = default;
COPYASSIGNMOVE(psource_t, delete)
@@ -104,11 +103,11 @@ namespace plib
{
public:
psource_str_t(pstring name, pstring str)
- : m_name(name), m_str(str)
+ : m_name(std::move(name)), m_str(std::move(str))
{}
COPYASSIGNMOVE(psource_str_t, delete)
- virtual ~psource_str_t() noexcept = default;
+ ~psource_str_t() noexcept override = default;
typename TS::stream_ptr stream(const pstring &name) override
{
@@ -133,8 +132,7 @@ namespace plib
using source_type = plib::unique_ptr<TS>;
using list_t = std::vector<source_type>;
- psource_collection_t()
- {}
+ psource_collection_t() noexcept = default;
COPYASSIGNMOVE(psource_collection_t, delete)
virtual ~psource_collection_t() noexcept = default;
@@ -161,7 +159,7 @@ namespace plib
}
template <typename S, typename F>
- bool for_all(pstring name, F lambda)
+ bool for_all(F lambda)
{
for (auto &s : m_collection)
{
@@ -181,8 +179,8 @@ namespace plib
namespace util
{
- pstring basename(pstring filename);
- pstring path(pstring filename);
+ pstring basename(const pstring &filename);
+ pstring path(const pstring &filename);
pstring buildpath(std::initializer_list<pstring> list );
pstring environment(const pstring &var, const pstring &default_val);
} // namespace util
@@ -365,7 +363,7 @@ namespace plib
return static_cast<T>(ret);
}
- template<typename R, bool CLOCALE, typename T>
+ template<typename R, typename T>
R pstonum_ne(const T &str, bool &err, std::locale loc = std::locale::classic()) noexcept
{
try
@@ -380,6 +378,19 @@ namespace plib
}
}
+ template<typename R, typename T>
+ R pstonum_ne_def(const T &str, R def, std::locale loc = std::locale::classic()) noexcept
+ {
+ try
+ {
+ return pstonum<R>(str, loc);
+ }
+ catch (...)
+ {
+ return def;
+ }
+ }
+
//============================================================
// penum - strongly typed enumeration
//============================================================
@@ -402,9 +413,9 @@ namespace plib
int f = from_string_int(strings(), s); \
if (f>=0) { m_v = static_cast<E>(f); return true; } else { return false; } \
} \
- operator E() const {return m_v;} \
- bool operator==(const ename &rhs) const {return m_v == rhs.m_v;} \
- bool operator==(const E &rhs) const {return m_v == rhs;} \
+ operator E() const noexcept {return m_v;} \
+ bool operator==(const ename &rhs) const noexcept {return m_v == rhs.m_v;} \
+ bool operator==(const E &rhs) const noexcept {return m_v == rhs;} \
std::string name() const { \
return nthstr(static_cast<int>(m_v), strings()); \
} \
diff --git a/src/lib/netlist/plib/vector_ops.h b/src/lib/netlist/plib/vector_ops.h
index bdeb24ae502..51c592968f5 100644
--- a/src/lib/netlist/plib/vector_ops.h
+++ b/src/lib/netlist/plib/vector_ops.h
@@ -27,7 +27,7 @@
namespace plib
{
template<typename VT, typename T>
- void vec_set_scalar(const std::size_t n, VT &v, T && scalar)
+ void vec_set_scalar(const std::size_t n, VT &v, T && scalar) noexcept
{
const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
for ( std::size_t i = 0; i < n; i++ )
@@ -35,14 +35,14 @@ namespace plib
}
template<typename VT, typename VS>
- void vec_set(const std::size_t n, VT &v, const VS & source)
+ void vec_set(const std::size_t n, VT &v, const VS & source) noexcept
{
for ( std::size_t i = 0; i < n; i++ )
v[i] = source[i];
}
template<typename T, typename V1, typename V2>
- T vec_mult(const std::size_t n, const V1 & v1, const V2 & v2 )
+ T vec_mult(const std::size_t n, const V1 & v1, const V2 & v2 ) noexcept
{
using b8 = std::array<T, 8>;
PALIGNAS_VECTOROPT() b8 value = {0};
@@ -54,7 +54,7 @@ namespace plib
}
template<typename T, typename VT>
- T vec_mult2(const std::size_t n, const VT &v)
+ T vec_mult2(const std::size_t n, const VT &v) noexcept
{
using b8 = std::array<T, 8>;
PALIGNAS_VECTOROPT() b8 value = {0};
@@ -66,7 +66,7 @@ namespace plib
}
template<typename T, typename VT>
- T vec_sum(const std::size_t n, const VT &v)
+ T vec_sum(const std::size_t n, const VT &v) noexcept
{
if (n<8)
{
@@ -88,7 +88,7 @@ namespace plib
}
template<typename VV, typename T, typename VR>
- void vec_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
+ void vec_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar) noexcept
{
const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
for ( std::size_t i = 0; i < n; i++ )
@@ -96,7 +96,7 @@ namespace plib
}
template<typename VR, typename VV, typename T>
- void vec_add_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar)
+ void vec_add_mult_scalar(const std::size_t n, VR & result, const VV & v, T && scalar) noexcept
{
const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
for ( std::size_t i = 0; i < n; i++ )
@@ -104,28 +104,28 @@ namespace plib
}
template<typename T>
- void vec_add_mult_scalar_p(const std::size_t n, T * result, const T * v, T scalar)
+ void vec_add_mult_scalar_p(const std::size_t n, T * result, const T * v, T scalar) noexcept
{
for ( std::size_t i = 0; i < n; i++ )
result[i] += scalar * v[i];
}
template<typename R, typename V>
- void vec_add_ip(const std::size_t n, R & result, const V & v)
+ void vec_add_ip(const std::size_t n, R & result, const V & v) noexcept
{
for ( std::size_t i = 0; i < n; i++ )
result[i] += v[i];
}
template<typename VR, typename V1, typename V2>
- void vec_sub(const std::size_t n, VR & result, const V1 &v1, const V2 & v2)
+ void vec_sub(const std::size_t n, VR & result, const V1 &v1, const V2 & v2) noexcept
{
for ( std::size_t i = 0; i < n; i++ )
result[i] = v1[i] - v2[i];
}
template<typename V, typename T>
- void vec_scale(const std::size_t n, V & v, T &&scalar)
+ void vec_scale(const std::size_t n, V & v, T &&scalar) noexcept
{
const typename std::remove_reference<decltype(v[0])>::type s(std::forward<T>(scalar));
for ( std::size_t i = 0; i < n; i++ )
@@ -133,7 +133,7 @@ namespace plib
}
template<typename T, typename V>
- T vec_maxabs(const std::size_t n, const V & v)
+ T vec_maxabs(const std::size_t n, const V & v) noexcept
{
T ret = 0.0;
for ( std::size_t i = 0; i < n; i++ )
diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h
index 16e13cbc4ab..761d9db78d2 100644
--- a/src/lib/netlist/solver/nld_ms_direct.h
+++ b/src/lib/netlist/solver/nld_ms_direct.h
@@ -38,15 +38,18 @@ namespace devices
unsigned vsolve_non_dynamic(const bool newton_raphson) override;
unsigned solve_non_dynamic(const bool newton_raphson);
- constexpr std::size_t size() const { return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; }
+ constexpr std::size_t size() const noexcept { return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; }
void LE_solve();
template <typename T>
void LE_back_subst(T & x);
- FT &A(std::size_t r, std::size_t c) { return m_A[r * m_pitch + c]; }
- FT &RHS(std::size_t r) { return m_A[r * m_pitch + size()]; }
+ const FT &A(std::size_t r, std::size_t c) const noexcept { return m_A[r][c]; }
+ FT &A(std::size_t r, std::size_t c) noexcept { return m_A[r][c]; }
+
+ const FT &RHS(std::size_t r) const noexcept { return m_A[r][size()]; }
+ FT &RHS(std::size_t r) noexcept { return m_A[r][size()]; }
plib::parray<FT, SIZE> m_new_V;
private:
@@ -55,8 +58,7 @@ namespace devices
const std::size_t m_dim;
const std::size_t m_pitch;
- plib::parray<FT, SIZE * int(m_pitch_ABS)> m_A;
-
+ plib::parray2D<FT, SIZE, m_pitch_ABS> m_A;
};
// ----------------------------------------------------------------------------------------
@@ -95,10 +97,10 @@ namespace devices
const auto &nzrd = m_terms[i]->m_nzrd;
const auto &nzbd = m_terms[i]->m_nzbd;
- for (const std::size_t j : nzbd)
+ for (auto j : nzbd)
{
const FT f1 = -f * A(j, i);
- for (const std::size_t k : nzrd)
+ for (auto k : nzrd)
A(j, k) += A(i, k) * f1;
//RHS(j) += RHS(i) * f1;
}
@@ -213,7 +215,7 @@ namespace devices
, m_new_V(size)
, m_dim(size)
, m_pitch(m_pitch_ABS ? m_pitch_ABS : (((m_dim + 1) + 7) / 8) * 8)
- , m_A(size * m_pitch)
+ , m_A(size, m_pitch)
{
}
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index ad2432647ec..360a9fc5dc9 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -281,7 +281,7 @@ namespace devices
break;
#endif
#if 1
- case 86:
+ case 87:
ms = create_solver<double,86>(86, sname);
break;
#endif
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 92142b60904..b29bf79d693 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -1,7 +1,7 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
/*
- * nl_convert.c
+ * nl_convert.cpp
*
*/
@@ -338,7 +338,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
pstring model;
pstring pins ="CBE";
bool err(false);
- auto nval = plib::pstonum_ne<long, true>(tt[4], err);
+ auto nval = plib::pstonum_ne<long>(tt[4], err);
plib::unused_var(nval);
if ((!err || plib::startsWith(tt[4], "N")) && tt.size() > 5)
diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h
index 3b30dc6094e..501a2d19e82 100644
--- a/src/lib/netlist/tools/nl_convert.h
+++ b/src/lib/netlist/tools/nl_convert.h
@@ -11,8 +11,8 @@
#define NL_CONVERT_H_
#include "plib/plists.h"
-#include "plib/pparser.h"
#include "plib/pstring.h"
+#include "plib/ptokenizer.h"
#include "plib/ptypes.h"
#include <memory>