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 #pragma warning (disable : 4503)
25 #endif
26 
27 #include "ScpStream.h"
28 #include "UtlException.h"
29 #include "UtlTrace.h"
30 #include "UtlTimer.h"
31 
32 #include "CGRuntime.h"
33 #include "DtaScript.h"
34 #include "DtaBNFScript.h"
35 #include "DtaPatternScript.h"
36 #include "DtaProject.h"
37 
38 namespace CodeWorker {
39 
40 	class DtaCustomTagsHandler {
41 	public:
42 		DtaBNFScript* _pReader;
43 		DtaPatternScript* _pWriter;
44 
DtaCustomTagsHandler(DtaBNFScript * pReader,DtaPatternScript * pWriter)45 		inline DtaCustomTagsHandler(DtaBNFScript* pReader, DtaPatternScript* pWriter) : _pReader(pReader), _pWriter(pWriter) {}
46 	};
47 
48 
49 	class DtaGlobalVariableData {
50 	public:
51 		DtaScriptVariable* _variableNode;
52 		EXPRESSION_TYPE _variableType;
53 
DtaGlobalVariableData(DtaScriptVariable * variableNode,EXPRESSION_TYPE variableType)54 		inline DtaGlobalVariableData(DtaScriptVariable* variableNode, EXPRESSION_TYPE variableType) : _variableNode(variableNode), _variableType(variableType) {}
DtaGlobalVariableData(EXPRESSION_TYPE variableType)55 		inline DtaGlobalVariableData(EXPRESSION_TYPE variableType) : _variableNode(NULL), _variableType(variableType) {}
~DtaGlobalVariableData()56 		~DtaGlobalVariableData() { delete _variableNode; }
57 	};
58 
59 
60 	DtaProject* DtaProject::_pInstance = NULL;
61 	std::list<DtaProject*> DtaProject::_stackOfProjects;
62 
DtaProject()63 	DtaProject::DtaProject() :	DtaScriptVariable(NULL, "project"), _pScript(NULL), _bVerbose(false),
64 								_pCommonAlienParser(NULL), _pBNFAlienParser(NULL),
65 								_pTemplateAlienParser(NULL), _pTranslationAlienParser(NULL),
66 								_sCommentBegin("//"), _sCommentEnd("\n"),
67 								_pDelayTimer(NULL), _dLastDelay(0.0),
68 								_pReadonlyHook(NULL), _pWritefileHook(NULL),
69 								iRemoteDebugPort_(0)
70 	{
71 		if (_pInstance != NULL) {
72 			_stackOfProjects.push_back(_pInstance);
73 			copyCommon(*_pInstance);
74 		} else {
75 #ifdef WIN32
76 			_iTextMode = DOS_MODE;
77 #else
78 			_iTextMode = UNIX_MODE;
79 #endif
80 		}
81 		_pInstance = this;
82 	}
83 
~DtaProject()84 	DtaProject::~DtaProject() {
85 		for (std::map<std::string, DtaGlobalVariableData*>::const_iterator i = _mapOfGlobalVariables.begin(); i != _mapOfGlobalVariables.end(); i++) {
86 			delete i->second;
87 		}
88 		for (std::map<std::string, DtaCustomTagsHandler*>::const_iterator j = _mapOfGenerationTagsHandlers.begin(); j != _mapOfGenerationTagsHandlers.end(); ++j) {
89 			delete j->second;
90 		}
91 		if (_stackOfProjects.empty()) {
92 			_pInstance = NULL;
93 		} else {
94 			_pInstance = _stackOfProjects.back();
95 			_stackOfProjects.pop_back();
96 			_pInstance->copyCommon(*this);
97 		}
98 	}
99 
reset()100 	void DtaProject::reset() {
101 		for (std::map<std::string, DtaGlobalVariableData*>::const_iterator i = _mapOfGlobalVariables.begin(); i != _mapOfGlobalVariables.end(); i++) {
102 			delete i->second;
103 		}
104 		_mapOfGlobalVariables = std::map<std::string, DtaGlobalVariableData*>();
105 		_sCommentBegin = "//";
106 		_sCommentEnd = "\n";
107 		_pScript = NULL;
108 		_pDelayTimer = NULL;
109 		_dLastDelay = 0.0;
110 		_pReadonlyHook = NULL;
111 		_pWritefileHook = NULL;
112 		_bVerbose = false;
113 		_sTargetLanguage = "";
114 		for (std::map<std::string, DtaCustomTagsHandler*>::const_iterator j = _mapOfGenerationTagsHandlers.begin(); j != _mapOfGenerationTagsHandlers.end(); ++j) {
115 			delete j->second;
116 		}
117 		_mapOfGenerationTagsHandlers = std::map<std::string, DtaCustomTagsHandler*>();
118 		_sCurrentGenerationTagsHandler = "";
119 		_mapOfCapturedOutputFiles = std::map<std::string, std::set<std::string> >();
120 		_mapOfCapturedInputFiles = std::map<std::string, std::set<std::string> >();
121 	}
122 
createRootInstance()123 	DtaProject& DtaProject::createRootInstance() {
124 		if (!existInstance()) new DtaProject;
125 		return getInstance();
126 	}
127 
setCodeWorkerHome(const std::string & sPath)128 	void DtaProject::setCodeWorkerHome(const std::string& sPath) {
129 		_sCodeWorkerHome = CGRuntime::canonizePath(sPath);
130 		if (!_sCodeWorkerHome.empty()) {
131 			char c = _sCodeWorkerHome[_sCodeWorkerHome.size() - 1];
132 			if ((c != '\\') && (c != '/')) _sCodeWorkerHome += "/";
133 		}
134 	}
135 
setFinalInfo(const std::string & sOutputFilename,int iFlag)136 	void DtaProject::setFinalInfo(const std::string& sOutputFilename, int iFlag) {
137 		sFinalInfoOutputFilename_ = sOutputFilename;
138 		iFinalInfoFlag_ = iFlag;
139 	}
140 
setRemoteDebug(const std::string & sHost,int iPort)141 	void DtaProject::setRemoteDebug(const std::string& sHost, int iPort) {
142 		sRemoteDebugHost_ = sHost;
143 		iRemoteDebugPort_ = iPort;
144 	}
145 
getTargetScriptFilename(const std::string & sTargetLanguage,const std::string & sScriptShortFilename)146 	std::string DtaProject::getTargetScriptFilename(const std::string& sTargetLanguage, const std::string& sScriptShortFilename) {
147 		std::string sFile;
148 		std::string sCodeWorkerHome = getInstance().getCodeWorkerHome();
149 		if (!sTargetLanguage.empty()) {
150 			sFile = sCodeWorkerHome + sTargetLanguage + "/user-scripts/" + sScriptShortFilename;
151 			if (CGRuntime::existFile(sFile)) return sFile;
152 			sFile = sCodeWorkerHome + sTargetLanguage + "/default-scripts/" + sScriptShortFilename;
153 			if (CGRuntime::existFile(sFile)) return sFile;
154 		}
155 		sFile = sCodeWorkerHome + "cpp/user-scripts/" + sScriptShortFilename;
156 		if (CGRuntime::existFile(sFile)) return sFile;
157 		sFile = sCodeWorkerHome + "cpp/default-scripts/" + sScriptShortFilename;
158 		if (CGRuntime::existFile(sFile)) return sFile;
159 		return "";
160 	}
161 
getCommonAlienParser() const162 	DtaBNFScript* DtaProject::getCommonAlienParser() const {
163 		if (_pCommonAlienParser == NULL) {
164 			if (!_sTargetLanguage.empty()) {
165 				std::string sScriptFile = getTargetScriptFilename(_sTargetLanguage, _sTargetLanguage + "CommonScript.cwp");
166 				if (sScriptFile.empty()) {
167 					throw UtlException("compiling a common script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "CommonScript.cwp\"");
168 				}
169 				std::auto_ptr<DtaBNFScript> pScript(new DtaBNFScript);
170 				pScript->parseFile(sScriptFile.c_str());
171 				_pCommonAlienParser = pScript.release();
172 			}
173 		}
174 		return _pCommonAlienParser;
175 	}
176 
getBNFAlienParser() const177 	DtaBNFScript* DtaProject::getBNFAlienParser() const {
178 		if (_pBNFAlienParser == NULL) {
179 			if (!_sTargetLanguage.empty()) {
180 				std::string sScriptFile = getTargetScriptFilename(_sTargetLanguage, _sTargetLanguage + "BNFScript.cwp");
181 				if (sScriptFile.empty()) {
182 					throw UtlException("compiling a BNF script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "BNFScript.cwp\"");
183 				}
184 				std::auto_ptr<DtaBNFScript> pScript(new DtaBNFScript);
185 				pScript->parseFile(sScriptFile.c_str());
186 				_pBNFAlienParser = pScript.release();
187 			}
188 		}
189 		return _pBNFAlienParser;
190 	}
191 
getTemplateAlienParser() const192 	DtaBNFScript* DtaProject::getTemplateAlienParser() const {
193 		if (_pTemplateAlienParser == NULL) {
194 			if (!_sTargetLanguage.empty()) {
195 				std::string sScriptFile = getTargetScriptFilename(_sTargetLanguage, _sTargetLanguage + "TemplateScript.cwp");
196 				if (sScriptFile.empty()) {
197 					throw UtlException("compiling a template script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "TemplateScript.cwp\"");
198 				}
199 				std::auto_ptr<DtaBNFScript> pScript(new DtaBNFScript);
200 				pScript->parseFile(sScriptFile.c_str());
201 				_pTemplateAlienParser = pScript.release();
202 			}
203 		}
204 		return _pTemplateAlienParser;
205 	}
206 
getTranslationAlienParser() const207 	DtaBNFScript* DtaProject::getTranslationAlienParser() const {
208 		if (_pTranslationAlienParser == NULL) {
209 			if (!_sTargetLanguage.empty()) {
210 				std::string sScriptFile = getTargetScriptFilename(_sTargetLanguage, _sTargetLanguage + "TranslationScript.cwp");
211 				if (sScriptFile.empty()) {
212 					throw UtlException("compiling a translation script in " + _sTargetLanguage + " requires \"($CODEWORKER_HOME)/" + _sTargetLanguage + "/default-scripts/" + _sTargetLanguage + "TranslationScript.cwp\"");
213 				}
214 				std::auto_ptr<DtaBNFScript> pScript(new DtaBNFScript);
215 				pScript->parseFile(sScriptFile.c_str());
216 				_pTranslationAlienParser = pScript.release();
217 			}
218 		}
219 		return _pTranslationAlienParser;
220 	}
221 
getDefineTarget(const std::string & sTarget) const222 	const std::string& DtaProject::getDefineTarget(const std::string& sTarget) const {
223 		std::map<std::string, std::string>::const_iterator i = _mapOfDefinedTargets.find(sTarget);
224 		if (i != _mapOfDefinedTargets.end()) return i->second;
225 		return ((DtaProject*) this)->_mapOfDefinedTargets[""];
226 	}
227 
setDefineTarget(const std::string & sTarget,const std::string & sValue)228 	void DtaProject::setDefineTarget(const std::string& sTarget, const std::string& sValue) {
229 		if (sTarget.empty()) throw UtlException("empty property '=\"" + sValue + "\"' is forbidden");
230 		_mapOfDefinedTargets[sTarget] = sValue;
231 	}
232 
getGlobalVariable(const std::string & sName) const233 	DtaScriptVariable* DtaProject::getGlobalVariable(const std::string& sName) const {
234 		std::map<std::string, DtaGlobalVariableData*>::const_iterator cursor = _mapOfGlobalVariables.find(sName);
235 		if (cursor == _mapOfGlobalVariables.end()) return NULL;
236 		return cursor->second->_variableNode;
237 	}
238 
getGlobalVariableType(const std::string & sName) const239 	EXPRESSION_TYPE DtaProject::getGlobalVariableType(const std::string& sName) const {
240 		std::map<std::string, DtaGlobalVariableData*>::const_iterator cursor = _mapOfGlobalVariables.find(sName);
241 		if (cursor == _mapOfGlobalVariables.end()) {
242 			if ((sName == "_ARGS") || (sName == "_REQUEST")) return NODE_EXPRTYPE;
243 			return UNKNOWN_EXPRTYPE;
244 		}
245 		return cursor->second->_variableType;
246 	}
247 
setGlobalVariable(const std::string & sName,EXPRESSION_TYPE variableType)248 	DtaScriptVariable* DtaProject::setGlobalVariable(const std::string& sName, EXPRESSION_TYPE variableType) {
249 		DtaScriptVariable* pGlobalVariable;
250 		std::map<std::string, DtaGlobalVariableData*>::const_iterator cursor = _mapOfGlobalVariables.find(sName);
251 		if (cursor != _mapOfGlobalVariables.end()) {
252 			pGlobalVariable = cursor->second->_variableNode;
253 			if (pGlobalVariable == NULL) {
254 				pGlobalVariable = new DtaScriptVariable(NULL, sName);
255 				cursor->second->_variableNode = pGlobalVariable;
256 			} else {
257 				pGlobalVariable->clearContent();
258 			}
259 		} else {
260 			pGlobalVariable = new DtaScriptVariable(NULL, sName);
261 			_mapOfGlobalVariables[sName] = new DtaGlobalVariableData(pGlobalVariable, variableType);
262 		}
263 		return pGlobalVariable;
264 	}
265 
setGlobalVariableType(const std::string & sName,EXPRESSION_TYPE variableType)266 	void DtaProject::setGlobalVariableType(const std::string& sName, EXPRESSION_TYPE variableType) {
267 		std::map<std::string, DtaGlobalVariableData*>::const_iterator cursor = _mapOfGlobalVariables.find(sName);
268 		if (cursor != _mapOfGlobalVariables.end()) {
269 			cursor->second->_variableType = variableType;
270 		} else {
271 			_mapOfGlobalVariables[sName] = new DtaGlobalVariableData(NULL, variableType);
272 		}
273 	}
274 
setTextMode(TEXT_MODE iTextMode)275 	void DtaProject::setTextMode(TEXT_MODE iTextMode) {
276 		_iTextMode = iTextMode;
277 		if (iTextMode == DOS_MODE) {
278 			if (strcmp(ScpStream::ENDL.c_str(), "\r\n") != 0) ScpStream::ENDL = "\r\n";
279 		} else {
280 			if (strcmp(ScpStream::ENDL.c_str(), "\n") != 0) ScpStream::ENDL = "\n";
281 		}
282 	}
283 
getLastDelay() const284 	double DtaProject::getLastDelay() const {
285 		if (_pDelayTimer != NULL) return _pDelayTimer->getTimeInSec();
286 		return _dLastDelay;
287 	}
288 
copyCommon(const DtaProject & project)289 	void DtaProject::copyCommon(const DtaProject& project) {
290 		_pScript = project._pScript;
291 		_bVerbose = project._bVerbose;
292 		_sVersion = project._sVersion;
293 		_sMarkupKey = project._sMarkupKey;
294 		_sMarkupValue = project._sMarkupValue;
295 		_sWorkingPath = project._sWorkingPath;
296 		_mapOfDefinedTargets = project._mapOfDefinedTargets;
297 		_sCommentBegin = project._sCommentBegin;
298 		_sCommentEnd = project._sCommentEnd;
299 		_sGenerationHeader = project._sGenerationHeader;
300 		_mapOfWarnings = project._mapOfWarnings;
301 		_pReadonlyHook = project._pReadonlyHook;
302 		_pWritefileHook = project._pWritefileHook;
303 		_bSpeed = project._bSpeed;
304 		_iTextMode = project._iTextMode;
305 		_sCurrentGenerationTagsHandler = project._sCurrentGenerationTagsHandler;
306 	}
307 
getTraceStack(ScpStream & script) const308 	std::string DtaProject::getTraceStack(ScpStream& script) const {
309 		std::string sStack = UtlTrace::getTraceStack();
310 		const char* tcFilename = getScript()->getFilenamePtr();
311 		if (tcFilename != NULL) {
312 			sStack += tcFilename;
313 		}
314 		char tcNumber[16];
315 		sprintf(tcNumber, "(%d)", script.getLineCount());
316 		sStack += tcNumber;
317 		return sStack;
318 	}
319 
traceEngine() const320 	void DtaProject::traceEngine() const {
321 		if (_pScript != NULL) {
322 			_pScript->traceEngine();
323 		}
324 	}
325 
prepareExecution()326 	void DtaProject::prepareExecution() {
327 		_mapOfWarnings = std::map<std::string, int>();
328 	}
329 
addWarning(const std::string & sWarning)330 	int DtaProject::addWarning(const std::string& sWarning) {
331 		int& iCounter = _mapOfWarnings[sWarning];
332 		iCounter++;
333 		return iCounter;
334 	}
335 
isScriptVersionOlderThan(int * tiVersion) const336 	bool DtaProject::isScriptVersionOlderThan(int* tiVersion) const {
337 		return true;
338 	}
339 
addGenerationTagsHandler(const std::string & sKey,DtaBNFScript * pReader,DtaPatternScript * pWriter)340 	bool DtaProject::addGenerationTagsHandler(const std::string& sKey, DtaBNFScript* pReader, DtaPatternScript* pWriter) {
341 		if (_mapOfGenerationTagsHandlers.find(sKey) != _mapOfGenerationTagsHandlers.end()) return false;
342 		_mapOfGenerationTagsHandlers[sKey] = new DtaCustomTagsHandler(pReader, pWriter);
343 		return true;
344 	}
345 
removeGenerationTagsHandler(const std::string & sKey)346 	bool DtaProject::removeGenerationTagsHandler(const std::string& sKey) {
347 		std::map<std::string, DtaCustomTagsHandler*>::iterator cursor = _mapOfGenerationTagsHandlers.find(sKey);
348 		if (cursor == _mapOfGenerationTagsHandlers.end()) return false;
349 		_mapOfGenerationTagsHandlers.erase(cursor);
350 		if (_sCurrentGenerationTagsHandler == sKey) _sCurrentGenerationTagsHandler = "";
351 		return true;
352 	}
353 
selectGenerationTagsHandler(const std::string & sKey)354 	bool DtaProject::selectGenerationTagsHandler(const std::string& sKey) {
355 		std::map<std::string, DtaCustomTagsHandler*>::const_iterator cursor = _mapOfGenerationTagsHandlers.find(sKey);
356 		if (cursor == _mapOfGenerationTagsHandlers.end()) return false;
357 		_sCurrentGenerationTagsHandler = sKey;
358 		return true;
359 	}
360 
existGenerationTagsHandler(const std::string & sKey) const361 	bool DtaProject::existGenerationTagsHandler(const std::string& sKey) const {
362 		std::map<std::string, DtaCustomTagsHandler*>::const_iterator cursor = _mapOfGenerationTagsHandlers.find(sKey);
363 		return (cursor != _mapOfGenerationTagsHandlers.end());
364 	}
365 
getGenerationTagsHandler(const std::string & sKey,DtaBNFScript * & pReader,DtaPatternScript * & pWriter) const366 	bool DtaProject::getGenerationTagsHandler(const std::string& sKey, DtaBNFScript*& pReader, DtaPatternScript*& pWriter) const {
367 		std::map<std::string, DtaCustomTagsHandler*>::const_iterator cursor = _mapOfGenerationTagsHandlers.find(sKey);
368 		if (cursor == _mapOfGenerationTagsHandlers.end()) return false;
369 		pReader = cursor->second->_pReader;
370 		pWriter = cursor->second->_pWriter;
371 		return true;
372 	}
373 
captureOutputFile(const char * tcOutputFile,const char * tcTemplateScript)374 	void DtaProject::captureOutputFile(const char* tcOutputFile, const char* tcTemplateScript) {
375 		_mapOfCapturedOutputFiles[tcOutputFile].insert(tcTemplateScript);
376 	}
377 
captureInputFile(const char * tcInputFile,const char * tcBNFScript)378 	void DtaProject::captureInputFile(const char* tcInputFile, const char* tcBNFScript) {
379 		_mapOfCapturedInputFiles[tcInputFile].insert(tcBNFScript);
380 	}
381 }
382