1 /* "CodeWorker":	a scripting language for parsing and generating text.
2 
3 Copyright (C) 1996-1997, 1999-2002 C�dric Lemaire
4 
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 To contact the author: codeworker@free.fr
20 */
21 
22 #ifdef WIN32
23 #pragma warning (disable : 4786)
24 #endif
25 
26 #include <set>
27 
28 #include "ScpStream.h"
29 #include "UtlException.h"
30 
31 #include "CGRuntime.h"
32 #include "DtaProject.h"
33 #include "DtaPatternScript.h"
34 #include "GrfFunction.h"
35 #include "BNFClause.h"
36 #include "DynFunction.h"
37 #include "DynPackage.h"
38 #include "CGCompiler.h"
39 #include "CppCompilerEnvironment.h"
40 
41 namespace CodeWorker {
42 	class CppStack {
43 	private:
44 		std::set<std::string> _setOfVariables;
45 
46 	public:
CppStack()47 		CppStack() {}
~CppStack()48 		~CppStack() {}
49 
50 		bool addVariable(const std::string& sVariable);
51 		bool existVariable(const std::string& sVariable) const;
52 	};
53 
addVariable(const std::string & sVariable)54 	bool CppStack::addVariable(const std::string& sVariable) {
55 		std::set<std::string>::const_iterator cursor = _setOfVariables.find(sVariable);
56 		if (cursor != _setOfVariables.end()) return false;
57 		_setOfVariables.insert(sVariable);
58 		return true;
59 	}
60 
existVariable(const std::string & sVariable) const61 	bool CppStack::existVariable(const std::string& sVariable) const {
62 		std::set<std::string>::const_iterator cursor = _setOfVariables.find(sVariable);
63 		return (cursor != _setOfVariables.end());
64 	}
65 
66 
67 	class CppVariableScope {
68 	private:
69 		std::list<CppStack*> _stack;
70 		std::string _sClauseReturnValue;
71 		bool _bHasEvaluatedExpressionInScope;
72 
73 	public:
CppVariableScope()74 		CppVariableScope() : _bHasEvaluatedExpressionInScope(false) { addStack(); }
~CppVariableScope()75 		~CppVariableScope() { removeStack(); }
76 
addVariable(const std::string & sVariable)77 		bool addVariable(const std::string& sVariable) { return _stack.front()->addVariable(sVariable); }
78 		bool existVariable(const std::string& sVariable) const;
addStack()79 		void addStack() { _stack.push_front(new CppStack); }
removeStack()80 		void removeStack() { delete _stack.front(); _stack.pop_front(); }
81 		void setClauseReturnValue(const std::string& sClauseName);
82 		bool isClauseReturnValue(const std::string& sVariableName) const;
hasEvaluatedExpressionInScope(bool bEvaluated)83 		void hasEvaluatedExpressionInScope(bool bEvaluated) { _bHasEvaluatedExpressionInScope = bEvaluated; }
hasEvaluatedExpressionInScope() const84 		bool hasEvaluatedExpressionInScope() const { return _bHasEvaluatedExpressionInScope; }
85 
86 	private:
87 		CppVariableScope(const CppVariableScope&);
88 		CppVariableScope& operator =(const CppVariableScope&);
89 	};
90 
existVariable(const std::string & sVariable) const91 	bool CppVariableScope::existVariable(const std::string& sVariable) const {
92 		for (std::list<CppStack*>::const_iterator i = _stack.begin(); i != _stack.end(); i++) {
93 			if ((*i)->existVariable(sVariable)) return true;
94 		}
95 		return false;
96 	}
97 
setClauseReturnValue(const std::string & sClauseName)98 	void CppVariableScope::setClauseReturnValue(const std::string& sClauseName) {
99 		_sClauseReturnValue = sClauseName;
100 	}
101 
isClauseReturnValue(const std::string & sVariableName) const102 	bool CppVariableScope::isClauseReturnValue(const std::string& sVariableName) const {
103 		return (_sClauseReturnValue == sVariableName);
104 	}
105 
106 
CppScriptSession(const std::string & sFilename,const std::string & sCppRadical)107 	CppScriptSession::CppScriptSession(const std::string& sFilename, const std::string& sCppRadical) : _sFilename(sFilename), _sCppRadical(sCppRadical), _header(0), _body(0) {
108 		_header = new DtaPatternScript;
109 		std::string sSourceFile = sCppRadical + ".h";
110 		ScpStream* pOldStream;
111 		_header->openGenerate(false, sSourceFile.c_str(), pOldStream);
112 		_body = new DtaPatternScript;
113 		sSourceFile = sCppRadical + ".cpp";
114 		_body->openGenerate(false, sSourceFile.c_str(), pOldStream);
115 		pushVariableScope();
116 	}
CppScriptSession(const CppScriptSession & copy)117 	CppScriptSession::CppScriptSession(const CppScriptSession& copy) : _header(copy._header), _body(copy._body) {
118 		_sIndentation = copy._sIndentation;
119 		_setOfProjectFunctions = copy._setOfProjectFunctions;
120 		_setOfProjectClauses = copy._setOfProjectClauses;
121 		_sFilename = copy._sFilename;
122 		_sCppRadical = copy._sCppRadical;
123 		copy._header = 0;
124 		copy._body = 0;
125 		_stackOfScopes = copy._stackOfScopes;
126 		copy._stackOfScopes = std::list<CppVariableScope*>();
127 	}
operator =(const CppScriptSession & copy)128 	CppScriptSession& CppScriptSession::operator =(const CppScriptSession& copy) {
129 		_sIndentation = copy._sIndentation;
130 		_setOfProjectFunctions = copy._setOfProjectFunctions;
131 		_setOfProjectClauses = copy._setOfProjectClauses;
132 		_sFilename = copy._sFilename;
133 		_sCppRadical = copy._sCppRadical;
134 		_header = copy._header;
135 		_body = copy._body;
136 		copy._header = 0;
137 		copy._body = 0;
138 		_stackOfScopes = copy._stackOfScopes;
139 		copy._stackOfScopes = std::list<CppVariableScope*>();
140 		return *this;
141 	}
~CppScriptSession()142 	CppScriptSession::~CppScriptSession() {
143 		std::string sExceptionMessage;
144 		std::string sExceptionStack;
145 		if (_header != 0) {
146 			try {
147 				ScpStream* pOldStream = NULL;
148 				std::string sSourceFile = _sCppRadical + ".h";
149 				_header->closeGenerate(false, sSourceFile.c_str(), pOldStream);
150 			} catch(UtlException& exception) {
151 				sExceptionMessage = exception.getMessage();
152 				sExceptionStack = exception.getTraceStack();
153 			}
154 			delete _header;
155 		}
156 		if (_body != 0) {
157 			try {
158 				ScpStream* pOldStream = NULL;
159 				std::string sSourceFile = _sCppRadical + ".cpp";
160 				_body->closeGenerate(false, sSourceFile.c_str(), pOldStream);
161 			} catch(UtlException& exception) {
162 				if (!sExceptionMessage.empty() || !sExceptionStack.empty()) sExceptionMessage += "\n";
163 				sExceptionMessage += exception.getMessage();
164 				sExceptionStack += exception.getTraceStack();
165 			}
166 			delete _body;
167 		}
168 
169 		for (std::list<CppVariableScope*>::iterator i = _stackOfScopes.begin(); i != _stackOfScopes.end(); ++i) {
170 			delete *i;
171 		}
172 
173 		if (!sExceptionMessage.empty() || !sExceptionStack.empty()) throw UtlException(sExceptionMessage, sExceptionStack);
174 	}
175 
incrementIndentation()176 	void CppScriptSession::incrementIndentation() {
177 		_sIndentation += "\t";
178 		_stackOfScopes.front()->addStack();
179 	}
180 
decrementIndentation()181 	void CppScriptSession::decrementIndentation() {
182 		if (_sIndentation.size() == 1) _sIndentation = "";
183 		else _sIndentation = _sIndentation.substr(1);
184 		_stackOfScopes.front()->removeStack();
185 	}
186 
pushVariableScope() const187 	void CppScriptSession::pushVariableScope() const {
188 		_stackOfScopes.push_front(new CppVariableScope);
189 	}
190 
popVariableScope() const191 	void CppScriptSession::popVariableScope() const {
192 		delete _stackOfScopes.front();
193 		_stackOfScopes.pop_front();
194 	}
195 
pushForeach(GrfForeach * pForeach)196 	void CppScriptSession::pushForeach(GrfForeach* pForeach) {
197 		_listOfForeachStatements.push_front(pForeach);
198 	}
199 
getLastForeach() const200 	GrfForeach* CppScriptSession::getLastForeach() const {
201 		return _listOfForeachStatements.front();
202 	}
203 
popForeach()204 	void CppScriptSession::popForeach() {
205 		_listOfForeachStatements.pop_front();
206 	}
207 
catchFilename()208 	void CppScriptSession::catchFilename() {
209 		ScpStream* pOldStream = NULL;
210 		_header->catchGenerateExecution(false, pOldStream, NULL);
211 		delete _header;
212 		_header = 0;
213 		_body->catchGenerateExecution(false, pOldStream, NULL);
214 		delete _body;
215 		_body = 0;
216 	}
217 
218 
CppNewVariableScopeEnvironment(CppCompilerEnvironment & env)219 	CppNewVariableScopeEnvironment::CppNewVariableScopeEnvironment(CppCompilerEnvironment& env) : _session(env.getCurrentScriptSession()) {
220 		_stackOfScopes = _session._stackOfScopes;
221 		_session._stackOfScopes = std::list<CppVariableScope*>();
222 		_session.pushVariableScope();
223 	}
224 
~CppNewVariableScopeEnvironment()225 	CppNewVariableScopeEnvironment::~CppNewVariableScopeEnvironment() {
226 		_session.popVariableScope();
227 		_session._stackOfScopes = _stackOfScopes;
228 	}
229 
230 
231 
CppCompilerEnvironment(const std::string & sCppProjectDirectory)232 	CppCompilerEnvironment::CppCompilerEnvironment(const std::string& sCppProjectDirectory) : _bBracketsToNextBlock(true), _bCarriageReturnAfterBlock(true), _iSwitchNumber(0), _iCursorNumber(0), _bErrorEncountered(false), _iPointerToDeclarations(0), _pCurrentClause(NULL), _iBNFStepperCursor(0), _iInlineScriptCounter(0) {
233 		_sCodeWorkerDirectory = DtaProject::getInstance().getCodeWorkerHome();
234 		if ((sCppProjectDirectory[0] == '/') || (!sCppProjectDirectory.empty() && (sCppProjectDirectory[1] == ':'))) _sCppProjectDirectory = CGRuntime::canonizePath(sCppProjectDirectory);
235 		else _sCppProjectDirectory = CGRuntime::relativePath(sCppProjectDirectory, CGRuntime::getWorkingPath());
236 		if (_sCppProjectDirectory[_sCppProjectDirectory.size() - 1] != '/') _sCppProjectDirectory += "/";
237 		CGRuntime::setProperty("c++2target-path", _sCppProjectDirectory);
238 		addGlobalVariable("_ARGS");
239 		addGlobalVariable("_REQUEST"); // for CGI program
240 		try {
241 			std::string sCWIncludeDir = _sCodeWorkerDirectory;
242 			if (CGRuntime::existFile(sCWIncludeDir + "include/UtlException.h")) sCWIncludeDir += "include/";
243 			CGRuntime::copySmartFile(sCWIncludeDir + "UtlException.h", _sCppProjectDirectory + "UtlException.h");
244 			CGRuntime::copySmartFile(sCWIncludeDir + "CppParsingTree.h", _sCppProjectDirectory + "CppParsingTree.h");
245 			CGRuntime::copySmartFile(sCWIncludeDir + "CGRuntime.h", _sCppProjectDirectory + "CGRuntime.h");
246 			CGRuntime::copySmartFile(sCWIncludeDir + "CGExternalHandling.h", _sCppProjectDirectory + "CGExternalHandling.h");
247 			CGRuntime::copySmartFile(sCWIncludeDir + "DynPackage.h", _sCppProjectDirectory + "DynPackage.h");
248 		} catch(UtlException&) {
249 			CGRuntime::traceLine("WARNING: (considering '" + _sCodeWorkerDirectory + "' as the root path of 'CodeWorker') unable to copy files 'UtlException.h' + 'CppParsingTree.h' + 'CGRuntime.h' in the project directory '" + _sCppProjectDirectory + "'");
250 		}
251 	}
252 
~CppCompilerEnvironment()253 	CppCompilerEnvironment::~CppCompilerEnvironment() {
254 		if (!_bErrorEncountered) {
255 			generateDynamicPackages();
256 			generateDSP();
257 			generateMakefile();
258 		}
259 	}
260 
pushLastRepeatCursor(int iCursor)261 	void CppCompilerEnvironment::pushLastRepeatCursor(int iCursor) {
262 		_listOfLastRepeatCursors.push_back(iCursor);
263 		_listOfLastRepeatCursorUsed.push_back(false);
264 	}
265 
getLastRepeatCursor(bool bUsed)266 	int CppCompilerEnvironment::getLastRepeatCursor(bool bUsed) {
267 		if (_listOfLastRepeatCursors.empty()) return -1;
268 		if (bUsed) _listOfLastRepeatCursorUsed.back() = true;
269 		return _listOfLastRepeatCursors.back();
270 	}
271 
popLastRepeatCursor()272 	bool CppCompilerEnvironment::popLastRepeatCursor() {
273 		bool bUsed = _listOfLastRepeatCursorUsed.back();
274 		_listOfLastRepeatCursors.pop_back();
275 		_listOfLastRepeatCursorUsed.pop_back();
276 		return bUsed;
277 	}
278 
generateDynamicPackages()279 	void CppCompilerEnvironment::generateDynamicPackages() {
280 		const std::map<std::string, DynPackage*>& allPackages = DynPackage::allPackages();
281 		for (std::map<std::string, DynPackage*>::const_iterator i = allPackages.begin(); i != allPackages.end(); ++i) {
282 			std::auto_ptr<ScpStream> pModuleHeader(new ScpStream(_sCppProjectDirectory + i->first + ".h", ScpStream::OUT));
283 			std::auto_ptr<ScpStream> pModuleBody(new ScpStream(_sCppProjectDirectory + i->first + ".cpp", ScpStream::OUT));
284 			(*pModuleHeader) << "#ifndef _" << i->first << "_h_" << ScpStream::ENDL;
285 			(*pModuleHeader) << "#define _" << i->first << "_h_" << ScpStream::ENDL << ScpStream::ENDL;
286 			(*pModuleHeader) << "#include <string>" << ScpStream::ENDL;
287 			(*pModuleHeader) << "#include \"DynPackage.h\"" << ScpStream::ENDL;
288 			(*pModuleHeader) << ScpStream::ENDL << "namespace CodeWorker {" << ScpStream::ENDL;
289 			(*pModuleHeader) << "\tclass CppParsingTree_value;" << ScpStream::ENDL;
290 			(*pModuleHeader) << "\tclass CppParsingTree_var;" << ScpStream::ENDL;
291 			(*pModuleHeader) << ScpStream::ENDL << "\tclass " << i->first << " : public CodeWorker::DynPackage {" << ScpStream::ENDL;
292 			(*pModuleHeader) << "\t\tpublic:" << ScpStream::ENDL;
293 			(*pModuleHeader) << "\t\t\t" << i->first << "();" << ScpStream::ENDL;
294 			(*pModuleHeader) << "\t\t\tstatic " << i->first << "& instance();" << ScpStream::ENDL;
295 			(*pModuleBody) << "#ifdef WIN32" << ScpStream::ENDL;
296 			(*pModuleBody) << "#pragma warning(disable: 4786)" << ScpStream::ENDL;
297 			(*pModuleBody) << "#endif" << ScpStream::ENDL << ScpStream::ENDL;
298 			(*pModuleBody) << "#include \"UtlException.h\"" << ScpStream::ENDL;
299 			(*pModuleBody) << "#include \"CppParsingTree.h\"" << ScpStream::ENDL;
300 			(*pModuleBody) << "#include \"" << i->first << ".h\"" << ScpStream::ENDL;
301 			(*pModuleBody) << ScpStream::ENDL << "namespace CodeWorker {" << ScpStream::ENDL;
302 			(*pModuleBody) << "\t" << i->first << "* " << i->first << "::pInstance_ = NULL;" << ScpStream::ENDL << ScpStream::ENDL;
303 			(*pModuleBody) << "\t" << i->first << "::" << i->first << "() : CodeWorker::DynPackage(\"" << i->first << "\") {" << ScpStream::ENDL;
304 			(*pModuleBody) << "\t\tpInstance_ = this;" << ScpStream::ENDL;
305 			(*pModuleBody) << "\t}" << ScpStream::ENDL << ScpStream::ENDL;
306 			(*pModuleBody) << "\t" << i->first << "& " << i->first << "::instance() {" << ScpStream::ENDL;
307 			(*pModuleBody) << "\t\tif (pInstance_ == NULL) throw UtlException(\"The dynamic package '" << i->first << "' should have been initialized before use!\");" << ScpStream::ENDL;
308 			(*pModuleBody) << "\t\treturn *pInstance_;" << ScpStream::ENDL;
309 			(*pModuleBody) << "\t}" << ScpStream::ENDL << ScpStream::ENDL;
310 			for (std::map<std::string, DynFunction*>::const_iterator j = i->second->allFunctions().begin(); j != i->second->allFunctions().end(); ++j) {
311 				(*pModuleHeader) << "\t\t\tstd::string _compilerFunction_" << j->first << "(";
312 				(*pModuleBody) << "\tstd::string " + i->first + "::_compilerFunction_" << j->first << "(";
313 				int iIndex = 0;
314 				std::list<std::string>::const_iterator k;
315 				for (k = j->second->getParameters().begin(); k != j->second->getParameters().end(); ++k) {
316 					if (iIndex > 0) {
317 						(*pModuleHeader) << ", ";
318 						(*pModuleBody) << ", ";
319 					}
320 					switch(j->second->getParameterType(iIndex) & 0x00FF) {
321 						case VALUE_EXPRTYPE:
322 							(*pModuleHeader) << "const CodeWorker::CppParsingTree_value& ";
323 							(*pModuleBody) << "const CodeWorker::CppParsingTree_value& ";
324 							break;
325 						case NODE_EXPRTYPE:
326 							(*pModuleHeader) << "const CodeWorker::CppParsingTree_var& ";
327 							(*pModuleBody) << "const CodeWorker::CppParsingTree_var& ";
328 							break;
329 						default:
330 							throw UtlException("fatal error while generating the C++ layer of the dynamic module '" + i->first + "': unrecognized parameter type of variable '" + *k + "'");
331 					}
332 					(*pModuleHeader) << *k;
333 					(*pModuleBody) << *k;
334 					iIndex++;
335 				}
336 				(*pModuleHeader) << ");" << ScpStream::ENDL;
337 				(*pModuleBody) << ") {" << ScpStream::ENDL;
338 				(*pModuleBody) << "\t\tstatic CALL" << iIndex << "_FUNCTION pfFunctionCall = (CALL" << iIndex << "_FUNCTION) findFunction(_hHandle, \"" << j->first << "\");" << ScpStream::ENDL;
339 				(*pModuleBody) << "\t\tif (pfFunctionCall == NULL) throw UtlException(\"the module '" << i->first << "' doesn't export the function '" << i->first << "::" << j->first << "'\");" << ScpStream::ENDL;
340 				iIndex = 0;
341 				if (j->second->getParameters().size() <= 4) {
342 					(*pModuleBody) << "\t\tconst char* tcResult = pfFunctionCall(_pInterpreter";
343 					for (k = j->second->getParameters().begin(); k != j->second->getParameters().end(); ++k) {
344 						(*pModuleBody) << ", ";
345 						switch(j->second->getParameterType(iIndex) & 0x00FF) {
346 							case VALUE_EXPRTYPE:
347 								(*pModuleBody) << "(char*) " << *k << ".getValue()";
348 								break;
349 							case NODE_EXPRTYPE:
350 								(*pModuleBody) << *k << ".getInternalNode()";
351 								break;
352 							default:
353 								throw UtlException("fatal error while generating the C++ layer of the dynamic module '" + i->first + "': unrecognized parameter type of variable '" + *k + "'");
354 						}
355 						iIndex++;
356 					}
357 					(*pModuleBody) << ");" << ScpStream::ENDL;
358 				} else {
359 					(*pModuleBody) << "\t\tCodeWorker::Parameter* tParams = new CodeWorker::Parameter[" << (int) j->second->getParameters().size() << "];";
360 					for (k = j->second->getParameters().begin(); k != j->second->getParameters().end(); ++k) {
361 						(*pModuleBody) << ", ";
362 						switch(j->second->getParameterType(iIndex) & 0x00FF) {
363 							case VALUE_EXPRTYPE:
364 								(*pModuleBody) << "\t\ttParams[" << iIndex << "] = (char*) " << *k << ".getValue();" << ScpStream::ENDL;
365 								break;
366 							case NODE_EXPRTYPE:
367 								(*pModuleBody) << "\t\ttParams[" << iIndex << "] = " << *k << ".getInternalNode();" << ScpStream::ENDL;
368 								break;
369 							default:
370 								throw UtlException("fatal error while generating the C++ layer of the dynamic module '" + i->first + "': unrecognized parameter type of variable '" + *k + "'");
371 						}
372 						iIndex++;
373 					}
374 					(*pModuleBody) << "\t\tconst char* tcResult = pfFunctionCall(_pInterpreter, tParams);" << ScpStream::ENDL;
375 					(*pModuleBody) << "\t\tdelete [] tParams;" << ScpStream::ENDL;
376 				}
377 				(*pModuleBody) << "\t\tif (tcResult == NULL) return \"\";" << ScpStream::ENDL;
378 				(*pModuleBody) << "\t\treturn tcResult;" << ScpStream::ENDL;
379 				(*pModuleBody) << "\t}" << ScpStream::ENDL << ScpStream::ENDL;
380 			}
381 			(*pModuleBody) << "}" << ScpStream::ENDL;
382 			(*pModuleHeader) << "\t\tprivate:" << ScpStream::ENDL;
383 			(*pModuleHeader) << "\t\t\tstatic " << i->first << "* " << "pInstance_;" << ScpStream::ENDL;
384 			(*pModuleHeader) << "\t};" << ScpStream::ENDL;
385 			(*pModuleHeader) << "}" << ScpStream::ENDL;
386 			(*pModuleHeader) << "#endif" << ScpStream::ENDL;
387 			{
388 				std::auto_ptr<ScpStream> pOldHeader(new ScpStream(_sCppProjectDirectory + i->first + ".h", ScpStream::IN | ScpStream::OUT));
389 				int iPosition;
390 				if (!pModuleHeader->equals(*pOldHeader, iPosition)) pModuleHeader->saveIntoFile(_sCppProjectDirectory + i->first + ".h", true);
391 			}
392 			{
393 				std::auto_ptr<ScpStream> pOldBody(new ScpStream(_sCppProjectDirectory + i->first + ".cpp", ScpStream::IN | ScpStream::OUT));
394 				int iPosition;
395 				if (!pModuleBody->equals(*pOldBody, iPosition)) pModuleBody->saveIntoFile(_sCppProjectDirectory + i->first + ".cpp", true);
396 			}
397 		}
398 	}
399 
generateDSP()400 	void CppCompilerEnvironment::generateDSP() {
401 		std::string sBinDir = _sCodeWorkerDirectory;
402 		if (CGRuntime::existFile(sBinDir + "bin/CodeWorker.lib")) sBinDir += "bin/";
403 		else if (CGRuntime::existFile(sBinDir + "../bin/CodeWorker.lib")) sBinDir += "../bin/";
404 		else if (CGRuntime::existFile(sBinDir + "lib/CodeWorker.lib")) sBinDir += "lib/";
405 		else if (CGRuntime::existFile(sBinDir + "../lib/CodeWorker.lib")) sBinDir += "../lib/";
406 		else sBinDir += "Release/";
407 		std::string sProjectName = getRadical(_listOfProjectModules.front());
408 		std::string::size_type iIndex = sProjectName.find_last_of('_');
409 		if ((iIndex != std::string::npos) && (iIndex != 0)) sProjectName = sProjectName.substr(0, iIndex);
410 		std::auto_ptr<ScpStream> pMakeFile(new ScpStream(_sCppProjectDirectory + sProjectName + ".dsp", ScpStream::IN | ScpStream::OUT));
411 		if (pMakeFile->empty()) {
412 			(*pMakeFile) << "# Microsoft Developer Studio Project File - Name=\"" << sProjectName << "\" - Package Owner=<4>\r\n";
413 			(*pMakeFile) << "# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n";
414 			(*pMakeFile) << "# ** DO NOT EDIT **\r\n";
415 			(*pMakeFile) << "\r\n";
416 			(*pMakeFile) << "# TARGTYPE \"Win32 (x86) Console Application\" 0x0103\r\n";
417 			(*pMakeFile) << "\r\n";
418 			(*pMakeFile) << "CFG=" << sProjectName << " - Win32 Debug\r\n";
419 			(*pMakeFile) << "!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n";
420 			(*pMakeFile) << "!MESSAGE use the Export Makefile command and run\r\n";
421 			(*pMakeFile) << "!MESSAGE \r\n";
422 			(*pMakeFile) << "!MESSAGE NMAKE /f \"" << sProjectName << ".mak\".\r\n";
423 			(*pMakeFile) << "!MESSAGE \r\n";
424 			(*pMakeFile) << "!MESSAGE You can specify a configuration when running NMAKE\r\n";
425 			(*pMakeFile) << "!MESSAGE by defining the macro CFG on the command line. For example:\r\n";
426 			(*pMakeFile) << "!MESSAGE \r\n";
427 			(*pMakeFile) << "!MESSAGE NMAKE /f \"" << sProjectName << ".mak\" CFG=\"" << sProjectName << " - Win32 Debug\"\r\n";
428 			(*pMakeFile) << "!MESSAGE \r\n";
429 			(*pMakeFile) << "!MESSAGE Possible choices for configuration are:\r\n";
430 			(*pMakeFile) << "!MESSAGE \r\n";
431 			(*pMakeFile) << "!MESSAGE \"" << sProjectName << " - Win32 Release\" (based on \"Win32 (x86) Console Application\")\r\n";
432 			(*pMakeFile) << "!MESSAGE \"" << sProjectName << " - Win32 Debug\" (based on \"Win32 (x86) Console Application\")\r\n";
433 			(*pMakeFile) << "!MESSAGE \r\n";
434 			(*pMakeFile) << "\r\n";
435 			(*pMakeFile) << "# Begin Project\r\n";
436 			(*pMakeFile) << "# PROP AllowPerConfigDependencies 0\r\n";
437 			(*pMakeFile) << "# PROP Scc_ProjName \"\"\r\n";
438 			(*pMakeFile) << "# PROP Scc_LocalPath \"\"\r\n";
439 			(*pMakeFile) << "CPP=cl.exe\r\n";
440 			(*pMakeFile) << "RSC=rc.exe\r\n";
441 			(*pMakeFile) << "\r\n";
442 			(*pMakeFile) << "!IF  \"$(CFG)\" == \"" << sProjectName << " - Win32 Release\"\r\n";
443 			(*pMakeFile) << "\r\n";
444 			(*pMakeFile) << "# PROP BASE Use_MFC 0\r\n";
445 			(*pMakeFile) << "# PROP BASE Use_Debug_Libraries 0\r\n";
446 			(*pMakeFile) << "# PROP BASE Output_Dir \"Release\"\r\n";
447 			(*pMakeFile) << "# PROP BASE Intermediate_Dir \"Release\"\r\n";
448 			(*pMakeFile) << "# PROP BASE Target_Dir \"\"\r\n";
449 			(*pMakeFile) << "# PROP Use_MFC 0\r\n";
450 			(*pMakeFile) << "# PROP Use_Debug_Libraries 0\r\n";
451 			(*pMakeFile) << "# PROP Output_Dir \"Release\"\r\n";
452 			(*pMakeFile) << "# PROP Intermediate_Dir \"Release\"\r\n";
453 			(*pMakeFile) << "# PROP Ignore_Export_Lib 0\r\n";
454 			(*pMakeFile) << "# PROP Target_Dir \"\"\r\n";
455 			(*pMakeFile) << "# ADD BASE CPP /nologo /W3 /GX /O2 /D \"WIN32\" /D \"NDEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /c\r\n";
456 			(*pMakeFile) << "# ADD CPP /nologo /MD /W3 /GR /GX /O2 /D \"NDEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /c\r\n";
457 			(*pMakeFile) << "# SUBTRACT CPP /YX\r\n";
458 			(*pMakeFile) << "# ADD BASE RSC /l 0x40c /d \"NDEBUG\"\r\n";
459 			(*pMakeFile) << "# ADD RSC /l 0x40c /d \"NDEBUG\"\r\n";
460 			(*pMakeFile) << "BSC32=bscmake.exe\r\n";
461 			(*pMakeFile) << "# ADD BASE BSC32 /nologo\r\n";
462 			(*pMakeFile) << "# ADD BSC32 /nologo\r\n";
463 			(*pMakeFile) << "LINK32=link.exe\r\n";
464 			(*pMakeFile) << "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n";
465 			(*pMakeFile) << "# ADD LINK32 " << sBinDir << "CodeWorker.lib ws2_32.lib rpcrt4.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r\n";
466 			(*pMakeFile) << "\r\n";
467 			(*pMakeFile) << "!ELSEIF  \"$(CFG)\" == \"" << sProjectName << " - Win32 Debug\"\r\n";
468 			(*pMakeFile) << "\r\n";
469 			(*pMakeFile) << "# PROP BASE Use_MFC 0\r\n";
470 			(*pMakeFile) << "# PROP BASE Use_Debug_Libraries 1\r\n";
471 			(*pMakeFile) << "# PROP BASE Output_Dir \"Debug\"\r\n";
472 			(*pMakeFile) << "# PROP BASE Intermediate_Dir \"Debug\"\r\n";
473 			(*pMakeFile) << "# PROP BASE Target_Dir \"\"\r\n";
474 			(*pMakeFile) << "# PROP Use_MFC 0\r\n";
475 			(*pMakeFile) << "# PROP Use_Debug_Libraries 1\r\n";
476 			(*pMakeFile) << "# PROP Output_Dir \"Debug\"\r\n";
477 			(*pMakeFile) << "# PROP Intermediate_Dir \"Debug\"\r\n";
478 			(*pMakeFile) << "# PROP Ignore_Export_Lib 0\r\n";
479 			(*pMakeFile) << "# PROP Target_Dir \"\"\r\n";
480 			(*pMakeFile) << "# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D \"WIN32\" /D \"_DEBUG\" /D \"_CONSOLE\" /D \"_MBCS\" /YX /FD /GZ /c\r\n";
481 			(*pMakeFile) << "# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /ZI /Od /D \"_DEBUG\" /D \"WIN32\" /D \"_CONSOLE\" /D \"_MBCS\" /FD /GZ /c\r\n";
482 			(*pMakeFile) << "# SUBTRACT CPP /YX\r\n";
483 			(*pMakeFile) << "# ADD BASE RSC /l 0x40c /d \"_DEBUG\"\r\n";
484 			(*pMakeFile) << "# ADD RSC /l 0x40c /d \"_DEBUG\"\r\n";
485 			(*pMakeFile) << "BSC32=bscmake.exe\r\n";
486 			(*pMakeFile) << "# ADD BASE BSC32 /nologo\r\n";
487 			(*pMakeFile) << "# ADD BSC32 /nologo\r\n";
488 			(*pMakeFile) << "LINK32=link.exe\r\n";
489 			(*pMakeFile) << "# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n";
490 			(*pMakeFile) << "# ADD LINK32 " << _sCodeWorkerDirectory << "Debug/CodeWorkerD.lib ws2_32.lib rpcrt4.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r\n";
491 			(*pMakeFile) << "\r\n";
492 			(*pMakeFile) << "!ENDIF \r\n";
493 			(*pMakeFile) << "\r\n";
494 			(*pMakeFile) << "# Begin Target\r\n";
495 			(*pMakeFile) << "\r\n";
496 			(*pMakeFile) << "# Name \"" << sProjectName << " - Win32 Release\"\r\n";
497 			(*pMakeFile) << "# Name \"" << sProjectName << " - Win32 Debug\"\r\n";
498 			(*pMakeFile) << "# Begin Group \"Source Files\"\r\n";
499 			(*pMakeFile) << "\r\n";
500 			(*pMakeFile) << "# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n";
501 		} else {
502 			if (!pMakeFile->findString("# Begin Source File")) throw UtlException("bad format encountered into Visual C++ project \"" + sProjectName + ".dsp\": unable to find tag '# Begin Source File'");
503 			pMakeFile->setOutputLocation(pMakeFile->getInputLocation() - 19);
504 		}
505 		std::list<std::string>::const_iterator i;
506 		for (i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
507 			(*pMakeFile) << "# Begin Source File\r\n";
508 			(*pMakeFile) << "\r\n";
509 			(*pMakeFile) << "SOURCE=\".\\" << getRelativePath(*i) << ".cpp\"\r\n";
510 			(*pMakeFile) << "# End Source File\r\n";
511 		}
512 		{
513 			const std::map<std::string, DynPackage*>& allPackages = DynPackage::allPackages();
514 			for (std::map<std::string, DynPackage*>::const_iterator i = allPackages.begin(); i != allPackages.end(); ++i) {
515 				(*pMakeFile) << "# Begin Source File\r\n";
516 				(*pMakeFile) << "\r\n";
517 				(*pMakeFile) << "SOURCE=\".\\" << i->first << ".cpp\"\r\n";
518 				(*pMakeFile) << "# End Source File\r\n";
519 			}
520 		}
521 		(*pMakeFile) << "# End Group\r\n";
522 		(*pMakeFile) << "# Begin Group \"Header Files\"\r\n";
523 		(*pMakeFile) << "\r\n";
524 		(*pMakeFile) << "# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n";
525 		for (i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
526 			std::string::size_type iIndex = i->find_last_of("/\\");
527 			std::string sFile;
528 			if (iIndex != std::string::npos) sFile = i->substr(iIndex + 1);
529 			else sFile = *i;
530 			(*pMakeFile) << "# Begin Source File\r\n";
531 			(*pMakeFile) << "\r\n";
532 			(*pMakeFile) << "SOURCE=\".\\" << getRelativePath(*i) << ".h\"\r\n";
533 			(*pMakeFile) << "# End Source File\r\n";
534 		}
535 		{
536 			const std::map<std::string, DynPackage*>& allPackages = DynPackage::allPackages();
537 			for (std::map<std::string, DynPackage*>::const_iterator i = allPackages.begin(); i != allPackages.end(); ++i) {
538 				(*pMakeFile) << "# Begin Source File\r\n";
539 				(*pMakeFile) << "\r\n";
540 				(*pMakeFile) << "SOURCE=\".\\" << i->first << ".h\"\r\n";
541 				(*pMakeFile) << "# End Source File\r\n";
542 			}
543 		}
544 		(*pMakeFile) << "# Begin Source File\r\n";
545 		(*pMakeFile) << "\r\n";
546 		(*pMakeFile) << "SOURCE=.\\CppParsingTree.h\r\n";
547 		(*pMakeFile) << "# End Source File\r\n";
548 		(*pMakeFile) << "# Begin Source File\r\n";
549 		(*pMakeFile) << "\r\n";
550 		(*pMakeFile) << "SOURCE=.\\UtlException.h\r\n";
551 		(*pMakeFile) << "# End Source File\r\n";
552 		(*pMakeFile) << "# End Group\r\n";
553 		(*pMakeFile) << "# Begin Group \"Resource Files\"\r\n";
554 		(*pMakeFile) << "\r\n";
555 		(*pMakeFile) << "# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n";
556 		(*pMakeFile) << "# End Group\r\n";
557 		(*pMakeFile) << "# End Target\r\n";
558 		(*pMakeFile) << "# End Project\r\n";
559 		std::auto_ptr<ScpStream> pOldMakeFile(new ScpStream(_sCppProjectDirectory + sProjectName + ".dsp", ScpStream::IN | ScpStream::OUT));
560 		int iPosition;
561 		if (!pMakeFile->equals(*pOldMakeFile, iPosition)) pMakeFile->saveIntoFile(_sCppProjectDirectory + sProjectName + ".dsp", true);
562 	}
563 
generateMakefile()564 	void CppCompilerEnvironment::generateMakefile() {
565 		std::string sBinDir = _sCodeWorkerDirectory;
566 		if (CGRuntime::existFile(sBinDir + "bin/libCodeWorker.a")) sBinDir += "bin/";
567 		else if (CGRuntime::existFile(sBinDir + "../bin/libCodeWorker.a")) sBinDir += "../bin/";
568 		else if (CGRuntime::existFile(sBinDir + "lib/libCodeWorker.a")) sBinDir += "lib/";
569 		else if (CGRuntime::existFile(sBinDir + "../lib/libCodeWorker.a")) sBinDir += "../lib/";
570 		std::string sProjectName = getRadical(_listOfProjectModules.front());
571 		std::string::size_type iIndex = sProjectName.find_last_of('_');
572 		if ((iIndex != std::string::npos) && (iIndex != 0)) sProjectName = sProjectName.substr(0, iIndex);
573 		std::auto_ptr<ScpStream> pMakeFile(new ScpStream(_sCppProjectDirectory + "Makefile", ScpStream::IN | ScpStream::OUT));
574 		std::auto_ptr<ScpStream> pOldMakeFile(new ScpStream(_sCppProjectDirectory + "Makefile", ScpStream::IN | ScpStream::OUT));
575 		(*pMakeFile) << "INCDIRS	= -I.\n";
576 		(*pMakeFile) << "CXXFLAGS	= -O2 -g $(INCDIRS)\n";
577 		(*pMakeFile) << "LFLAGS	= -g -lm -ldl -L" << sBinDir << " -lcodeworker\n";
578 		(*pMakeFile) << "CC	= g++\n";
579 		(*pMakeFile) << "\n";
580 		(*pMakeFile) << "OBJECTS = ";
581 		std::list<std::string>::const_iterator i;
582 		for (i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
583 			std::string sRadical = getRelativePath(*i);
584 			if (pMakeFile->getColCount() + sRadical.size() > 70) {
585 				(*pMakeFile) << "\\\n\t\t  ";
586 			} else {
587 				(*pMakeFile) << " ";
588 			}
589 			(*pMakeFile) << sRadical << ".o";
590 		}
591 		{
592 			const std::map<std::string, DynPackage*>& allPackages = DynPackage::allPackages();
593 			for (std::map<std::string, DynPackage*>::const_iterator i = allPackages.begin(); i != allPackages.end(); ++i) {
594 				if (pMakeFile->getColCount() + i->first.size() > 70) {
595 					(*pMakeFile) << "\\\n\t\t  ";
596 				} else {
597 					(*pMakeFile) << " ";
598 				}
599 				(*pMakeFile) << i->first << ".o";
600 			}
601 		}
602 		(*pMakeFile) << "\n\n";
603 		(*pMakeFile) << "all: build\n";
604 		(*pMakeFile) << "build: $(OBJECTS)\n";
605 		(*pMakeFile) << "\t$(CC) -o " << sProjectName << " $(OBJECTS) $(LFLAGS)\n";
606 		(*pMakeFile) << "clean:\n";
607 		(*pMakeFile) << "\t-rm -f *.o " << sProjectName << " core\n";
608 		int iPosition;
609 		if (!pMakeFile->equals(*pOldMakeFile, iPosition)) pMakeFile->saveIntoFile(_sCppProjectDirectory + "Makefile", true);
610 	}
611 
optimizeSources()612 	void CppCompilerEnvironment::optimizeSources() {
613 		std::string sOptimizerScript = DtaProject::getTargetScriptFilename(DtaProject::getInstance().getTargetLanguage(), "cppOptimizer.cwp");
614 		if (sOptimizerScript.empty()) return;
615 		CGCompiledTranslationScript script(sOptimizerScript);
616 		DtaScriptVariable parseTree(NULL, "parseTree");
617 		for (std::list<std::string>::const_iterator i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
618 			std::string sRadical  = _sCppProjectDirectory + *i;
619 			std::string sInputFile  = sRadical + ".cpp";
620 			std::string sOutputFile = sRadical + ".out";
621 			DtaScriptVariable* pLast = parseTree.pushItem(sRadical);
622 			script.translate(pLast, sInputFile, sOutputFile);
623 			if (pLast->getNode("implicit_copy") != NULL) parseTree.insertNode("implicit_copy")->setValue(true);
624 		}
625 		if (parseTree.getNode("implicit_copy") == NULL) parseTree.insertNode("explicit_copy")->setValue(true);
626 		const std::list<DtaScriptVariable*>* pList = parseTree.getArray();
627 		if (pList != NULL) {
628 			for (std::list<DtaScriptVariable*>::const_iterator i = pList->begin(); i != pList->end(); ++i) {
629 				std::string sRadical  = (*i)->getValue();
630 				std::string sInputFile  = sRadical + ".out";
631 				std::string sOutputFile = sRadical + ".out";
632 				DtaScriptVariable* pVariables = (*i)->getNode("variables");
633 				if ((pVariables != NULL) && (parseTree.getNode("explicit_copy") != NULL)) {
634 					const std::list<DtaScriptVariable*>* pVariablesList = pVariables->getArray();
635 					if (pVariablesList != NULL) {
636 						for (std::list<DtaScriptVariable*>::const_iterator j = pVariablesList->begin(); j != pVariablesList->end(); ++j) {
637 							if (CGRuntime::startString((*j)->getName(), "_compilerClauseImplicitCopy_")) {
638 								(*j)->insertNode("used")->setValue(false);
639 								(*j)->insertNode("active")->setValue(true);
640 							}
641 						}
642 					}
643 				}
644 				if (parseTree.getNode("explicit_copy") != NULL) (*i)->insertNode("explicit_copy")->setValue(true);
645 				if ((*i)->getNode("explicit_copy") != NULL) {
646 					script.translate(*i, sInputFile, sOutputFile);
647 				}
648 			}
649 		}
650 		for (std::list<std::string>::const_iterator i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
651 			std::string sRadical  = _sCppProjectDirectory + *i;
652 			std::string sInputFile  = sRadical + ".out";
653 			std::string sOutputFile = sRadical + ".cpp";
654 			DtaScriptVariable* pLast = parseTree.pushItem(sRadical);
655 			pLast->insertNode("rules")->setValue(true);
656 			script.translate(pLast, sInputFile, sOutputFile);
657 		}
658 	}
659 
translateToTargetLanguage(const std::string & sTargetLanguage)660 	void CppCompilerEnvironment::translateToTargetLanguage(const std::string& sTargetLanguage) {
661 		std::string sParserScript = DtaProject::getTargetScriptFilename(sTargetLanguage, "CWcpp-parser.cwp");
662 		if (sParserScript.empty()) throw UtlException("C++-to-" + sTargetLanguage + " translation error: unable to find the BNF-parse script \"CWcpp-parser.cwp\"");
663 		std::string sTranslatorScript = DtaProject::getTargetScriptFilename(sTargetLanguage, "CWcpp2" + sTargetLanguage + ".cws");
664 		if (sTranslatorScript.empty()) {
665 			if (sTargetLanguage == "cpp") return;
666 			throw UtlException("C++-to-" + sTargetLanguage + " translation error: unable to find the translation script \"CWcpp2" + sTargetLanguage + ".cws\"");
667 		}
668 		CGCompiledBNFScript parser(sParserScript);
669 		CGCompiledCommonScript translator;
670 		translator.buildFromFile(sTranslatorScript);
671 		DtaScriptVariable parseTree(NULL, "parseTree");
672 		for (std::list<std::string>::const_iterator i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
673 			std::string sCppFile = _sCppProjectDirectory + *i + ".cpp";
674 			parser.parse(&parseTree, sCppFile);
675 		}
676 		translator.execute(&parseTree);
677 	}
678 
getHeader() const679 	ScpStream& CppCompilerEnvironment::getHeader() const {
680 		DtaPatternScript* pScript = getCurrentScriptSession()._header;
681 		return *(pScript->getOutputStream());
682 	}
683 
getMainHeader() const684 	ScpStream& CppCompilerEnvironment::getMainHeader() const {
685 		DtaPatternScript* pScript = _listOfScriptSessions.back()._header;
686 		return *(pScript->getOutputStream());
687 	}
688 
getBody() const689 	ScpStream& CppCompilerEnvironment::getBody() const {
690 		DtaPatternScript* pScript = getCurrentScriptSession()._body;
691 		return *(pScript->getOutputStream());
692 	}
693 
filename2Module(const std::string & sFilename)694 	std::string CppCompilerEnvironment::filename2Module(const std::string& sFilename) {
695 		std::string sModule;
696 		std::string::size_type iIndex = sFilename.find('.');
697 		if (iIndex != std::string::npos) {
698 			sModule = sFilename.substr(0, iIndex) + '_' + filename2Module(sFilename.substr(iIndex + 1));
699 		} else sModule = sFilename;
700 		return sModule;
701 	}
702 
pushFilename(const std::string & sFilename)703 	bool CppCompilerEnvironment::pushFilename(const std::string& sFilename) {
704 		std::string sModule = filename2Module(sFilename);
705 		for (std::list<std::string>::const_iterator i = _listOfProjectModules.begin(); i != _listOfProjectModules.end(); i++) {
706 			if ((*i) == sModule) return false;
707 		}
708 		CppScriptSession session(sFilename, _sCppProjectDirectory + getRadical(sModule));
709 		_listOfScriptSessions.push_front(session);
710 		_listOfProjectModules.push_back(sModule);
711 		return true;
712 	}
713 
getRadical() const714 	std::string CppCompilerEnvironment::getRadical() const {
715 		return getRadical(getCurrentScriptSession()._sCppRadical);
716 	}
717 
getMainRadical() const718 	std::string CppCompilerEnvironment::getMainRadical() const {
719 		return getRadical(_listOfScriptSessions.back()._sCppRadical);
720 	}
721 
getRadical(const std::string & sFile)722 	std::string CppCompilerEnvironment::getRadical(const std::string& sFile) {
723 		std::string sRadical = sFile;
724 		std::string::size_type iIndex = sRadical.find_last_of("/\\");
725 		if (iIndex != std::string::npos) sRadical = sRadical.substr(iIndex + 1);
726 		iIndex = sRadical.find('.');
727 		if (iIndex != std::string::npos) sRadical = sRadical.substr(0, iIndex);
728 		return sRadical;
729 	}
730 
getRelativePath(const std::string & sFile)731 	std::string CppCompilerEnvironment::getRelativePath(const std::string& sFile) {
732 		std::string sRadical;
733 		std::string::size_type iIndex = sFile.find_last_of("/\\");
734 		if (iIndex != std::string::npos) sRadical = sFile.substr(iIndex + 1);
735 		else sRadical = sFile;
736 		return sRadical;
737 	}
738 
convertTemplateKey(const std::string & sKey)739 	std::string CppCompilerEnvironment::convertTemplateKey(const std::string& sKey) {
740 		std::string sText;
741 		for (std::string::size_type i = 0; i < sKey.size(); i++) {
742 			char a = sKey[i];
743 			if (((a >= 'A') && (a <= 'Z')) || ((a >= 'a') && (a <= 'z')) || ((a >= '0') && (a <= '9'))) sText += a;
744 			else switch(a) {
745 				case '+': sText += "_compilerPlus_";break;
746 				case '-': sText += "_compilerMinus_";break;
747 				case '.': sText += "_compilerDot_";break;
748 				case ',': sText += "_compilerComma_";break;
749 				default: sText += '_';
750 			}
751 		}
752 		return sText;
753 	}
754 
convertToCppVariable(const std::string & sVariable)755 	std::string CppCompilerEnvironment::convertToCppVariable(const std::string& sVariable) {
756 		if ((sVariable == "namespace") || (sVariable == "class")) return "_compilerCppVariable_" + sVariable;
757 		return sVariable;
758 	}
759 
getIncludeParentScript() const760 	std::string CppCompilerEnvironment::getIncludeParentScript() const {
761 		std::string sRadical;
762 		if (_listOfScriptSessions.front()._sFilename != _listOfScriptSessions.back()._sFilename) {
763 			std::list<CppScriptSession>::const_iterator cursor = _listOfScriptSessions.begin();
764 			++cursor;
765 			sRadical = filename2Module(cursor->_sFilename);
766 		}
767 		return sRadical;
768 	}
769 
incrementIndentation()770 	void CppCompilerEnvironment::incrementIndentation() {
771 		_listOfScriptSessions.front().incrementIndentation();
772 	}
773 
pushVariableScope()774 	void CppCompilerEnvironment::pushVariableScope() {
775 		_listOfScriptSessions.front().pushVariableScope();
776 	}
777 
newInlineScriptFilename()778 	std::string CppCompilerEnvironment::newInlineScriptFilename() {
779 		_iInlineScriptCounter++;
780 		char tcFile[80];
781 		sprintf(tcFile, "InlineScript2File_%d", _iInlineScriptCounter);
782 		return tcFile;
783 	}
784 
newFunction(const GrfFunction * pFunction)785 	void CppCompilerEnvironment::newFunction(const GrfFunction* pFunction) {
786 		_listOfScriptSessions.front()._setOfProjectFunctions.insert(pFunction->getFunctionName());
787 		_pCurrentFunction = pFunction;
788 	}
789 
newClause(const BNFClause * pClause)790 	void CppCompilerEnvironment::newClause(const BNFClause* pClause) {
791 		_listOfScriptSessions.front()._setOfProjectFunctions.insert(pClause->getName());
792 		_pCurrentClause = pClause;
793 	}
794 
getFunctionModule(const std::string & sFunction) const795 	std::string CppCompilerEnvironment::getFunctionModule(const std::string& sFunction) const {
796 		for (std::list<CppScriptSession>::const_iterator i = _listOfScriptSessions.begin(); i != _listOfScriptSessions.end(); i++) {
797 			if (i->_setOfProjectFunctions.find(sFunction) != i->_setOfProjectFunctions.end()) return i->_sCppRadical;
798 		}
799 		return _listOfScriptSessions.front()._sCppRadical;
800 	}
801 
getClauseModule(const std::string & sClause) const802 	std::string CppCompilerEnvironment::getClauseModule(const std::string& sClause) const {
803 		for (std::list<CppScriptSession>::const_iterator i = _listOfScriptSessions.begin(); i != _listOfScriptSessions.end(); i++) {
804 			if (i->_setOfProjectClauses.find(sClause) != i->_setOfProjectClauses.end()) return i->_sCppRadical;
805 		}
806 		return _listOfScriptSessions.front()._sCppRadical;
807 	}
808 
popVariableScope()809 	void CppCompilerEnvironment::popVariableScope() {
810 		_listOfScriptSessions.front().popVariableScope();
811 	}
812 
addVariable(const std::string & sVariable)813 	bool CppCompilerEnvironment::addVariable(const std::string& sVariable) {
814 		return _listOfScriptSessions.front()._stackOfScopes.front()->addVariable(sVariable);
815 	}
816 
existVariable(const std::string & sVariable) const817 	bool CppCompilerEnvironment::existVariable(const std::string& sVariable) const {
818 		return _listOfScriptSessions.front()._stackOfScopes.front()->existVariable(sVariable) | (_globalVariables.find(sVariable) != _globalVariables.end());
819 	}
820 
addGlobalVariable(const std::string & sVariable)821 	void CppCompilerEnvironment::addGlobalVariable(const std::string& sVariable) {
822 		_globalVariables.insert(sVariable);
823 	}
824 
setClauseReturnValue(const std::string & sClauseName)825 	void CppCompilerEnvironment::setClauseReturnValue(const std::string& sClauseName) {
826 		_listOfScriptSessions.front()._stackOfScopes.front()->setClauseReturnValue(sClauseName);
827 	}
828 
isClauseReturnValue(const std::string & sVariableName) const829 	bool CppCompilerEnvironment::isClauseReturnValue(const std::string& sVariableName) const {
830 		return _listOfScriptSessions.front()._stackOfScopes.front()->isClauseReturnValue(sVariableName);
831 	}
832 
hasEvaluatedExpressionInScope(bool bEvaluated)833 	void CppCompilerEnvironment::hasEvaluatedExpressionInScope(bool bEvaluated) {
834 		_listOfScriptSessions.front()._stackOfScopes.front()->hasEvaluatedExpressionInScope(bEvaluated);
835 	}
836 
hasEvaluatedExpressionInScope() const837 	bool CppCompilerEnvironment::hasEvaluatedExpressionInScope() const {
838 		return _listOfScriptSessions.front()._stackOfScopes.front()->hasEvaluatedExpressionInScope();
839 	}
840 
newSwitch()841 	int CppCompilerEnvironment::newSwitch() {
842 		_iSwitchNumber++;
843 		return _iSwitchNumber;
844 	}
845 
newCursor()846 	int CppCompilerEnvironment::newCursor() {
847 		_iCursorNumber++;
848 		return _iCursorNumber;
849 	}
850 
decrementIndentation()851 	void CppCompilerEnvironment::decrementIndentation() {
852 		_listOfScriptSessions.front().decrementIndentation();
853 	}
854 
pushForeach(GrfForeach * pForeach)855 	void CppCompilerEnvironment::pushForeach(GrfForeach* pForeach) {
856 		_listOfScriptSessions.front().pushForeach(pForeach);
857 	}
858 
getLastForeach() const859 	GrfForeach* CppCompilerEnvironment::getLastForeach() const {
860 		return _listOfScriptSessions.front().getLastForeach();
861 	}
862 
popForeach()863 	void CppCompilerEnvironment::popForeach() {
864 		_listOfScriptSessions.front().popForeach();
865 	}
866 
catchFilename(UtlException & exception)867 	void CppCompilerEnvironment::catchFilename(UtlException& exception) {
868 		_listOfScriptSessions.front().catchFilename();
869 		_bErrorEncountered = true;
870 		throw UtlException(exception.getTraceStack(), exception.getMessage());
871 	}
872 
popFilename()873 	void CppCompilerEnvironment::popFilename() {
874 		_listOfScriptSessions.pop_front();
875 	}
876 }
877 //##markup##"build C++ headers"
878