netlist: fix a bug in preprocessor if and elif parsing.

This commit is contained in:
couriersud 2020-07-28 20:41:48 +02:00
parent af3118d0f1
commit 45713f390c
2 changed files with 62 additions and 18 deletions

View File

@ -17,6 +17,8 @@ namespace plib {
: std::istream(new readbuffer(this))
, m_sources(sources)
, m_if_flag(0)
, m_if_seen(0)
, m_elif(0)
, m_if_level(0)
, m_pos(0)
, m_state(PROCESS)
@ -197,7 +199,14 @@ namespace plib {
CHECKTOK2(||, 15)
else
{
val = plib::pstonum<decltype(val)>(tok);
try
{
val = plib::pstonum<decltype(val)>(tok);
}
catch (pexception &e)
{
sexpr.error(e.text());
}
has_val = true;
sexpr.next();
}
@ -460,45 +469,78 @@ namespace plib {
if (lti[0] == "#if")
{
m_if_level++;
lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true));
auto val = narrow_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);
m_if_seen |= (1 << m_if_level);
if (m_if_flag == 0)
{
lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true));
auto val = narrow_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
m_elif |= (1 << m_if_level);
}
}
else if (lti[0] == "#ifdef")
{
m_if_level++;
m_if_seen |= (1 << m_if_level);
if (get_define(lti[1]) == nullptr)
m_if_flag |= (1 << m_if_level);
else
m_elif |= (1 << m_if_level);
}
else if (lti[0] == "#ifndef")
{
m_if_level++;
m_if_seen |= (1 << m_if_level);
if (get_define(lti[1]) != nullptr)
m_if_flag |= (1 << m_if_level);
else
m_elif |= (1 << m_if_level);
}
else if (lti[0] == "#else")
{
if (!(m_if_seen & (1 << m_if_level)))
error("#else without #if");
m_if_flag ^= (1 << m_if_level);
m_elif &= ~(1 << m_if_level);
}
else if (lti[0] == "#elif")
{
m_if_flag ^= (1 << m_if_level);
lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true));
auto val = narrow_cast<int>(prepro_expr(t, 255));
t.skip_ws();
if (!t.eod())
error("found unprocessed content at end of line");
if (val == 0)
if (!(m_if_seen & (1 << m_if_level)))
error("#elif without #if");
//if ((m_if_flag & (1 << m_if_level)) == 0)
// m_if_flag ^= (1 << m_if_level);
if (m_elif & (1 << m_if_level))
m_if_flag |= (1 << m_if_level);
else
m_if_flag &= ~(1 << m_if_level);
if (m_if_flag == 0)
{
//m_if_flag ^= (1 << m_if_level);
lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true));
auto val = narrow_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
m_elif |= ~(1 << m_if_level);
}
}
else if (lti[0] == "#endif")
{
if (!(m_if_seen & (1 << m_if_level)))
error("#else without #if");
m_if_seen &= ~(1 << m_if_level);
m_elif &= ~(1 << m_if_level);
m_if_flag &= ~(1 << m_if_level);
m_if_level--;
}

View File

@ -139,7 +139,9 @@ namespace plib {
psource_collection_t<> &m_sources;
string_list m_expr_sep;
std::uint_least64_t m_if_flag; // 31 if levels
std::uint_least64_t m_if_flag; // 63 if levels
std::uint_least64_t m_if_seen; // 63 if levels
std::uint_least64_t m_elif; // 63 if levels - for #elif
int m_if_level;
struct input_context