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.h127
1 files changed, 127 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..1e21e72a5b0
--- /dev/null
+++ b/src/lib/netlist/plib/ppreprocessor.h
@@ -0,0 +1,127 @@
+// license:BSD-3-Clause
+// copyright-holders:Couriersud
+
+#ifndef PPREPROCESSOR_H_
+#define PPREPROCESSOR_H_
+
+///
+/// \file ppreprocessor.h
+///
+
+#include "pstream.h"
+#include "pstring.h"
+
+#include "psource.h"
+#include "putil.h"
+
+#include <istream>
+#include <unordered_map>
+#include <vector>
+
+namespace plib {
+
+ class ppreprocessor
+ {
+ 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)
+ {}
+ explicit 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);
+
+ PCOPYASSIGNMOVE(ppreprocessor, delete)
+
+ ~ppreprocessor() = default;
+
+ /// \brief process stream
+ ///
+ /// \param filename a filename or identifier identifying the stream.
+ ///
+ /// FIXME: this is sub-optimal. Refactor input_context into `pinput`_context
+ /// and pass this to `ppreprocessor`.
+ ///
+ template <typename T>
+ pstring process(T &&istrm, const pstring &filename)
+ {
+ m_outbuf.clear();
+ m_stack.emplace_back(input_context(istrm.release_stream(),plib::util::path(filename), filename));
+ process_stack();
+ return m_outbuf;
+ }
+
+ [[noreturn]] void error(const pstring &err) noexcept(false);
+
+ 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);
+ static bool is_valid_token(const pstring &str);
+
+ std::pair<pstring,bool> process_line(const pstring &line_in);
+ pstring process_comments(const pstring &line);
+
+ defines_map_type m_defines;
+ psource_collection_t &m_sources;
+ string_list m_expr_sep;
+
+ 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
+ {
+ 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 m_outbuf;
+ state_e m_state;
+ pstring m_line;
+ bool m_comment;
+ bool m_debug_out;
+
+ };
+
+} // namespace plib
+
+#endif // PPREPROCESSOR_H_