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