From 45713f390cefd502a8f0d21f6f844c54ddb9cb1a Mon Sep 17 00:00:00 2001 From: couriersud Date: Tue, 28 Jul 2020 20:41:48 +0200 Subject: [PATCH] netlist: fix a bug in preprocessor if and elif parsing. --- src/lib/netlist/plib/ppreprocessor.cpp | 76 ++++++++++++++++++++------ src/lib/netlist/plib/ppreprocessor.h | 4 +- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/src/lib/netlist/plib/ppreprocessor.cpp b/src/lib/netlist/plib/ppreprocessor.cpp index 05cdb648f34..d183485789f 100644 --- a/src/lib/netlist/plib/ppreprocessor.cpp +++ b/src/lib/netlist/plib/ppreprocessor.cpp @@ -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(tok); + try + { + val = plib::pstonum(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 t(this, tokenize(lt.substr(3), m_expr_sep, true, true)); - auto val = narrow_cast(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 t(this, tokenize(lt.substr(3), m_expr_sep, true, true)); + auto val = narrow_cast(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 t(this, tokenize(lt.substr(5), m_expr_sep, true, true)); - auto val = narrow_cast(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 t(this, tokenize(lt.substr(5), m_expr_sep, true, true)); + auto val = narrow_cast(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--; } diff --git a/src/lib/netlist/plib/ppreprocessor.h b/src/lib/netlist/plib/ppreprocessor.h index 467db358264..9758da6c8ac 100644 --- a/src/lib/netlist/plib/ppreprocessor.h +++ b/src/lib/netlist/plib/ppreprocessor.h @@ -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