mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
Improve type safety on string->numeric conversions. (nw)
Also fixed an issue with 7497. ./nltool -t 5 -f src/mame/machine/nl_tp1983.cpp -v now runs again.
This commit is contained in:
parent
f8d5b95e37
commit
4213a396d8
@ -74,7 +74,7 @@ namespace netlist
|
|||||||
ENTRYX(7485, TTL_7485, "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN")
|
ENTRYX(7485, TTL_7485, "+A0,+A1,+A2,+A3,+B0,+B1,+B2,+B3,+LTIN,+EQIN,+GTIN")
|
||||||
ENTRYX(7490, TTL_7490, "+A,+B,+R1,+R2,+R91,+R92")
|
ENTRYX(7490, TTL_7490, "+A,+B,+R1,+R2,+R91,+R92")
|
||||||
ENTRYX(7493, TTL_7493, "+CLKA,+CLKB,+R1,+R2")
|
ENTRYX(7493, TTL_7493, "+CLKA,+CLKB,+R1,+R2")
|
||||||
ENTRYX(7497, TTL_7497, "+CLK,+STRB,+EN,+UNITY,+CLR,+B0,+B1,+B2,+B3,+B4,+B5")
|
ENTRYX(7497, TTL_7497, "+CLK,+STRBQ,+ENQ,+UNITYQ,+CLR,+B0,+B1,+B2,+B3,+B4,+B5")
|
||||||
ENTRYX(74107, TTL_74107, "+CLK,+J,+K,+CLRQ")
|
ENTRYX(74107, TTL_74107, "+CLK,+J,+K,+CLRQ")
|
||||||
ENTRYX(74107A, TTL_74107A, "+CLK,+J,+K,+CLRQ")
|
ENTRYX(74107A, TTL_74107A, "+CLK,+J,+K,+CLRQ")
|
||||||
ENTRYX(74123, TTL_74123, "")
|
ENTRYX(74123, TTL_74123, "")
|
||||||
|
@ -136,7 +136,9 @@ namespace netlist
|
|||||||
unsigned long total = 0;
|
unsigned long total = 0;
|
||||||
for (unsigned i=0; i<m_size; i++)
|
for (unsigned i=0; i<m_size; i++)
|
||||||
{
|
{
|
||||||
pati[i] = static_cast<unsigned long>(plib::pstol(pat[i]));
|
// FIXME: use pstonum_ne
|
||||||
|
//pati[i] = plib::pstonum<decltype(pati[i])>(pat[i]);
|
||||||
|
pati[i] = plib::pstonum<unsigned long>(pat[i]);
|
||||||
total += pati[i];
|
total += pati[i];
|
||||||
}
|
}
|
||||||
netlist_time ttotal = netlist_time::zero();
|
netlist_time ttotal = netlist_time::zero();
|
||||||
|
@ -407,7 +407,8 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
|
|||||||
val.set(j);
|
val.set(j);
|
||||||
else
|
else
|
||||||
nl_assert_always(outs == "0", "Unknown value (not 0 or 1");
|
nl_assert_always(outs == "0", "Unknown value (not 0 or 1");
|
||||||
netlist_time t = netlist_time::from_nsec(static_cast<unsigned long>(plib::pstol(plib::trim(times[j]))));
|
// FIXME: error handling
|
||||||
|
netlist_time t = netlist_time::from_nsec(plib::pstonum<unsigned long>(plib::trim(times[j])));
|
||||||
uint_least8_t k=0;
|
uint_least8_t k=0;
|
||||||
while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t)
|
while (m_timing_nt[k] != netlist_time::zero() && m_timing_nt[k] != t)
|
||||||
k++;
|
k++;
|
||||||
|
@ -343,8 +343,8 @@ void netlist_t::start()
|
|||||||
auto p = setup().m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
|
auto p = setup().m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
|
||||||
if (p != setup().m_param_values.end())
|
if (p != setup().m_param_values.end())
|
||||||
{
|
{
|
||||||
//FIXME: turn this into a proper function
|
//FIXME: check for errors ...
|
||||||
auto v = plib::pstod(p->second);;
|
double v = plib::pstonum<double>(p->second);;
|
||||||
if (std::abs(v - std::floor(v)) > 1e-6 )
|
if (std::abs(v - std::floor(v)) > 1e-6 )
|
||||||
log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
|
log().fatal(MF_1_HND_VAL_NOT_SUPPORTED, p->second);
|
||||||
d->set_hint_deactivate(v == 0.0);
|
d->set_hint_deactivate(v == 0.0);
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
* linear memory pool. This is based of the assumption that
|
* linear memory pool. This is based of the assumption that
|
||||||
* due to enhanced locality there will be less cache misses.
|
* due to enhanced locality there will be less cache misses.
|
||||||
* Your mileage may vary.
|
* Your mileage may vary.
|
||||||
* This will cause crashes on OSX and thus is ignored on OSX.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define USE_MEMPOOL (0)
|
#define USE_MEMPOOL (0)
|
||||||
|
@ -403,7 +403,6 @@ nl_double parser_t::eval_param(const token_t tok)
|
|||||||
int i;
|
int i;
|
||||||
int f=0;
|
int f=0;
|
||||||
nl_double ret;
|
nl_double ret;
|
||||||
pstring val;
|
|
||||||
|
|
||||||
for (i=1; i<6;i++)
|
for (i=1; i<6;i++)
|
||||||
if (tok.str() == macs[i])
|
if (tok.str() == macs[i])
|
||||||
@ -416,9 +415,10 @@ nl_double parser_t::eval_param(const token_t tok)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = tok.str();
|
bool err;
|
||||||
if (!plib::pstod_ne(val, ret))
|
ret = plib::pstonum_ne<nl_double>(tok.str(), err);
|
||||||
error(plib::pfmt("Parameter value <{1}> not double \n")(val));
|
if (err)
|
||||||
|
error(plib::pfmt("Parameter value <{1}> not double \n")(tok.str()));
|
||||||
}
|
}
|
||||||
return ret * facs[f];
|
return ret * facs[f];
|
||||||
|
|
||||||
|
@ -159,8 +159,9 @@ double setup_t::get_initial_param_val(const pstring &name, const double def)
|
|||||||
auto i = m_param_values.find(name);
|
auto i = m_param_values.find(name);
|
||||||
if (i != m_param_values.end())
|
if (i != m_param_values.end())
|
||||||
{
|
{
|
||||||
double vald = 0;
|
bool err = false;
|
||||||
if (!plib::pstod_ne(i->second, vald))
|
double vald = plib::pstonum_ne<double>(i->second, err);
|
||||||
|
if (err)
|
||||||
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
||||||
return vald;
|
return vald;
|
||||||
}
|
}
|
||||||
@ -173,8 +174,9 @@ int setup_t::get_initial_param_val(const pstring &name, const int def)
|
|||||||
auto i = m_param_values.find(name);
|
auto i = m_param_values.find(name);
|
||||||
if (i != m_param_values.end())
|
if (i != m_param_values.end())
|
||||||
{
|
{
|
||||||
long vald = 0;
|
bool err;
|
||||||
if (!plib::pstod_ne(i->second, vald))
|
double vald = plib::pstonum_ne<double>(i->second, err);
|
||||||
|
if (err)
|
||||||
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
||||||
if (vald - std::floor(vald) != 0.0)
|
if (vald - std::floor(vald) != 0.0)
|
||||||
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
log().fatal(MF_2_INVALID_NUMBER_CONVERSION_1_2, name, i->second);
|
||||||
@ -872,7 +874,8 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
|
|||||||
}
|
}
|
||||||
if (factor != NL_FCONST(1.0))
|
if (factor != NL_FCONST(1.0))
|
||||||
tmp = plib::left(tmp, tmp.size() - 1);
|
tmp = plib::left(tmp, tmp.size() - 1);
|
||||||
return plib::pstod(tmp) * factor;
|
// FIXME: check for errors
|
||||||
|
return plib::pstonum<nl_double>(tmp) * factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
class logic_family_std_proxy_t : public logic_family_desc_t
|
class logic_family_std_proxy_t : public logic_family_desc_t
|
||||||
|
@ -69,7 +69,9 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
|
|||||||
if (rc.m_cmd != PUSH_INPUT)
|
if (rc.m_cmd != PUSH_INPUT)
|
||||||
{
|
{
|
||||||
rc.m_cmd = PUSH_CONST;
|
rc.m_cmd = PUSH_CONST;
|
||||||
if (!plib::pstod_ne(cmd, rc.m_param))
|
bool err;
|
||||||
|
rc.m_param = plib::pstonum_ne<decltype(rc.m_param)>(cmd, err);
|
||||||
|
if (err)
|
||||||
throw plib::pexception(plib::pfmt("nld_function: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
|
throw plib::pexception(plib::pfmt("nld_function: unknown/misformatted token <{1}> in <{2}>")(cmd)(expr));
|
||||||
stk += 1;
|
stk += 1;
|
||||||
}
|
}
|
||||||
|
@ -46,49 +46,13 @@ namespace plib {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int option_str_limit::parse(const pstring &argument)
|
|
||||||
{
|
|
||||||
if (plib::container::contains(m_limit, argument))
|
|
||||||
{
|
|
||||||
m_val = argument;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int option_bool::parse(const pstring &argument)
|
int option_bool::parse(const pstring &argument)
|
||||||
{
|
{
|
||||||
|
unused_var(argument);
|
||||||
m_val = true;
|
m_val = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int option_double::parse(const pstring &argument)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_val = plib::pstod(argument);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int option_long::parse(const pstring &argument)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_val = plib::pstol(argument);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int option_vec::parse(const pstring &argument)
|
int option_vec::parse(const pstring &argument)
|
||||||
{
|
{
|
||||||
bool err = false;
|
bool err = false;
|
||||||
@ -233,7 +197,7 @@ namespace plib {
|
|||||||
if (opt->has_argument())
|
if (opt->has_argument())
|
||||||
{
|
{
|
||||||
line += "=";
|
line += "=";
|
||||||
option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
|
option_str_limit_base *ol = dynamic_cast<option_str_limit_base *>(opt);
|
||||||
if (ol)
|
if (ol)
|
||||||
{
|
{
|
||||||
for (auto &v : ol->limit())
|
for (auto &v : ol->limit())
|
||||||
|
@ -102,24 +102,52 @@ private:
|
|||||||
pstring m_val;
|
pstring m_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
class option_str_limit : public option
|
class option_str_limit_base : public option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help)
|
option_str_limit_base(options &parent, pstring ashort, pstring along, std::vector<pstring> &&limit, pstring help)
|
||||||
: option(parent, ashort, along, help, true), m_val(defval)
|
: option(parent, ashort, along, help, true)
|
||||||
, m_limit(plib::psplit(limit, ":"))
|
, m_limit(limit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const std::vector<pstring> &limit() const { return m_limit; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<pstring> m_limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class option_str_limit : public option_str_limit_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
option_str_limit(options &parent, pstring ashort, pstring along, const T &defval, std::vector<pstring> &&limit, pstring help)
|
||||||
|
: option_str_limit_base(parent, ashort, along, std::move(limit), help), m_val(defval)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pstring operator ()() { return m_val; }
|
T operator ()() { return m_val; }
|
||||||
const std::vector<pstring> &limit() { return m_limit; }
|
|
||||||
|
pstring as_string() const { return limit()[m_val]; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int parse(const pstring &argument) override;
|
virtual int parse(const pstring &argument) override
|
||||||
|
{
|
||||||
|
auto raw = plib::container::indexof(limit(), argument);
|
||||||
|
|
||||||
|
if (raw != plib::container::npos)
|
||||||
|
{
|
||||||
|
m_val = static_cast<T>(raw);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pstring m_val;
|
T m_val;
|
||||||
std::vector<pstring> m_limit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class option_bool : public option
|
class option_bool : public option
|
||||||
@ -138,36 +166,34 @@ private:
|
|||||||
bool m_val;
|
bool m_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
class option_double : public option
|
template <typename T>
|
||||||
|
class option_num : public option
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
option_double(options &parent, pstring ashort, pstring along, double defval, pstring help)
|
option_num(options &parent, pstring ashort, pstring along, T defval,
|
||||||
: option(parent, ashort, along, help, true), m_val(defval)
|
pstring help,
|
||||||
|
T minval = std::numeric_limits<T>::min(),
|
||||||
|
T maxval = std::numeric_limits<T>::max() )
|
||||||
|
: option(parent, ashort, along, help, true)
|
||||||
|
, m_val(defval)
|
||||||
|
, m_min(minval)
|
||||||
|
, m_max(maxval)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
double operator ()() { return m_val; }
|
T operator ()() { return m_val; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int parse(const pstring &argument) override;
|
virtual int parse(const pstring &argument) override
|
||||||
|
{
|
||||||
|
bool err;
|
||||||
|
m_val = pstonum_ne<T>(argument, err);
|
||||||
|
return (err ? 1 : (m_val < m_min || m_val > m_max));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_val;
|
T m_val;
|
||||||
};
|
T m_min;
|
||||||
|
T m_max;
|
||||||
class option_long : public option
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
option_long(options &parent, pstring ashort, pstring along, long defval, pstring help)
|
|
||||||
: option(parent, ashort, along, help, true), m_val(defval)
|
|
||||||
{}
|
|
||||||
|
|
||||||
long operator ()() { return m_val; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual int parse(const pstring &argument) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
long m_val;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class option_vec : public option
|
class option_vec : public option
|
||||||
@ -207,6 +233,17 @@ private:
|
|||||||
static pstring split_paragraphs(pstring text, unsigned width, unsigned indent,
|
static pstring split_paragraphs(pstring text, unsigned width, unsigned indent,
|
||||||
unsigned firstline_indent);
|
unsigned firstline_indent);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T *getopt_type()
|
||||||
|
{
|
||||||
|
for (auto & optbase : m_opts )
|
||||||
|
{
|
||||||
|
if (auto opt = dynamic_cast<T *>(optbase))
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
option *getopt_short(pstring arg);
|
option *getopt_short(pstring arg);
|
||||||
option *getopt_long(pstring arg);
|
option *getopt_long(pstring arg);
|
||||||
|
|
||||||
|
@ -122,6 +122,7 @@ pstring ptokenizer::get_identifier_or_number()
|
|||||||
return tok.str();
|
return tok.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: combine into template
|
||||||
double ptokenizer::get_number_double()
|
double ptokenizer::get_number_double()
|
||||||
{
|
{
|
||||||
token_t tok = get_token();
|
token_t tok = get_token();
|
||||||
@ -129,9 +130,9 @@ double ptokenizer::get_number_double()
|
|||||||
{
|
{
|
||||||
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
|
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
|
||||||
}
|
}
|
||||||
double ret = 0.0;
|
bool err;
|
||||||
|
double ret = plib::pstonum_ne<double>(tok.str(), err);
|
||||||
if (!plib::pstod_ne(tok.str(), ret))
|
if (err)
|
||||||
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
|
error(pfmt("Expected a number, got <{1}>")(tok.str()) );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -143,8 +144,9 @@ long ptokenizer::get_number_long()
|
|||||||
{
|
{
|
||||||
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
|
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
|
||||||
}
|
}
|
||||||
long ret = 0;
|
bool err;
|
||||||
if (!plib::pstol_ne(tok.str(), ret))
|
long ret = plib::pstonum_ne<long>(tok.str(), err);
|
||||||
|
if (err)
|
||||||
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
|
error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -326,7 +328,8 @@ double ppreprocessor::expr(const std::vector<pstring> &sexpr, std::size_t &start
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
tok=sexpr[start];
|
tok=sexpr[start];
|
||||||
val = plib::pstod(tok);
|
// FIXME: error handling
|
||||||
|
val = plib::pstonum<decltype(val)>(tok);
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
while (start < sexpr.size())
|
while (start < sexpr.size())
|
||||||
|
@ -9,8 +9,10 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <stdexcept>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <limits>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
@ -518,57 +520,72 @@ namespace plib
|
|||||||
return pwstring(std::to_wstring(v));
|
return pwstring(std::to_wstring(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PSTRING_USE_STD_STRING)
|
template <typename T, typename E = void>
|
||||||
inline double pstod(const std::string &str, std::size_t *e = nullptr)
|
struct pstonum_helper;
|
||||||
{
|
|
||||||
return std::stod(str, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline long pstol(const std::string &str, std::size_t *e = nullptr, int base = 10)
|
|
||||||
{
|
|
||||||
return std::stol(str, e, base);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
template<typename T>
|
|
||||||
double pstod(const T &str, std::size_t *e = nullptr)
|
|
||||||
{
|
|
||||||
return std::stod(str.cpp_string(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
long pstol(const T &str, std::size_t *e = nullptr, int base = 10)
|
struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
|
||||||
|
&& std::is_signed<T>::value>::type>
|
||||||
{
|
{
|
||||||
return std::stol(str.cpp_string(), e, base);
|
template <typename S>
|
||||||
|
long long operator()(const S &arg, std::size_t *idx)
|
||||||
|
{
|
||||||
|
return std::stoll(arg, idx);
|
||||||
}
|
}
|
||||||
#endif
|
};
|
||||||
|
|
||||||
template<typename T, typename R>
|
template<typename T>
|
||||||
bool pstol_ne(const T &str, R &ret)
|
struct pstonum_helper<T, typename std::enable_if<std::is_integral<T>::value
|
||||||
|
&& !std::is_signed<T>::value>::type>
|
||||||
|
{
|
||||||
|
template <typename S>
|
||||||
|
unsigned long long operator()(const S &arg, std::size_t *idx)
|
||||||
|
{
|
||||||
|
return std::stoull(arg, idx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct pstonum_helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
|
||||||
|
{
|
||||||
|
template <typename S>
|
||||||
|
long double operator()(const S &arg, std::size_t *idx)
|
||||||
|
{
|
||||||
|
return std::stold(arg, idx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename S>
|
||||||
|
T pstonum(const S &arg)
|
||||||
|
{
|
||||||
|
decltype(arg.c_str()) cstr = arg.c_str();
|
||||||
|
std::size_t idx(0);
|
||||||
|
auto ret = pstonum_helper<T>()(cstr, &idx);
|
||||||
|
if (ret >= std::numeric_limits<T>::lowest() && ret <= std::numeric_limits<T>::max())
|
||||||
|
//&& (ret == T(0) || std::abs(ret) >= std::numeric_limits<T>::min() ))
|
||||||
|
{
|
||||||
|
if (cstr[idx] != 0)
|
||||||
|
throw std::invalid_argument(std::string("Continuation after numeric value ends: ") + cstr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::out_of_range(std::string("Out of range: ") + cstr);
|
||||||
|
}
|
||||||
|
return static_cast<T>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R, typename T>
|
||||||
|
R pstonum_ne(const T &str, bool &err) noexcept
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::size_t e = 0;
|
err = false;
|
||||||
ret = pstol(str, &e);
|
return pstonum<R>(str);
|
||||||
return str.c_str()[e] == 0;
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
err = true;
|
||||||
}
|
return R(0);
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename R>
|
|
||||||
bool pstod_ne(const T &str, R &ret)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::size_t e = 0;
|
|
||||||
ret = pstod(str, &e);
|
|
||||||
return str.c_str()[e] == 0;
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,36 @@ namespace plib
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> psplit_r(const std::string &stri,
|
||||||
|
const std::string &token,
|
||||||
|
const std::size_t maxsplit)
|
||||||
|
{
|
||||||
|
std::string str(stri);
|
||||||
|
std::vector<std::string> result;
|
||||||
|
std::size_t splits = 0;
|
||||||
|
|
||||||
|
while(str.size())
|
||||||
|
{
|
||||||
|
std::size_t index = str.rfind(token);
|
||||||
|
bool found = index!=std::string::npos;
|
||||||
|
if (found)
|
||||||
|
splits++;
|
||||||
|
if ((splits <= maxsplit || maxsplit == 0) && found)
|
||||||
|
{
|
||||||
|
result.push_back(str.substr(index+token.size()));
|
||||||
|
str = str.substr(0, index);
|
||||||
|
if (str.size()==0)
|
||||||
|
result.push_back(str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.push_back(str);
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl)
|
std::vector<pstring> psplit(const pstring &str, const std::vector<pstring> &onstrl)
|
||||||
{
|
{
|
||||||
pstring col = "";
|
pstring col = "";
|
||||||
|
@ -16,6 +16,11 @@
|
|||||||
|
|
||||||
namespace plib
|
namespace plib
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Avoid unused variable warnings
|
||||||
|
template<typename... Ts>
|
||||||
|
inline void unused_var(Ts&&...) {}
|
||||||
|
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
const pstring buildpath(std::initializer_list<pstring> list );
|
const pstring buildpath(std::initializer_list<pstring> list );
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
tool_app_t() :
|
tool_app_t() :
|
||||||
plib::app(),
|
plib::app(),
|
||||||
opt_grp1(*this, "General options", "The following options apply to all commands."),
|
opt_grp1(*this, "General options", "The following options apply to all commands."),
|
||||||
opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static:header:docheader", "run|convert|listdevices|static|header"),
|
opt_cmd (*this, "c", "cmd", 0, std::vector<pstring>({"run","convert","listdevices","static","header","docheader"}), "run|convert|listdevices|static|header|docheader"),
|
||||||
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
|
opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
|
||||||
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
|
opt_defines(*this, "D", "define", "predefine value as macro, e.g. -Dname=value. If '=value' is omitted predefine it as 1. This option may be specified repeatedly."),
|
||||||
opt_rfolders(*this, "r", "rom", "where to look for data files"),
|
opt_rfolders(*this, "r", "rom", "where to look for data files"),
|
||||||
@ -40,7 +40,7 @@ public:
|
|||||||
opt_loadstate(*this,"", "loadstate", "", "load state from file and continue from there"),
|
opt_loadstate(*this,"", "loadstate", "", "load state from file and continue from there"),
|
||||||
opt_savestate(*this,"", "savestate", "", "save state to file at end of run"),
|
opt_savestate(*this,"", "savestate", "", "save state to file at end of run"),
|
||||||
opt_grp4(*this, "Options for convert command", "These options are only used by the convert command."),
|
opt_grp4(*this, "Options for convert command", "These options are only used by the convert command."),
|
||||||
opt_type(*this, "y", "type", "spice", "spice:eagle:rinf", "type of file to be converted: spice,eagle,rinf"),
|
opt_type(*this, "y", "type", 0, std::vector<pstring>({"spice","eagle","rinf"}), "type of file to be converted: spice,eagle,rinf"),
|
||||||
|
|
||||||
opt_ex1(*this, "nltool -c run -t 3.5 -f nl_examples/cdelay.c -n cap_delay",
|
opt_ex1(*this, "nltool -c run -t 3.5 -f nl_examples/cdelay.c -n cap_delay",
|
||||||
"Run netlist \"cap_delay\" from file nl_examples/cdelay.c for 3.5 seconds"),
|
"Run netlist \"cap_delay\" from file nl_examples/cdelay.c for 3.5 seconds"),
|
||||||
@ -49,7 +49,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
plib::option_group opt_grp1;
|
plib::option_group opt_grp1;
|
||||||
plib::option_str_limit opt_cmd;
|
plib::option_str_limit<unsigned> opt_cmd;
|
||||||
plib::option_str opt_file;
|
plib::option_str opt_file;
|
||||||
plib::option_vec opt_defines;
|
plib::option_vec opt_defines;
|
||||||
plib::option_vec opt_rfolders;
|
plib::option_vec opt_rfolders;
|
||||||
@ -60,13 +60,13 @@ public:
|
|||||||
plib::option_group opt_grp2;
|
plib::option_group opt_grp2;
|
||||||
plib::option_str opt_name;
|
plib::option_str opt_name;
|
||||||
plib::option_group opt_grp3;
|
plib::option_group opt_grp3;
|
||||||
plib::option_double opt_ttr;
|
plib::option_num<double> opt_ttr;
|
||||||
plib::option_vec opt_logs;
|
plib::option_vec opt_logs;
|
||||||
plib::option_str opt_inp;
|
plib::option_str opt_inp;
|
||||||
plib::option_str opt_loadstate;
|
plib::option_str opt_loadstate;
|
||||||
plib::option_str opt_savestate;
|
plib::option_str opt_savestate;
|
||||||
plib::option_group opt_grp4;
|
plib::option_group opt_grp4;
|
||||||
plib::option_str_limit opt_type;
|
plib::option_str_limit<unsigned> opt_type;
|
||||||
plib::option_example opt_ex1;
|
plib::option_example opt_ex1;
|
||||||
plib::option_example opt_ex2;
|
plib::option_example opt_ex2;
|
||||||
|
|
||||||
@ -706,7 +706,7 @@ int tool_app_t::execute()
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pstring cmd = opt_cmd();
|
pstring cmd = opt_cmd.as_string();
|
||||||
if (cmd == "listdevices")
|
if (cmd == "listdevices")
|
||||||
listdevices();
|
listdevices();
|
||||||
else if (cmd == "run")
|
else if (cmd == "run")
|
||||||
@ -734,19 +734,19 @@ int tool_app_t::execute()
|
|||||||
contents = ostrm.str();
|
contents = ostrm.str();
|
||||||
|
|
||||||
pstring result;
|
pstring result;
|
||||||
if (opt_type() == "spice")
|
if (opt_type.as_string() == "spice")
|
||||||
{
|
{
|
||||||
nl_convert_spice_t c;
|
nl_convert_spice_t c;
|
||||||
c.convert(contents);
|
c.convert(contents);
|
||||||
result = c.result();
|
result = c.result();
|
||||||
}
|
}
|
||||||
else if (opt_type() == "eagle")
|
else if (opt_type.as_string() == "eagle")
|
||||||
{
|
{
|
||||||
nl_convert_eagle_t c;
|
nl_convert_eagle_t c;
|
||||||
c.convert(contents);
|
c.convert(contents);
|
||||||
result = c.result();
|
result = c.result();
|
||||||
}
|
}
|
||||||
else if (opt_type() == "rinf")
|
else if (opt_type.as_string() == "rinf")
|
||||||
{
|
{
|
||||||
nl_convert_rinf_t c;
|
nl_convert_rinf_t c;
|
||||||
c.convert(contents);
|
c.convert(contents);
|
||||||
|
@ -24,8 +24,8 @@ public:
|
|||||||
{}
|
{}
|
||||||
plib::option_str opt_inp;
|
plib::option_str opt_inp;
|
||||||
plib::option_str opt_out;
|
plib::option_str opt_out;
|
||||||
plib::option_double opt_amp;
|
plib::option_num<double> opt_amp;
|
||||||
plib::option_long opt_rate;
|
plib::option_num<long> opt_rate;
|
||||||
plib::option_bool opt_verb;
|
plib::option_bool opt_verb;
|
||||||
plib::option_bool opt_quiet;
|
plib::option_bool opt_quiet;
|
||||||
plib::option_bool opt_version;
|
plib::option_bool opt_version;
|
||||||
|
@ -268,7 +268,7 @@ void NETLIB_NAME(solver)::post_start()
|
|||||||
// Override log statistics
|
// Override log statistics
|
||||||
pstring p = plib::util::environment("NL_STATS", "");
|
pstring p = plib::util::environment("NL_STATS", "");
|
||||||
if (p != "")
|
if (p != "")
|
||||||
m_params.m_log_stats = plib::pstol(p);
|
m_params.m_log_stats = plib::pstonum<decltype(m_params.m_log_stats)>(p);
|
||||||
else
|
else
|
||||||
m_params.m_log_stats = m_log_stats();
|
m_params.m_log_stats = m_log_stats();
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ double nl_convert_base_t::get_sp_val(const pstring &sin)
|
|||||||
++p;
|
++p;
|
||||||
pstring val = plib::left(sin, p);
|
pstring val = plib::left(sin, p);
|
||||||
pstring unit = sin.substr(p);
|
pstring unit = sin.substr(p);
|
||||||
double ret = get_sp_unit(unit) * plib::pstod(val);
|
double ret = get_sp_unit(unit) * plib::pstonum<double>(val);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,11 +304,12 @@ void nl_convert_spice_t::process_line(const pstring &line)
|
|||||||
/* check for fourth terminal ... should be numeric net
|
/* check for fourth terminal ... should be numeric net
|
||||||
* including "0" or start with "N" (ltspice)
|
* including "0" or start with "N" (ltspice)
|
||||||
*/
|
*/
|
||||||
long nval = 0;
|
|
||||||
pstring model;
|
pstring model;
|
||||||
pstring pins ="CBE";
|
pstring pins ="CBE";
|
||||||
|
bool err;
|
||||||
|
ATTR_UNUSED long nval = plib::pstonum_ne<long>(tt[4], err);
|
||||||
|
|
||||||
if ((!plib::pstol_ne(tt[4], nval) || plib::startsWith(tt[4], "N")) && tt.size() > 5)
|
if ((err || plib::startsWith(tt[4], "N")) && tt.size() > 5)
|
||||||
model = tt[5];
|
model = tt[5];
|
||||||
else
|
else
|
||||||
model = tt[4];
|
model = tt[4];
|
||||||
@ -492,7 +493,7 @@ void nl_convert_eagle_t::convert(const pstring &contents)
|
|||||||
else if (plib::ucase(sval) == "LOW")
|
else if (plib::ucase(sval) == "LOW")
|
||||||
add_device("TTL_INPUT", name, 0);
|
add_device("TTL_INPUT", name, 0);
|
||||||
else
|
else
|
||||||
add_device("ANALOG_INPUT", name, plib::pstod(sval));
|
add_device("ANALOG_INPUT", name, plib::pstonum<double>(sval));
|
||||||
add_pin_alias(name, "1", "Q");
|
add_pin_alias(name, "1", "Q");
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
|
Loading…
Reference in New Issue
Block a user