1 // $Id: CxxFile.hh,v 1.29 2004/05/07 06:53:14 christof Exp $
2 /*  glade--: C++ frontend for glade (Gtk+ User Interface Builder)
3  *  Copyright (C) 1998  Christof Petig
4  *  Copyright (C) 1999-2000 Adolf Petig GmbH & Co. KG, written by Christof Petig
5  *
6  *  This program 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 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program 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 this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 // 2do: When to push ???
22 
23 // see also Makefile.hh
24 
25 #ifndef CXXFILE_HH
26 #define CXXFILE_HH
27 
28 #include "SystemFile.hh"
29 #include <set>
30 #include <UniqueValue.h>
31 
32 // I'd like to put these in an namespace, but not all compiler support it
33 // yet
34 
35 enum CxxFile_Context
36 {  ctx_Outside, // nothing pending, new line
37    ctx_ClassPrivate, // within a class declaration
38    ctx_ClassPublic,
39    ctx_ClassProtected,
40    ctx_Block, // perhaps an alias for Outside
41    ctx_ReturnType, // return type of a function declaration
42    ctx_FunctionName, // name of a function declaration, perhaps call
43    ctx_MidFunctionArgs, // argument of a function
44    ctx_MidConstructor, // constructors
45    ctx_MidConstruction, // 2nd+ constructor
46    ctx_MidCtorArgs, // Arguments to a member constructor
47    ctx_DefineName, // define Name
48    ctx_DefineBody, // define Body
49    ctx_Declaration, // inside a declaration (';' at end of line)
50    ctx_Definition, // perhaps ';' after block (see Global_Context)
51    ctx_Statement, // inside a statement
52    ctx_ShortComment, // inside a short comment
53    ctx_Comment, // inside a comment
54    ctx_ClassName, // just behind 'class '
55    ctx_RValue, // just behind ' = '
56    ctx_RValueWritten, // behind ' = something'
57    ctx_Derivation, // just behind 'class X :'
58    ctx_CppIf, // #if
59    ctx_CppIfDef, // #if[n]def
60    ctx_BlockStatement, // for, if, else, while
61    ctx_Namespace, // namespace
62 };
63 
64 enum CxxFile_Global_Context
65 {  gc_start, // start of file
66    gc_include, // includes
67    gc_declaration, // variable, class or function declaration
68    gc_statement, // statement or function call
69    gc_class, // class/struct/union definition
70    gc_function, // function definition
71 };
72 
73 // this @$%& C++ standard does not allow this enum inside CxxFile
74 // if you want to use this operation inside inline declared functions!!!
75 // namespaces cure this (sort of)
76 extern std::ostream &operator<<(std::ostream &,const CxxFile_Context &ctx);
77 extern std::ostream &operator<<(std::ostream &,const CxxFile_Global_Context &ctx);
78 
79 class CxxFile : public SystemFile
80 {
81 public:
82 	typedef CxxFile_Global_Context Global_Context;
83 	typedef CxxFile_Context Context;
84 
85 	static UniqueValue element_types;
86 	static const UniqueValue::value_t v_IncludeBracket;
87 	static const UniqueValue::value_t v_IncludeQuote;
88 
89 	struct element_t
90 	{  UniqueValue::value_t type;
91 	   std::string identifier;
92 
element_tCxxFile::element_t93 	   element_t(UniqueValue::value_t v,const std::string &i)
94 	   : type(v), identifier(i) {}
operator ==CxxFile::element_t95 	   bool operator==(const element_t &b) const
96 	   { return type==b.type && identifier==b.identifier; }
operator <CxxFile::element_t97 	   bool operator<(const element_t &b) const
98 	   { return type<b.type || (type==b.type && identifier<b.identifier); }
99 	};
100 private:
101 	struct t_state
102 	{  int indentation;
103 	   int cpp_indentation;
104 	   Context context;
105 	   Global_Context global;
106 
t_stateCxxFile::t_state107 	   t_state() : indentation(0), cpp_indentation(0),
108 	   	context(ctx_Outside), global(gc_start) {}
109 	} state;
110 
111 	typedef std::vector<t_state> t_statestack;
112 	t_statestack pushed;
113 
114 	std::set<element_t> elements;
115 
116 	bool empty_line:1;
117 	bool indent_pending:1;
118 
119 	void push(Context c,int indent_delta=0);
120 	void pop();
121 	void new_context(Context c);
122 	SystemFile &Output();
123 	void SomethingShiftingLeft();
124 
init()125 	void init()
126 	{  empty_line=true;
127 	   indent_pending=true;
128 	}
129 public:
CxxFile()130 	CxxFile() : empty_line(true), indent_pending(true) {}
131 protected:
CxxFile(CxxFile * fp,unsigned int stage=0)132 	CxxFile(CxxFile *fp,unsigned int stage=0)
133 		: SystemFile(fp,stage)
134 		{ fp->EndLine(); init(); state=fp->state; }
135 public:
CxxFile(std::ofstream & str,const std::string & name="")136 	CxxFile(std::ofstream &str, const std::string &name="")
137 		: SystemFile(str, name)  { init(); }
138 #if 0 // not portable !
139 	CxxFile(int fd, const std::string &name="")
140 		: SystemFile(fd, name) { init(); }
141 #endif
CxxFile(const std::string & name)142 	CxxFile(const std::string &name)
143 		: SystemFile(name) { init(); }
~CxxFile()144 	~CxxFile() { close(); }
145 	// perhaps shadow open to clear some variables, done by close?
146 	void close();
147 
148 	CxxFile &GlobalContext(Global_Context new_gc,bool stay_inside=false);
149 	CxxFile &ToOutside();
150 
151 	CxxFile &Include(const std::string &name,bool local=false);
152 	CxxFile &FunctionArg();
153 	CxxFile &Funct_ReturnType();
Funct_Storage()154 	CxxFile &Funct_Storage()
155 	{  return Funct_ReturnType(); }
156 	CxxFile &FunctionName();
157 	CxxFile &StartBlock();
158 	CxxFile &EndBlock();
159 	CxxFile &BlockStatement(); // if(), else, while(), for()
160 	CxxFile &TypeDefinition(); // ??
161 	CxxFile &EndType();
162 	CxxFile &Private();
163 	CxxFile &Protected();
164 	CxxFile &Public();
165 	CxxFile_Context Visibility(); // !const, calls ToOutside()
166 	CxxFile &Visibility(CxxFile_Context ctx);
167 	CxxFile &NewLine(bool end_this_line=true);
168 	CxxFile &Statement();
169 	CxxFile &Declaration();
170 	CxxFile &Definition();
171 	CxxFile &Class();
172 	CxxFile &EndLine(bool endBlock=false);
173 	CxxFile &ShortComment();
VSpace()174 	CxxFile &VSpace()
175 	{  NewLine(false);
176 	   empty_line=false;
177 	   return NewLine(false);
178 	}
179 	CxxFile &DefineName();
180 	CxxFile &DefineBody();
181 	CxxFile &CppIf();
182 	CxxFile &CppElse();
183 	CxxFile &CppElif();
184 	CxxFile &EndIf();
185 	CxxFile &Constructor();
186 	CxxFile &Assignment();
187 	CxxFile &Derivation();
188 	CxxFile &Namespace();
189 
Construct(const std::string & instance,const std::string & params)190 	CxxFile &Construct(const std::string &instance, const std::string &params)
191 	{  return Constructor() << instance << '(' << params << ')';
192 	}
193 
EndIf(const std::string & s)194 	CxxFile &EndIf(const std::string &s)
195 	{  EndIf() << s;
196 //	   empty_line=true; // what was this for?
197 	   return *this;
198 	}
CppIf(const std::string & s)199 	CxxFile &CppIf(const std::string &s)
200 	{  return CppIf() << s; }
Undef(const std::string & s)201 	CxxFile &Undef(const std::string &s)
202 	{  NewLine().NoIndent() << "#undef " << s;
203 	   NewLine(false);
204 	   return *this;
205 	}
206 	CxxFile &FunctionEndArgs();
207 
208 	// convenience Functions:
NoIndent()209 	CxxFile &NoIndent()
210 	{  indent_pending=false;
211 	   return *this;
212 	}
FunctionArg(const std::string & s)213 	CxxFile &FunctionArg(const std::string &s)
214 	{  return FunctionArg()<<s; }
Funct_Storage(const std::string & s)215 	CxxFile &Funct_Storage(const std::string &s)
216 	{  return Funct_Storage()<<s; }
Funct_ReturnType(const std::string & s)217 	CxxFile &Funct_ReturnType(const std::string &s)
218 	{  return Funct_ReturnType()<<s; }
FunctionName(const std::string & s)219 	CxxFile &FunctionName(const std::string &s)
220 	{  return FunctionName()<<s; }
Statement(const std::string & s)221 	CxxFile &Statement(const std::string &s)
222 	{  return Statement()<<s; }
Declaration(const std::string & s)223 	CxxFile &Declaration(const std::string &s)
224 	{  return Declaration()<<s; }
Class(const std::string & s)225 	CxxFile &Class(const std::string &s)
226 	{  return Class()<<s; }
ShortComment(const std::string & s)227 	CxxFile &ShortComment(const std::string &s)
228 	{  return ShortComment()<<s; }
DefineName(const std::string & s)229 	CxxFile &DefineName(const std::string &s)
230 	{  return DefineName()<<s; }
DefineBody(const std::string & s)231 	CxxFile &DefineBody(const std::string &s)
232 	{  return DefineBody()<<s; }
Assignment(const std::string & s)233 	CxxFile &Assignment(const std::string &s)
234 	{  return Assignment()<<s; }
Derive(const std::string & s)235 	CxxFile &Derive(const std::string &s)
236 	{  return Derivation()<<s; }
Namespace(const std::string & s)237 	CxxFile &Namespace(const std::string &s)
238 	{  return Namespace()<<s; }
239 
240 	void InvalidState(const std::string &s="CxxFile.cc");
241 	void dump_context_stack() const;
write_remembered(unsigned int stage=0)242 	void write_remembered(unsigned int stage=0)
243 	{  EndLine(); SystemFile::write_remembered(stage); }
244 
ElementAlreadyThere(const element_t & e)245 	bool ElementAlreadyThere(const element_t &e)
246 	{  return elements.find(e)!=elements.end();
247 	}
AddElement(const element_t & e)248 	void AddElement(const element_t &e)
249 	{  elements.insert(e);
250 	}
251 
252 /* egcs 1.x issues an error and gcc-2.95 crashes */
253 #if defined __GNUC__ && __GNUC__ >= 3
254 	// adaptor
operator <<(const U & t)255 	template <class U> CxxFile &operator<<(const U &t)
256 	{  SomethingShiftingLeft();
257 	   Output() << t;
258 	   return *this;
259 	}
260 #else // older compilers do not work correctly
261 #	define op_shl(U) CxxFile &operator<<(const U &t) \
262 		{  SomethingShiftingLeft(); \
263 		   Output() << t; \
264 		   return *this; \
265 		}
266 
267 	op_shl(std::string)
268 	op_shl(char * const)
269 	op_shl(signed int)
270 	op_shl(unsigned int)
271 	op_shl(unsigned long)
272 	op_shl(signed long)
273 	op_shl(char)
274 #ifdef __CHAR_UNSIGNED__
275 	op_shl(signed char)
276 #else
277 	op_shl(unsigned char)
278 #endif
279 	op_shl(float)
280 #undef op_shl
281 #endif
282 };
283 
284 #endif
285