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