1 // -*- C++ -*-
2 //*************************************************************************
3 //
4 // Copyright 2000-2021 by Wilson Snyder.  This program is free software;
5 // you can redistribute it and/or modify it under the terms of either the GNU
6 // Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 //*************************************************************************
14 /// \file
15 /// \brief Verilog::Preproc: Preprocess verilog code
16 ///
17 /// Authors: Wilson Snyder
18 ///
19 /// Code available from: https://www.veripool.org/verilog-perl
20 ///
21 //*************************************************************************
22 
23 #ifndef _VPREPROC_H_
24 #define _VPREPROC_H_ 1
25 
26 #include <string>
27 #include <map>
28 #include <iostream>
29 using namespace std;
30 #include "VFileLine.h"
31 
32 /// Generic opaque pointer to VPreProcImp implementation class.
33 struct VPreProcOpaque {
~VPreProcOpaqueVPreProcOpaque34     virtual ~VPreProcOpaque() {}
35 };
36 class VDefine;
37 
38 //**********************************************************************
39 // VPreProc
40 /// Verilog Preprocessor.
41 ////
42 /// This defines a preprocessor.  Functions are virtual so users can override them.
43 /// After creating, call openFile(), then getline() in a loop.  The class will to the rest...
44 
45 class VPreProc {
46 public:
47     VPreProc();
48     void configure(VFileLine* filelinep);
49     virtual ~VPreProc();
50 
51     // STATE
52 private:
53     int		m_keepComments;
54     int		m_keepWhitespace;
55     bool	m_lineDirectives;
56     bool	m_pedantic;
57     bool	m_synthesis;
58 
59 public:
60     // CONSTANTS
61     enum MiscConsts {
62  	DEFINE_RECURSION_LEVEL_MAX = 1000,	// How many `def substitutions before an error
63  	INCLUDE_DEPTH_MAX = 500,		// How many `includes deep before an error
64 	STREAM_DEPTH_LEVEL_MAX = 2000,		// How many streams deep (sometimes `def deep) before an error
65 	//					// Set more than DEFINE_RECURSION_LEVEL_MAX or INCLUDE_DEPTH_MAX
66  	NEWLINES_VS_TICKLINE = 20		// Use `line in place of this many newlines
67     };
68 
69     // ACCESSORS
70     /// Insert given file into this point in input stream
71     void openFile(string filename, VFileLine* filelinep=NULL);
72     void debug(int level);	///< Set debugging level
73     string getall(size_t approx_chunk);	///< Return all lines, or at least approx_chunk bytes. (Null if done.)
74     string getline();		///< Return next line/lines. (Null if done.)
75     bool isEof();		///< Return true on EOF.
76     void insertUnreadback(string text);
77 
78     VFileLine* fileline();	///< File/Line number for last getline call
79 
80     // The default behavior is to pass all unknown `defines right through.
81     // This lets the user determine how to report the errors.  It also nicely
82     // allows `celldefine and such to remain in the output stream.
83 
84     // CONTROL METHODS
85     // These options control how the parsing proceeds
keepComments()86     int  keepComments() { return m_keepComments; }
keepComments(int flag)87     void keepComments(int flag) { m_keepComments=flag; }	// Return comments, 0=no, 1=yes, 2=callback
keepWhitespace()88     int  keepWhitespace() { return m_keepWhitespace; }
keepWhitespace(int flag)89     void keepWhitespace(int flag) { m_keepWhitespace=flag; }	// Return extra whitespace
lineDirectives()90     bool lineDirectives() { return m_lineDirectives; }
lineDirectives(bool flag)91     void lineDirectives(bool flag) { m_lineDirectives=flag; }	// Insert `line directives
pedantic()92     bool pedantic() { return m_pedantic; }
pedantic(bool flag)93     void pedantic(bool flag) { m_pedantic=flag; }	// Obey standard; Don't substitute `error
synthesis()94     bool synthesis() { return m_synthesis; }
synthesis(bool flag)95     void synthesis(bool flag) { m_synthesis=flag; }	// Ignore translate off
96 
97     // CALLBACK METHODS
98     // This probably will want to be overridden for given child users of this class.
99     virtual void comment(string cmt) = 0;		///< Comment detected (if keepComments==2)
100     virtual void include(string filename) = 0;	///< Request a include file be processed
101     virtual void define(string name, string value, string params) = 0; ///< `define without any parameters
102     virtual void undef(string name) = 0;		///< Remove a definition
103     virtual void undefineall() = 0;			///< Remove all non-command-line definitions
104     virtual bool defExists(string name) = 0;	///< Return true if define exists
105     virtual string defParams(string name) = 0;	///< Return parameter list if define exists
106     virtual string defValue(string name) = 0;	///< Return value of given define (should exist)
107     virtual string defSubstitute(string substitute) = 0;	///< Return value to substitute for given post-parameter value
108 
109     // UTILITIES
error(string msg)110     void error(string msg) { fileline()->error(msg); }	///< Report a error
fatal(string msg)111     void fatal(string msg) { fileline()->fatal(msg); }	///< Report a fatal error
112 
113 private:
114     VPreProcOpaque*	m_opaquep;	///< Pointer to parser's implementation data.
115 };
116 
117 #endif // Guard
118