1 /* "CodeWorker": a scripting language for parsing and generating text. 2 3 Copyright (C) 1996-1997, 1999-2003 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 # include <windows.h> 25 #else 26 # include <dlfcn.h> 27 #endif 28 29 #include "ScpStream.h" 30 #include "UtlException.h" 31 #include "UtlTrace.h" 32 33 #include "DtaScriptVariable.h" 34 #include "ExprScriptVariable.h" 35 #include "CppCompilerEnvironment.h" 36 #include "CGRuntime.h" // CGRuntime::toString(double) 37 38 #include "DynFunction.h" 39 #include "DynPackage.h" 40 41 namespace CodeWorker { 42 std::map<std::string, DynPackage*> DynPackage::_packages; 43 44 //-------------------------------------------------------------------------------- 45 // Callbacks 46 //-------------------------------------------------------------------------------- 47 typedef DtaScriptVariable Tree; 48 typedef ExprScriptFunction Function; 49 50 class ExternalValueNode; 51 52 53 /** class 'Parameter2CW' 54 * Type of parameters to pass to the interpreter when calling a CodeWorker's 55 * function. See Interpreter::callFunction(...). 56 **/ 57 class Parameter2CW { 58 private: 59 bool _bValue; 60 union PARAMETER2CW_TYPE { 61 const char* _tcValue; 62 Tree* _pNode; 63 }; 64 PARAMETER2CW_TYPE _param; 65 66 public: Parameter2CW(const char * tcValue)67 inline Parameter2CW(const char* tcValue) : _bValue(true) { _param._tcValue = tcValue; } Parameter2CW(Tree * pNode)68 inline Parameter2CW(Tree* pNode) : _bValue(false) { _param._pNode = pNode; } 69 isValue() const70 inline bool isValue() const { return _bValue; } 71 getValue() const72 inline const char* getValue() const { return ((_bValue) ? _param._tcValue : NULL); } getNode() const73 inline Tree* getNode() const { return ((_bValue) ? NULL : _param._pNode); } 74 }; 75 76 77 typedef bool (*CREATE_COMMAND0)(DynPackage*, const char*); 78 typedef bool (*CREATE_COMMAND1)(DynPackage*, const char*, bool); 79 typedef bool (*CREATE_COMMAND2)(DynPackage*, const char*, bool, bool); 80 typedef bool (*CREATE_COMMAND3)(DynPackage*, const char*, bool, bool, bool); 81 typedef bool (*CREATE_COMMAND4)(DynPackage*, const char*, bool, bool, bool, bool); 82 typedef bool (*CREATE_COMMANDN)(DynPackage*, const char*, int, int*); 83 typedef Tree* (*CREATE_VARIABLE)(DynPackage*, const char*); 84 typedef void (*ERROR_COMMAND)(const char*); 85 typedef const char* (*COPY_LOCAL_STRING)(Interpreter*, const char*); 86 typedef const char* (*COPY_LOCAL_BOOLEAN)(Interpreter* pInterpreter, bool); 87 typedef const char* (*COPY_LOCAL_INT)(Interpreter* pInterpreter, int); 88 typedef const char* (*COPY_LOCAL_DOUBLE)(Interpreter* pInterpreter, double); 89 90 typedef Tree* (*CREATE_TREE)(const char*); 91 typedef const char* (*GET_VALUE)(Tree*); 92 typedef int (*GET_INT_VALUE)(Tree*); 93 typedef double (*GET_DOUBLE_VALUE)(Tree*); 94 typedef bool (*GET_BOOLEAN_VALUE)(Tree*); 95 typedef ExternalValueNode* (*GET_EXTERNAL_VALUE)(Tree*); 96 typedef void (*SET_VALUE)(Tree*, const char*); 97 typedef void (*SET_EXTERNAL_VALUE)(Tree*, ExternalValueNode*); 98 typedef void (*SET_INT_VALUE)(Tree*, int); 99 typedef void (*SET_DOUBLE_VALUE)(Tree*, double); 100 typedef void (*SET_BOOLEAN_VALUE)(Tree*, bool); 101 typedef Tree* (*NEXT_NODE)(Tree*, const char*); 102 typedef Tree* (*INSERT_NODE)(Tree*, const char*); 103 typedef void (*CLEAR_NODE)(Tree*); 104 typedef int (*SIZE_ARRAY)(Tree*); 105 typedef int (*ALL_KEYS)(Tree*, const char**); 106 typedef int (*ALL_VALUES)(Tree*, const char**); 107 typedef Tree* (*GET_ITEM_FROM_KEY)(Tree*, const char*); 108 typedef Tree* (*GET_ITEM_FROM_POS)(Tree*, int); 109 typedef const char* (*GET_ITEM_KEY)(Tree*, int); 110 typedef Tree* (*PUSH_ITEM)(Tree*, const char*); 111 typedef Tree* (*INSERT_ITEM)(Tree*, const char*, const char*); 112 113 typedef Function* (*FIND_FUNCTION)(Interpreter*, const char*); 114 115 typedef const char* (*CALL_FUNCTION0)(Interpreter* pInterpreter, Function*); 116 typedef const char* (*CALL_FUNCTION1)(Interpreter* pInterpreter, Function*, Parameter2CW); 117 typedef const char* (*CALL_FUNCTION2)(Interpreter* pInterpreter, Function*, Parameter2CW, Parameter2CW); 118 typedef const char* (*CALL_FUNCTION3)(Interpreter* pInterpreter, Function*, Parameter2CW, Parameter2CW, Parameter2CW); 119 typedef const char* (*CALL_FUNCTION4)(Interpreter* pInterpreter, Function*, Parameter2CW, Parameter2CW, Parameter2CW, Parameter2CW); 120 121 typedef void (*RELEASE_FUNCTION)(Function*); 122 pfCreateCommand0(DynPackage * pPackage,const char * tcName)123 bool pfCreateCommand0(DynPackage* pPackage, const char* tcName) { 124 return pPackage->addFunction(tcName); 125 } 126 pfCreateCommand1(DynPackage * pPackage,const char * tcName,bool bIsP1Node)127 bool pfCreateCommand1(DynPackage* pPackage, const char* tcName, bool bIsP1Node) { 128 return pPackage->addFunction(tcName, bIsP1Node); 129 } 130 pfCreateCommand2(DynPackage * pPackage,const char * tcName,bool bIsP1Node,bool bIsP2Node)131 bool pfCreateCommand2(DynPackage* pPackage, const char* tcName, bool bIsP1Node, bool bIsP2Node) { 132 return pPackage->addFunction(tcName, bIsP1Node, bIsP2Node); 133 } 134 pfCreateCommand3(DynPackage * pPackage,const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node)135 bool pfCreateCommand3(DynPackage* pPackage, const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node) { 136 return pPackage->addFunction(tcName, bIsP1Node, bIsP2Node, bIsP3Node); 137 } 138 pfCreateCommand4(DynPackage * pPackage,const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node,bool bIsP4Node)139 bool pfCreateCommand4(DynPackage* pPackage, const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node, bool bIsP4Node) { 140 return pPackage->addFunction(tcName, bIsP1Node, bIsP2Node, bIsP3Node, bIsP4Node); 141 } 142 pfCreateCommandN(DynPackage * pPackage,const char * tcName,int iNbParams,int * tbNodeParams)143 bool pfCreateCommandN(DynPackage* pPackage, const char* tcName, int iNbParams, int* tbNodeParams) { 144 return pPackage->addFunction(tcName, iNbParams, tbNodeParams); 145 } 146 pfCreateVariable(DynPackage * pPackage,const char * tcName)147 Tree* pfCreateVariable(DynPackage* pPackage, const char* tcName) { 148 return pPackage->addVariable(tcName); 149 } 150 pfError(const char * tcError)151 void pfError(const char* tcError) { 152 throw UtlException(tcError); 153 } 154 155 const char* pfCopyLocalString(Interpreter* pInterpreter, const char* tcText); 156 const char* pfCopyLocalBoolean(Interpreter* pInterpreter, bool bValue); 157 const char* pfCopyLocalDouble(Interpreter* pInterpreter, double dValue); 158 const char* pfCopyLocalInt(Interpreter* pInterpreter, int iValue); 159 160 pfCreateTree(const char * tcName)161 Tree* pfCreateTree(const char* tcName) { 162 return new Tree(NULL, tcName); 163 } 164 pfGetValue(Tree * pNode)165 const char* pfGetValue(Tree* pNode) { 166 return pNode->getValue(); 167 } 168 pfGetIntValue(Tree * pNode)169 int pfGetIntValue(Tree* pNode) { 170 return pNode->getIntValue(); 171 } 172 pfGetDoubleValue(Tree * pNode)173 double pfGetDoubleValue(Tree* pNode) { 174 return pNode->getDoubleValue(); 175 } 176 pfGetBooleanValue(Tree * pNode)177 bool pfGetBooleanValue(Tree* pNode) { 178 return pNode->getBooleanValue(); 179 } 180 pfGetExternalValue(Tree * pNode)181 ExternalValueNode* pfGetExternalValue(Tree* pNode) { 182 return pNode->getExternalValueNode(); 183 } 184 pfSetValue(Tree * pNode,const char * tcValue)185 void pfSetValue(Tree* pNode, const char* tcValue) { 186 pNode->setValue(tcValue); 187 } 188 pfSetExternalValue(Tree * pNode,ExternalValueNode * pValue)189 void pfSetExternalValue(Tree* pNode, ExternalValueNode* pValue) { 190 pNode->setValue(pValue); 191 } 192 pfSetIntValue(Tree * pNode,int iValue)193 void pfSetIntValue(Tree* pNode, int iValue) { 194 pNode->setValue(iValue); 195 } 196 pfSetDoubleValue(Tree * pNode,double dValue)197 void pfSetDoubleValue(Tree* pNode, double dValue) { 198 pNode->setValue(dValue); 199 } 200 pfSetBooleanValue(Tree * pNode,bool bValue)201 void pfSetBooleanValue(Tree* pNode, bool bValue) { 202 pNode->setValue(bValue); 203 } 204 pfNextNode(Tree * pNode,const char * tcAttribute)205 Tree* pfNextNode(Tree* pNode, const char* tcAttribute) { 206 return pNode->getNode(tcAttribute); 207 } 208 pfInsertNode(Tree * pNode,const char * tcAttribute)209 Tree* pfInsertNode(Tree* pNode, const char* tcAttribute) { 210 return pNode->insertNode(tcAttribute); 211 } 212 pfClearNode(Tree * pNode)213 void pfClearNode(Tree* pNode) { 214 pNode->clearContent(); 215 } 216 pfSizeArray(Tree * pArray)217 int pfSizeArray(Tree* pArray) { 218 return pArray->getArraySize(); 219 } 220 pfAllKeys(Tree * pArray,const char ** tcKeys)221 int pfAllKeys(Tree* pArray, const char** tcKeys) { 222 const std::list<DtaScriptVariable*>* pArrayList = pArray->getArray(); 223 if (pArrayList == NULL) return 0; 224 int iIndex = 0; 225 for (std::list<DtaScriptVariable*>::const_iterator i = pArrayList->begin(); i != pArrayList->end(); i++) { 226 tcKeys[iIndex++] = (*i)->getName(); 227 } 228 return iIndex; 229 } 230 pfAllValues(Tree * pArray,const char ** tcValues)231 int pfAllValues(Tree* pArray, const char** tcValues) { 232 const std::list<DtaScriptVariable*>* pArrayList = pArray->getArray(); 233 if (pArrayList == NULL) return 0; 234 int iIndex = 0; 235 for (std::list<DtaScriptVariable*>::const_iterator i = pArrayList->begin(); i != pArrayList->end(); i++) { 236 tcValues[iIndex++] = (*i)->getValue(); 237 } 238 return iIndex; 239 } 240 pfGetItemFromKey(Tree * pArray,const char * tcKey)241 Tree* pfGetItemFromKey(Tree* pArray, const char* tcKey) { 242 return pArray->getArrayElement(tcKey); 243 } 244 pfGetItemFromPos(Tree * pArray,int iKey)245 Tree* pfGetItemFromPos(Tree* pArray, int iKey) { 246 return pArray->getArrayElement(iKey); 247 } 248 pfGetItemKey(Tree * pArray,int iKey)249 const char* pfGetItemKey(Tree* pArray, int iKey) { 250 DtaScriptVariable* pItem = pArray->getArrayElement(iKey); 251 if (pItem == NULL) return NULL; 252 return pItem->getName(); 253 } 254 pfPushItem(Tree * pArray,const char * tcValue)255 Tree* pfPushItem(Tree* pArray, const char* tcValue) { 256 if (tcValue == NULL) return pArray->pushItem(""); 257 return pArray->pushItem(tcValue); 258 } 259 pfInsertItem(Tree * pArray,const char * tcKey,const char * tcValue)260 Tree* pfInsertItem(Tree* pArray, const char* tcKey, const char* tcValue) { 261 DtaScriptVariable* pItem = pArray->addElement(tcKey); 262 if (tcValue != NULL) pItem->setValue(tcValue); 263 return pItem; 264 } 265 266 Function* pfFindFunction(Interpreter* pInterpreter, const char* sFunctionName); 267 268 const char* pfCallFunction0(Interpreter* pInterpreter, Function* pFunction); 269 const char* pfCallFunction1(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1); 270 const char* pfCallFunction2(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2); 271 const char* pfCallFunction3(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2, Parameter2CW p3); 272 const char* pfCallFunction4(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2, Parameter2CW p3, Parameter2CW p4); 273 pfReleaseFunction(Function * pFunction)274 void pfReleaseFunction(Function* pFunction) { 275 delete pFunction; 276 } 277 278 279 280 //-------------------------------------------------------------------------------- 281 // Interpreter 282 //-------------------------------------------------------------------------------- 283 class Interpreter { 284 private: 285 CREATE_COMMAND0 _createCommand0; 286 CREATE_COMMAND1 _createCommand1; 287 CREATE_COMMAND2 _createCommand2; 288 CREATE_COMMAND3 _createCommand3; 289 CREATE_COMMAND4 _createCommand4; 290 CREATE_COMMANDN _createCommandN; 291 CREATE_VARIABLE _createVariable; 292 ERROR_COMMAND _error; 293 COPY_LOCAL_STRING _copyLocalString; 294 COPY_LOCAL_BOOLEAN _copyLocalBoolean; 295 COPY_LOCAL_INT _copyLocalInt; 296 COPY_LOCAL_DOUBLE _copyLocalDouble; 297 298 CREATE_TREE _createTree; 299 GET_VALUE _getValue; 300 GET_INT_VALUE _getIntValue; 301 GET_DOUBLE_VALUE _getDoubleValue; 302 GET_BOOLEAN_VALUE _getBooleanValue; 303 GET_EXTERNAL_VALUE _getExternalValue; 304 SET_VALUE _setValue; 305 SET_EXTERNAL_VALUE _setExternalValue; 306 SET_INT_VALUE _setIntValue; 307 SET_DOUBLE_VALUE _setDoubleValue; 308 SET_BOOLEAN_VALUE _setBooleanValue; 309 NEXT_NODE _nextNode; 310 INSERT_NODE _insertNode; 311 CLEAR_NODE _clearNode; 312 SIZE_ARRAY _sizeArray; 313 ALL_KEYS _allKeys; 314 ALL_VALUES _allValues; 315 GET_ITEM_FROM_KEY _getItemFromKey; 316 GET_ITEM_FROM_POS _getItemFromPos; 317 GET_ITEM_KEY _getItemKey; 318 PUSH_ITEM _pushItem; 319 INSERT_ITEM _insertItem; 320 321 FIND_FUNCTION _findFunction; 322 323 CALL_FUNCTION0 _callFunction0; 324 CALL_FUNCTION1 _callFunction1; 325 CALL_FUNCTION2 _callFunction2; 326 CALL_FUNCTION3 _callFunction3; 327 CALL_FUNCTION4 _callFunction4; 328 329 RELEASE_FUNCTION _releaseFunction; 330 331 DynPackage* _pPackage; 332 333 Tree* _pVisibility; 334 char* _tcLocalString; 335 336 public: 337 Interpreter(DynPackage* pPackage); 338 getPackage() const339 inline DynPackage* getPackage() const { return _pPackage; } getVisibility() const340 inline DtaScriptVariable* getVisibility() const { return _pVisibility; } setVisibitity(DtaScriptVariable * pVisibility)341 inline void setVisibitity(DtaScriptVariable* pVisibility) { _pVisibility = pVisibility; } 342 343 void prepare(DtaScriptVariable& pVisibility); copyLocalString(const char * tcText)344 inline const char* copyLocalString(const char* tcText) { 345 #ifdef WIN32 346 return _tcLocalString = ::_strdup(tcText); 347 #else 348 return _tcLocalString = ::strdup(tcText); 349 #endif 350 } 351 352 private: 353 Interpreter(const Interpreter&); 354 }; 355 pfCopyLocalString(Interpreter * pInterpreter,const char * tcText)356 const char* pfCopyLocalString(Interpreter* pInterpreter, const char* tcText) { 357 return pInterpreter->copyLocalString(tcText); 358 } 359 pfCopyLocalBoolean(Interpreter * pInterpreter,bool bValue)360 const char* pfCopyLocalBoolean(Interpreter* pInterpreter, bool bValue) { 361 return pInterpreter->copyLocalString(bValue ? "true" : ""); 362 } 363 pfCopyLocalDouble(Interpreter * pInterpreter,double dValue)364 const char* pfCopyLocalDouble(Interpreter* pInterpreter, double dValue) { 365 return pInterpreter->copyLocalString(CGRuntime::toString(dValue).c_str()); 366 } 367 pfCopyLocalInt(Interpreter * pInterpreter,int iValue)368 const char* pfCopyLocalInt(Interpreter* pInterpreter, int iValue) { 369 char tcNumber[32]; 370 sprintf(tcNumber, "%d", iValue); 371 return pInterpreter->copyLocalString(tcNumber); 372 } 373 pfFindFunction(Interpreter * pInterpreter,const char * sFunctionName)374 Function* pfFindFunction(Interpreter* pInterpreter, const char* sFunctionName) { 375 if (pInterpreter->getPackage()->getBlock() == NULL) return NULL; 376 ScpStream script(""); 377 ExprScriptFunction* pFunction = ExprScriptFunction::create(*pInterpreter->getPackage()->getBlock(), script, sFunctionName, "", false); 378 return pFunction; 379 } 380 pfCallFunction0(Interpreter * pInterpreter,Function * pFunction)381 const char* pfCallFunction0(Interpreter* pInterpreter, Function* pFunction) { 382 static std::string sValue; 383 if (pFunction == NULL) return NULL; 384 if (pFunction->getArity() != 0) { 385 std::string sMessage = "CodeWorker's function '"; 386 sMessage += pFunction->getName(); 387 sMessage += "' requires parameters"; 388 throw UtlException(sMessage); 389 } 390 sValue = pFunction->getValue(*pInterpreter->getVisibility()); 391 return sValue.c_str(); 392 } 393 394 populateFunctionWithParameterExpression(Function * pFunction,EXPRESSION_TYPE eType,Parameter2CW & p)395 void populateFunctionWithParameterExpression(Function* pFunction, EXPRESSION_TYPE eType, Parameter2CW& p) { 396 if ((eType & 0x00FF) == VALUE_EXPRTYPE) { 397 if (p.isValue()) { 398 const char* tcValue = p.getValue(); 399 ExprScriptConstant* pConstant; 400 if (tcValue == NULL) pConstant = new ExprScriptConstant; 401 else pConstant = new ExprScriptConstant(tcValue); 402 pFunction->addParameter(pConstant); 403 } else { 404 pFunction->addParameter(new ExprScriptResolvedVariable(p.getNode())); 405 } 406 } else { 407 if (p.isValue()) { 408 std::string sMessage = "CodeWorker's function '"; 409 sMessage += pFunction->getName(); 410 sMessage += "' requires a node parameter, which isn't passed as one"; 411 throw UtlException(sMessage); 412 } 413 pFunction->addParameter(new ExprScriptResolvedVariable(p.getNode())); 414 } 415 } 416 pfCallFunction1(Interpreter * pInterpreter,Function * pFunction,Parameter2CW p1)417 const char* pfCallFunction1(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1) { 418 static std::string sValue; 419 if (pFunction == NULL) return NULL; 420 if (pFunction->getArity() != 1) { 421 std::string sMessage = "CodeWorker's function '"; 422 sMessage += pFunction->getName(); 423 sMessage += "' doesn't require one parameter"; 424 throw UtlException(sMessage); 425 } 426 pFunction->clearParameters(); 427 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(0), p1); 428 sValue = pFunction->getValue(*pInterpreter->getVisibility()); 429 return sValue.c_str(); 430 } 431 pfCallFunction2(Interpreter * pInterpreter,Function * pFunction,Parameter2CW p1,Parameter2CW p2)432 const char* pfCallFunction2(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2) { 433 static std::string sValue; 434 if (pFunction == NULL) return NULL; 435 if (pFunction->getArity() != 2) { 436 std::string sMessage = "CodeWorker's function '"; 437 sMessage += pFunction->getName(); 438 sMessage += "' doesn't require two parameters"; 439 throw UtlException(sMessage); 440 } 441 pFunction->clearParameters(); 442 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(0), p1); 443 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(1), p2); 444 sValue = pFunction->getValue(*pInterpreter->getVisibility()); 445 return sValue.c_str(); 446 } 447 pfCallFunction3(Interpreter * pInterpreter,Function * pFunction,Parameter2CW p1,Parameter2CW p2,Parameter2CW p3)448 const char* pfCallFunction3(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2, Parameter2CW p3) { 449 static std::string sValue; 450 if (pFunction == NULL) return NULL; 451 if (pFunction->getArity() != 3) { 452 std::string sMessage = "CodeWorker's function '"; 453 sMessage += pFunction->getName(); 454 sMessage += "' doesn't require three parameters"; 455 throw UtlException(sMessage); 456 } 457 pFunction->clearParameters(); 458 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(0), p1); 459 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(1), p2); 460 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(2), p3); 461 sValue = pFunction->getValue(*pInterpreter->getVisibility()); 462 return sValue.c_str(); 463 } 464 pfCallFunction4(Interpreter * pInterpreter,Function * pFunction,Parameter2CW p1,Parameter2CW p2,Parameter2CW p3,Parameter2CW p4)465 const char* pfCallFunction4(Interpreter* pInterpreter, Function* pFunction, Parameter2CW p1, Parameter2CW p2, Parameter2CW p3, Parameter2CW p4) { 466 static std::string sValue; 467 if (pFunction == NULL) return NULL; 468 if (pFunction->getArity() != 4) { 469 std::string sMessage = "CodeWorker's function '"; 470 sMessage += pFunction->getName(); 471 sMessage += "' doesn't require four parameters"; 472 throw UtlException(sMessage); 473 } 474 pFunction->clearParameters(); 475 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(0), p1); 476 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(1), p2); 477 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(2), p3); 478 populateFunctionWithParameterExpression(pFunction, pFunction->getParameterType(3), p4); 479 sValue = pFunction->getValue(*pInterpreter->getVisibility()); 480 return sValue.c_str(); 481 } 482 483 Interpreter(DynPackage * pPackage)484 Interpreter::Interpreter(DynPackage* pPackage) : _pPackage(pPackage), _tcLocalString(NULL) { 485 _createCommand0 = pfCreateCommand0; 486 _createCommand1 = pfCreateCommand1; 487 _createCommand2 = pfCreateCommand2; 488 _createCommand3 = pfCreateCommand3; 489 _createCommand4 = pfCreateCommand4; 490 _createCommandN = pfCreateCommandN; 491 _createVariable = pfCreateVariable; 492 _error = pfError; 493 _copyLocalString = pfCopyLocalString; 494 _copyLocalBoolean = pfCopyLocalBoolean; 495 _copyLocalInt = pfCopyLocalInt; 496 _copyLocalDouble = pfCopyLocalDouble; 497 498 _createTree = pfCreateTree; 499 _getValue = pfGetValue; 500 _getIntValue = pfGetIntValue; 501 _getBooleanValue = pfGetBooleanValue; 502 _getDoubleValue = pfGetDoubleValue; 503 _getExternalValue = pfGetExternalValue; 504 _setValue = pfSetValue; 505 _setExternalValue = pfSetExternalValue; 506 _setIntValue = pfSetIntValue; 507 _setDoubleValue = pfSetDoubleValue; 508 _setBooleanValue = pfSetBooleanValue; 509 _nextNode = pfNextNode; 510 _insertNode = pfInsertNode; 511 _clearNode = pfClearNode; 512 _sizeArray = pfSizeArray; 513 _allKeys = pfAllKeys; 514 _allValues = pfAllValues; 515 _getItemFromKey = pfGetItemFromKey; 516 _getItemFromPos = pfGetItemFromPos; 517 _getItemKey = pfGetItemKey; 518 _pushItem = pfPushItem; 519 _insertItem = pfInsertItem; 520 521 _findFunction = pfFindFunction; 522 523 _callFunction0 = pfCallFunction0; 524 _callFunction1 = pfCallFunction1; 525 _callFunction2 = pfCallFunction2; 526 _callFunction3 = pfCallFunction3; 527 _callFunction4 = pfCallFunction4; 528 529 _releaseFunction = pfReleaseFunction; 530 } 531 prepare(DtaScriptVariable & pVisibility)532 void Interpreter::prepare(DtaScriptVariable& pVisibility) { 533 _pVisibility = &pVisibility; 534 free(_tcLocalString); 535 _tcLocalString = NULL; 536 } 537 538 539 540 //-------------------------------------------------------------------------------- 541 // Dynamic function 542 //-------------------------------------------------------------------------------- 543 DynFunction(Interpreter * pInterpreter,const char * tcName,bool bIsP1Node)544 DynFunction::DynFunction(Interpreter* pInterpreter, const char* tcName, bool bIsP1Node) : GrfFunction(NULL, tcName, "", false), _pInterpreter(pInterpreter) { 545 init(); 546 addParameterAndType("p1", ((bIsP1Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 547 } 548 DynFunction(Interpreter * pInterpreter,const char * tcName,bool bIsP1Node,bool bIsP2Node)549 DynFunction::DynFunction(Interpreter* pInterpreter, const char* tcName, bool bIsP1Node, bool bIsP2Node) : GrfFunction(NULL, tcName, "", false), _pInterpreter(pInterpreter) { 550 init(); 551 addParameterAndType("p1", ((bIsP1Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 552 addParameterAndType("p2", ((bIsP2Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 553 } 554 DynFunction(Interpreter * pInterpreter,const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node)555 DynFunction::DynFunction(Interpreter* pInterpreter, const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node) : GrfFunction(NULL, tcName, "", false), _pInterpreter(pInterpreter) { 556 init(); 557 addParameterAndType("p1", ((bIsP1Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 558 addParameterAndType("p2", ((bIsP2Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 559 addParameterAndType("p3", ((bIsP3Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 560 } 561 DynFunction(Interpreter * pInterpreter,const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node,bool bIsP4Node)562 DynFunction::DynFunction(Interpreter* pInterpreter, const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node, bool bIsP4Node) : GrfFunction(NULL, tcName, "", false), _pInterpreter(pInterpreter) { 563 init(); 564 addParameterAndType("p1", ((bIsP1Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 565 addParameterAndType("p2", ((bIsP2Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 566 addParameterAndType("p3", ((bIsP3Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 567 addParameterAndType("p4", ((bIsP4Node) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 568 } 569 DynFunction(Interpreter * pInterpreter,const char * tcName,int iNbParams,int * tbNodeParams)570 DynFunction::DynFunction(Interpreter* pInterpreter, const char* tcName, int iNbParams, int* tbNodeParams) : GrfFunction(NULL, tcName, "", false), _pInterpreter(pInterpreter) { 571 init(); 572 char tcParam[16]; 573 for (int i = 0; i < iNbParams; i++) { 574 sprintf(tcParam, "p%d", i+1); 575 addParameterAndType(tcParam, ((tbNodeParams[i] != 0) ? NODE_EXPRTYPE : VALUE_EXPRTYPE), NULL); 576 } 577 } 578 ~DynFunction()579 DynFunction::~DynFunction() {} 580 init()581 void DynFunction::init() { 582 #ifdef WIN32 583 _sModuleName = _pInterpreter->getPackage()->getName() + "cw.dll"; 584 #else 585 _sModuleName = _pInterpreter->getPackage()->getName() + "cw.so"; 586 #endif 587 } 588 launchExecution(DtaScriptVariable & visibility,const ExprScriptFunction & functionCall,const std::string & sInstantiationKey)589 std::string DynFunction::launchExecution(DtaScriptVariable& visibility, const ExprScriptFunction& functionCall, const std::string& sInstantiationKey) { 590 UTLTRACE_STACK_FUNCTION(_sModuleName.c_str(), getFunctionName(), 0); 591 592 std::string sResult; 593 594 Parameter* tParameters = new Parameter[getArity()]; 595 try { 596 const std::vector<ExprScriptExpression*>& parameters = functionCall.getParameters(); 597 std::vector<EXPRESSION_TYPE>::const_iterator k = _parameterTypes.begin(); 598 int iIndex = 0; 599 for (std::vector<ExprScriptExpression*>::const_iterator i = parameters.begin(); i != parameters.end(); i++) { 600 DtaScriptVariable* pVariable = NULL; 601 switch(*k & 0x00FF) { 602 case VALUE_EXPRTYPE: 603 { 604 std::string sValue = (*i)->getValue(visibility); 605 if (sValue.empty()) { 606 ExprScriptVariable* pExprVar = dynamic_cast<ExprScriptVariable*>(*i); 607 if ((pExprVar != NULL) && pExprVar->getName() == "null") { 608 tParameters[iIndex++] = NULL; 609 } else { 610 #ifdef WIN32 611 tParameters[iIndex++] = ::_strdup(""); 612 #else 613 tParameters[iIndex++] = ::strdup(""); 614 #endif 615 } 616 } else { 617 #ifdef WIN32 618 tParameters[iIndex++] = ::_strdup(sValue.c_str()); 619 #else 620 tParameters[iIndex++] = ::strdup(sValue.c_str()); 621 #endif 622 } 623 } 624 break; 625 case NODE_EXPRTYPE: 626 { 627 ExprScriptResolvedVariable* pResolvedVariable = dynamic_cast<ExprScriptResolvedVariable*>(*i); 628 if (pResolvedVariable == NULL) { 629 ExprScriptVariable* pVarExpr = dynamic_cast<ExprScriptVariable*>(*i); 630 if (pVarExpr == NULL) { 631 throw UtlException("bad parameter passed to the function '" + _pInterpreter->getPackage()->getName() + "::" + std::string(getFunctionName()) + "()'"); 632 } 633 DtaScriptVariable* pVariable = visibility.getVariable((const ExprScriptVariable&) *(*i)); 634 tParameters[iIndex++] = pVariable; 635 } else { 636 tParameters[iIndex++] = pResolvedVariable->getVariable(); 637 } 638 } 639 break; 640 } 641 k++; 642 } 643 switch(getArity()) { 644 case 0: 645 sResult = call(visibility); 646 break; 647 case 1: 648 sResult = call(visibility, tParameters[0]); 649 break; 650 case 2: 651 sResult = call(visibility, tParameters[0], tParameters[1]); 652 break; 653 case 3: 654 sResult = call(visibility, tParameters[0], tParameters[1], tParameters[2]); 655 break; 656 case 4: 657 sResult = call(visibility, tParameters[0], tParameters[1], tParameters[2], tParameters[3]); 658 break; 659 default: 660 sResult = call(visibility, tParameters); 661 } 662 } catch(std::exception&) { 663 for (std::string::size_type iIndex = 0; iIndex < getArity(); iIndex++) { 664 if ((getParameterType(iIndex) & 0x00FF) == VALUE_EXPRTYPE) free(tParameters[iIndex]); 665 } 666 delete [] tParameters; 667 throw; 668 } catch(...) { 669 for (std::string::size_type iIndex = 0; iIndex < getArity(); iIndex++) { 670 if ((getParameterType(iIndex) & 0x00FF) == VALUE_EXPRTYPE) free(tParameters[iIndex]); 671 } 672 delete [] tParameters; 673 std::string sMessage = "an ellipsis exception has occurred in " + _sModuleName + ", function " + getName(); 674 throw UtlException(sMessage); 675 } 676 for (std::string::size_type iIndex = 0; iIndex < getArity(); iIndex++) { 677 if ((getParameterType(iIndex) & 0x00FF) == VALUE_EXPRTYPE) free(tParameters[iIndex]); 678 } 679 delete [] tParameters; 680 return sResult; 681 } 682 call(DtaScriptVariable & pVisibility)683 std::string DynFunction::call(DtaScriptVariable& pVisibility) { 684 _pInterpreter->prepare(pVisibility); 685 CALL0_FUNCTION pfCall0 = (CALL0_FUNCTION) _pfFunctionCall; 686 const char* tcResult = pfCall0(_pInterpreter); 687 if (tcResult == NULL) return ""; 688 return tcResult; 689 } 690 call(DtaScriptVariable & pVisibility,Parameter p1)691 std::string DynFunction::call(DtaScriptVariable& pVisibility, Parameter p1) { 692 _pInterpreter->prepare(pVisibility); 693 CALL1_FUNCTION pfCall1 = (CALL1_FUNCTION) _pfFunctionCall; 694 const char* tcResult = pfCall1(_pInterpreter, p1); 695 if (tcResult == NULL) return ""; 696 return tcResult; 697 } 698 call(DtaScriptVariable & pVisibility,Parameter p1,Parameter p2)699 std::string DynFunction::call(DtaScriptVariable& pVisibility, Parameter p1, Parameter p2) { 700 _pInterpreter->prepare(pVisibility); 701 CALL2_FUNCTION pfCall2 = (CALL2_FUNCTION) _pfFunctionCall; 702 const char* tcResult = pfCall2(_pInterpreter, p1, p2); 703 if (tcResult == NULL) return ""; 704 return tcResult; 705 } 706 call(DtaScriptVariable & pVisibility,Parameter p1,Parameter p2,Parameter p3)707 std::string DynFunction::call(DtaScriptVariable& pVisibility, Parameter p1, Parameter p2, Parameter p3) { 708 _pInterpreter->prepare(pVisibility); 709 CALL3_FUNCTION pfCall3 = (CALL3_FUNCTION) _pfFunctionCall; 710 const char* tcResult = pfCall3(_pInterpreter, p1, p2, p3); 711 if (tcResult == NULL) return ""; 712 return tcResult; 713 } 714 call(DtaScriptVariable & pVisibility,Parameter p1,Parameter p2,Parameter p3,Parameter p4)715 std::string DynFunction::call(DtaScriptVariable& pVisibility, Parameter p1, Parameter p2, Parameter p3, Parameter p4) { 716 _pInterpreter->prepare(pVisibility); 717 CALL4_FUNCTION pfCall4 = (CALL4_FUNCTION) _pfFunctionCall; 718 const char* tcResult = pfCall4(_pInterpreter, p1, p2, p3, p4); 719 if (tcResult == NULL) return ""; 720 return tcResult; 721 } 722 call(DtaScriptVariable & pVisibility,Parameter * tParams)723 std::string DynFunction::call(DtaScriptVariable& pVisibility, Parameter* tParams) { 724 _pInterpreter->prepare(pVisibility); 725 CALLN_FUNCTION pfCallN = (CALLN_FUNCTION) _pfFunctionCall; 726 const char* tcResult = pfCallN(_pInterpreter, tParams); 727 if (tcResult == NULL) return ""; 728 return tcResult; 729 } 730 731 compileCppFunctionNameForCalling(CppCompilerEnvironment & theCompilerEnvironment)732 void DynFunction::compileCppFunctionNameForCalling(CppCompilerEnvironment& theCompilerEnvironment) { 733 CW_BODY_STREAM << _pInterpreter->getPackage()->getName() << "::instance()._compilerFunction_" << getFunctionName(); 734 if (!theCompilerEnvironment.getIncludeParentScript().empty()) { 735 // not the leader script, which initializes the dynamic packages 736 ScpStream* pOwner = NULL; 737 int iInsertAreaLocation = CW_BODY_STREAM.getFloatingLocation("INSERT AREA", pOwner); 738 CW_BODY_STREAM.insertTextOnce("// header file for the dynamic module '" + _pInterpreter->getPackage()->getName() + "'" + ScpStream::ENDL + "#include \"" + _pInterpreter->getPackage()->getName() + ".h\"" + ScpStream::ENDL + ScpStream::ENDL, iInsertAreaLocation); 739 } 740 } 741 742 743 744 //-------------------------------------------------------------------------------- 745 // Dynamic package 746 //-------------------------------------------------------------------------------- 747 typedef void (*LIBRARY_INIT_FUNCTION)(Interpreter*); 748 749 DynPackage(const std::string & sPackage)750 DynPackage::DynPackage(const std::string& sPackage) : _sPackage(sPackage), _pBlock(NULL), _hHandle(0), _pInterpreter(NULL) { 751 initialize(); 752 } 753 DynPackage(const std::string & sPackage,GrfBlock & block)754 DynPackage::DynPackage(const std::string& sPackage, GrfBlock& block) : _sPackage(sPackage), _pBlock(&block), _hHandle(0), _pInterpreter(NULL) { 755 initialize(); 756 } initialize()757 void DynPackage::initialize() { 758 _hHandle = loadPackage(_sPackage + "cw"); 759 _pInterpreter = new Interpreter(this); 760 761 LIBRARY_INIT_FUNCTION pfInit = (LIBRARY_INIT_FUNCTION) findFunction(_hHandle, _sPackage + "_Init"); 762 if (pfInit == NULL) { 763 throw UtlException("unable to find the init function " + _sPackage + "_Init(CW4dl::Interpreter*) in module " + _sPackage + "cw"); 764 } 765 try { 766 pfInit(_pInterpreter); 767 } catch(...) { 768 throw UtlException("ellipsis exception while initializing the module " + _sPackage + "cw: is the interpreter's version the same as the module?"); 769 } 770 _packages[_sPackage] = this; 771 } 772 ~DynPackage()773 DynPackage::~DynPackage() { 774 freeLibrary(_hHandle); 775 delete _pInterpreter; 776 for (std::map<std::string, DynFunction*>::iterator i = _functions.begin(); i != _functions.end(); i++) { 777 delete i->second; 778 } 779 for (std::map<std::string, DtaScriptVariable*>::iterator j = _variables.begin(); j != _variables.end(); j++) { 780 delete j->second; 781 } 782 _packages.erase(_sPackage); 783 } 784 getFunction(const std::string & sFunction) const785 DynFunction* DynPackage::getFunction(const std::string& sFunction) const { 786 std::map<std::string, DynFunction*>::const_iterator cursor = _functions.find(sFunction); 787 if (cursor == _functions.end()) return NULL; 788 return cursor->second; 789 } 790 addFunction(const char * tcName)791 bool DynPackage::addFunction(const char* tcName) { 792 return addFunction(new DynFunction(_pInterpreter, tcName)); 793 } 794 addFunction(const char * tcName,bool bIsP1Node)795 bool DynPackage::addFunction(const char* tcName, bool bIsP1Node) { 796 return addFunction(new DynFunction(_pInterpreter, tcName, bIsP1Node)); 797 } 798 addFunction(const char * tcName,bool bIsP1Node,bool bIsP2Node)799 bool DynPackage::addFunction(const char* tcName, bool bIsP1Node, bool bIsP2Node) { 800 return addFunction(new DynFunction(_pInterpreter, tcName, bIsP1Node, bIsP2Node)); 801 } 802 addFunction(const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node)803 bool DynPackage::addFunction(const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node) { 804 return addFunction(new DynFunction(_pInterpreter, tcName, bIsP1Node, bIsP2Node, bIsP3Node)); 805 } 806 addFunction(const char * tcName,bool bIsP1Node,bool bIsP2Node,bool bIsP3Node,bool bIsP4Node)807 bool DynPackage::addFunction(const char* tcName, bool bIsP1Node, bool bIsP2Node, bool bIsP3Node, bool bIsP4Node) { 808 return addFunction(new DynFunction(_pInterpreter, tcName, bIsP1Node, bIsP2Node, bIsP3Node, bIsP4Node)); 809 } 810 addFunction(const char * tcName,int iNbParams,int * tbNodeParams)811 bool DynPackage::addFunction(const char* tcName, int iNbParams, int* tbNodeParams) { 812 return addFunction(new DynFunction(_pInterpreter, tcName, iNbParams, tbNodeParams)); 813 } 814 addFunction(DynFunction * pFunction)815 bool DynPackage::addFunction(DynFunction* pFunction) { 816 if (getFunction(pFunction->getFunctionName()) != NULL) { 817 delete pFunction; 818 std::string sError = "function '" + _sPackage + "::"; 819 sError += pFunction->getFunctionName(); 820 sError += "' already exists"; 821 throw UtlException(sError); 822 } 823 void* pfFunctionCall = findFunction(_hHandle, pFunction->getFunctionName()); 824 if (pfFunctionCall == NULL) { 825 std::string sError = "the module '" + _sPackage + "' doesn't export the function '" + _sPackage + "::"; 826 sError += pFunction->getFunctionName(); 827 sError += "'"; 828 delete pFunction; 829 throw UtlException(sError); 830 } 831 pFunction->setFunctionCall(pfFunctionCall); 832 _functions[pFunction->getFunctionName()] = pFunction; 833 return true; 834 } 835 getVariable(const std::string & sVariable) const836 DtaScriptVariable* DynPackage::getVariable(const std::string& sVariable) const { 837 std::map<std::string, DtaScriptVariable*>::const_iterator cursor = _variables.find(sVariable); 838 if (cursor == _variables.end()) return NULL; 839 return cursor->second; 840 } 841 addVariable(const char * tcName)842 DtaScriptVariable* DynPackage::addVariable(const char* tcName) { 843 std::map<std::string, DtaScriptVariable*>::const_iterator cursor = _variables.find(tcName); 844 if (cursor != _variables.end()) return cursor->second; 845 DtaScriptVariable* pVariable = new Tree(NULL, tcName); 846 _variables[tcName] = pVariable; 847 return pVariable; 848 } 849 850 getPackage(const std::string & sPackage)851 DynPackage* DynPackage::getPackage(const std::string& sPackage) { 852 std::map<std::string, DynPackage*>::iterator cursor = _packages.find(sPackage); 853 if (cursor == _packages.end()) return NULL; 854 return cursor->second; 855 } 856 addPackage(const std::string & sPackage,GrfBlock & block)857 DynPackage* DynPackage::addPackage(const std::string& sPackage, GrfBlock& block) { 858 DynPackage* pPackage = getPackage(sPackage); 859 if (pPackage == NULL) { 860 pPackage = new DynPackage(sPackage, block); 861 } 862 return pPackage; 863 } 864 loadPackage(const std::string & sLibrary)865 LIBRARY_HANDLE DynPackage::loadPackage(const std::string& sLibrary) { 866 LIBRARY_HANDLE hHandle; 867 std::string sLibraryWithExt; 868 #ifdef WIN32 869 sLibraryWithExt = sLibrary + ".dll"; 870 HMODULE hModule = LoadLibrary(sLibraryWithExt.c_str()); 871 if (hModule == NULL) { 872 sLibraryWithExt = sLibrary + "_d.dll"; 873 hModule = LoadLibrary(sLibraryWithExt.c_str()); 874 if (hModule == NULL) { 875 std::string sCompleteFileName; 876 if (ScpStream::existInputFileFromIncludePath(sLibraryWithExt.c_str(), sCompleteFileName)) { 877 sCompleteFileName = CGRuntime::canonizePath(sCompleteFileName); 878 hModule = LoadLibrary(sCompleteFileName.c_str()); 879 } 880 if (hModule == NULL) throw UtlException("unable to load library '" + sLibraryWithExt + "'"); 881 } 882 } 883 hHandle = hModule; 884 #else 885 sLibraryWithExt = sLibrary + ".so"; 886 hHandle = dlopen(sLibraryWithExt.c_str(), RTLD_NOW); 887 if (hHandle == NULL) { 888 sLibraryWithExt = sLibrary + "_d.so"; 889 hHandle = dlopen(sLibraryWithExt.c_str(), RTLD_NOW); 890 throw UtlException("unable to load library '" + sLibraryWithExt + "': " + dlerror()); 891 } 892 #endif 893 return hHandle; 894 } 895 loadLibrary(const std::string & sLibrary)896 LIBRARY_HANDLE DynPackage::loadLibrary(const std::string& sLibrary) { 897 LIBRARY_HANDLE hHandle; 898 #ifdef WIN32 899 HMODULE hModule = LoadLibrary(sLibrary.c_str()); 900 hHandle = hModule; 901 #else 902 hHandle = dlopen(sLibrary.c_str(), RTLD_NOW); 903 #endif 904 return hHandle; 905 } 906 freeLibrary(LIBRARY_HANDLE hHandle)907 void DynPackage::freeLibrary(LIBRARY_HANDLE hHandle) { 908 #ifdef WIN32 909 FreeLibrary((HMODULE) hHandle); 910 #else 911 dlclose(hHandle); 912 #endif 913 } 914 findFunction(LIBRARY_HANDLE hHandle,const std::string & sFunction)915 void* DynPackage::findFunction(LIBRARY_HANDLE hHandle, const std::string& sFunction) { 916 #ifdef WIN32 917 return GetProcAddress((HMODULE) hHandle, sFunction.c_str()); 918 #else 919 return dlsym(hHandle, sFunction.c_str()); 920 #endif 921 } 922 } 923