summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/ppreprocessor.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/ppreprocessor.h')
-rw-r--r--src/lib/netlist/plib/ppreprocessor.h173
1 files changed, 173 insertions, 0 deletions
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_ */