1 /*
2  * (C) Copyright 2001-2015 Diomidis Spinellis
3  *
4  * This file is part of CScout.
5  *
6  * CScout is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * CScout is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with CScout.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *
20  * A character coming from a file.
21  * This class also handles trigraphs and newline splicing.
22  *
23  */
24 
25 #ifndef FCHAR_
26 #define FCHAR_
27 
28 #include <stack>
29 #include <deque>
30 #include <map>
31 
32 #include "fileid.h"
33 #include "cpp.h"
34 #include "tokid.h"
35 #include "fchar.h"
36 #include "fifstream.h"
37 
38 using namespace std;
39 
40 /*
41  * A file position
42  * Assumes that the putback stack is empty.
43  * FcharContext is used for:
44  * - pushing/restoring include file handling
45  * - identifying begin/end locations of functions and macros
46  */
47 class FcharContext {
48 private:
49 	int line_number;
50 	Tokid ti;
51 public:
FcharContext()52 	FcharContext() : line_number(-1) {}
FcharContext(int l,Tokid t)53 	FcharContext(int l, Tokid t) :
54 		line_number(l), ti(t) {}
55 	// Accessor methods
get_line_number()56 	int get_line_number() const { return line_number; }
get_tokid()57 	Tokid get_tokid() const { return ti; }
58 	// Return true if correctly initialized
is_valid()59 	bool is_valid() const { return line_number != -1; }
60 };
61 
62 typedef stack <FcharContext> StackFcharContext;
63 
64 class Fchar;
65 
66 // For pushback; two token stack needed to parse the "..."
67 typedef stack <Fchar> stackFchar;
68 
69 class Fchar {
70 private:
71 	void simple_getnext();		// Trigraphs and slicing
72 	static bool trigraphs_enabled;	// True if trigraphs are enabled
73 	static fifstream in;		// Stream we are reading from
74 	static Fileid fi;		// and its Fileid
75 	static int line_number;		// Current line number
76 	static bool yacc_file;		// True if input file is yacc, not C
77 	static StackFcharContext cs;	// Pushed contexts (from push_input())
78 	static stackFchar ps;		// Putback stack
79 	static size_t stack_lock_size;	// So many elements can not be removed
80 					// from the push_input stack
81 
82 	static bool output_headers;	// Debug print of files being processed
83 	int val;
84 	Tokid ti;			// (pos_type from tellg(), fi)
85 
86 public:
87 	// Will read characters from file named s
88 	static void set_input(const string& s);
89 	// From now on will read from s; on EOF resume with previous file
90 	// Offset is the location of the include file path where the file
91 	// was located, and is used for implementing include_next
92 	static void push_input(const string& s, int offset = 0);
93 	// Next constructor will return c
94 	static void putback(Fchar c);
95 	/*
96 	 * Lock current context into the file stack, so it can not
97 	 * be popped by getnext until unlock is called.
98 	 * Call it after a push_input operation
99 	 */
lock_stack()100 	static void lock_stack() { stack_lock_size = cs.size(); }
unlock_stack()101 	static void unlock_stack() { stack_lock_size = 0; }
set_output_headers()102 	static void set_output_headers() { output_headers = true; }
103 
104 	// Return the current file position
get_context()105 	static FcharContext get_context() {
106 		return FcharContext(line_number, Tokid(fi, in.tellg()));
107 	}
108 	//
109 	// Set the current file position
110 	static void set_context(const FcharContext &c);
111 
112 	// Construct an unititialized one
Fchar()113 	Fchar() {};
114 	// Construct it with a given value and tokid
Fchar(int v,Tokid t)115 	Fchar(int v, Tokid t) : val(v), ti(t) {};
Fchar(int v)116 	Fchar(int v) : val(v) {};
117 	// Read next from stream
118 	void getnext();
119 	// Return the character value (or EOF)
get_char()120 	inline int get_char() const { return (val); };
121 	// Return the character's Tokid
get_tokid()122 	inline Tokid get_tokid() const { return (ti); };
123 	// Return the current line number
get_line_num()124 	static int get_line_num() { return line_number; }
get_path()125 	static string  get_path() { return fi.get_path(); }
get_fname()126 	static string  get_fname() { return fi.get_fname(); }
get_dir()127 	static string  get_dir() { return fi.get_dir(); }
128 	// Return the fileid of the file we are processing
get_fileid()129 	static Fileid get_fileid() { return fi; }
130 	// Return true if the class's source is a file
is_file_source()131 	static bool is_file_source() { return true; }
is_yacc_file()132 	static bool is_yacc_file() { return yacc_file; }
133 	// Enable the handling of trigraphs
enable_trigraphs()134 	static void enable_trigraphs() { trigraphs_enabled = true; }
135 };
136 
137 #endif /* FCHAR_ */
138