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 #ifndef WIN32
28 #	include <cstdio> // for Debian/gcc 2.95.4
29 #endif
30 
31 #include <string.h>
32 
33 #include "ScpStream.h"
34 
35 #include "UtlException.h"
36 #include "UtlTrace.h"
37 #include "UtlString.h"
38 
39 #include "CGRuntime.h"
40 #include "DtaArrayIterator.h"
41 #include "ExprScriptVariable.h"
42 #include "Workspace.h"
43 #include "DtaProject.h"
44 #include "ExternalValueNode.h"
45 #include "DynPackage.h"
46 #include "CGExternalHandling.h" // for CGQuietOutput
47 #include "DtaScriptVariable.h"
48 
49 namespace CodeWorker {
~DtaNodeListener()50 	DtaNodeListener::~DtaNodeListener() {}
51 
52 	class DtaNodeListeners {
53 	private:
54 		DtaScriptVariable* _pNode;
55 		std::list<DtaNodeListener*> _listeners;
56 
57 	public:
DtaNodeListeners(DtaScriptVariable * pNode)58 		inline DtaNodeListeners(DtaScriptVariable* pNode) : _pNode(pNode) {}
~DtaNodeListeners()59 		~DtaNodeListeners() {
60 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
61 				(*i)->onDelete();
62 				delete *i;
63 			}
64 		}
65 
addListener(DtaNodeListener * pListener)66 		void addListener(DtaNodeListener* pListener) {
67 			pListener->_pNode = _pNode;
68 			_listeners.push_back(pListener);
69 		}
70 
removeListener(DtaNodeListener * pListener)71 		bool removeListener(DtaNodeListener* pListener) {
72 			if (pListener->_pNode != _pNode) return false;
73 			_listeners.remove(pListener);
74 			delete pListener;
75 			return true;
76 		}
77 
onSetValue(const char * tcValue)78 		void onSetValue(const char* tcValue) {
79 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
80 				(*i)->onSetValue(tcValue);
81 			}
82 		}
83 
onConcatValue(const char * tcValue)84 		void onConcatValue(const char* tcValue) {
85 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
86 				(*i)->onConcatValue(tcValue);
87 			}
88 		}
89 
onSetReference(DtaScriptVariable * pReference)90 		void onSetReference(DtaScriptVariable* pReference) {
91 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
92 				(*i)->onSetReference(pReference);
93 			}
94 		}
95 
onSetExternal(ExternalValueNode * pExternalValue)96 		void onSetExternal(ExternalValueNode* pExternalValue) {
97 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
98 				(*i)->onSetExternal(pExternalValue);
99 			}
100 		}
101 
onSetIterator(DtaArrayIterator ** pIteratorData)102 		void onSetIterator(DtaArrayIterator** pIteratorData) {
103 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
104 				(*i)->onSetIterator(pIteratorData);
105 			}
106 		}
107 
onAddAttribute(DtaScriptVariable * pAttribute)108 		void onAddAttribute(DtaScriptVariable* pAttribute) {
109 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
110 				(*i)->onAddAttribute(pAttribute);
111 			}
112 		}
113 
onRemoveAttribute(DtaScriptVariable * pAttribute)114 		void onRemoveAttribute(DtaScriptVariable* pAttribute) {
115 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
116 				(*i)->onRemoveAttribute(pAttribute);
117 			}
118 		}
119 
onArrayHasChanged()120 		void onArrayHasChanged() {
121 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
122 				(*i)->onArrayHasChanged();
123 			}
124 		}
125 
onClearContent()126 		void onClearContent() {
127 			for (std::list<DtaNodeListener*>::iterator i = _listeners.begin(); i != _listeners.end(); ++i) {
128 				(*i)->onClearContent();
129 			}
130 		}
131 	};
132 
pushBack(DtaScriptVariable * pVariable)133 	void DtaScriptVariableList::pushBack(DtaScriptVariable* pVariable) {
134 		register DtaScriptVariableList* pList = this;
135 		while (pList->getNext() != NULL) pList = pList->getNext();
136 		pList->setNext(new DtaScriptVariableList(pVariable));
137 	}
138 
139 
~NodeArrayType()140 	DtaScriptVariable::NodeArrayType::~NodeArrayType() {
141 		for (std::list<DtaScriptVariable*>::iterator i = items.begin(); i != items.end(); i++) {
142 			delete (*i);
143 		}
144 		delete cache;
145 	}
146 
NodeArrayType(DtaScriptVariable * pElt)147 	DtaScriptVariable::NodeArrayType::NodeArrayType(DtaScriptVariable* pElt) : cache(NULL) {
148 		items.push_back(pElt);
149 	}
150 
151 
~DtaScriptVariable()152 	DtaScriptVariable::~DtaScriptVariable() {
153 		delete _pListeners;
154 		_pListeners = NULL;
155 		clearContent();
156 		if (_pReferencedByVariables != NULL) {
157 			while (!_pReferencedByVariables->empty()) {
158 				DtaScriptVariable* pReferencedBy = *(_pReferencedByVariables->begin());
159 				pReferencedBy->removeReference();
160 	/*
161 				std::string sErrorMessage = "warning: variable '";
162 				sErrorMessage += pReferencedBy->getCompleteName();
163 				sErrorMessage += "' refers to '";
164 				sErrorMessage += getCompleteName();
165 				sErrorMessage += "' that is being removed from the stack" + CGRuntime::endl();
166 				sErrorMessage += UtlTrace::getTraceStack();
167 				if (DtaProject::getInstance().addWarning(sErrorMessage) == 1) CGRuntime::traceLine(sErrorMessage);
168 	*/
169 			}
170 			delete _pReferencedByVariables;
171 			_pReferencedByVariables = NULL;
172 		}
173 		free((char*) _tcName);
174 	}
175 
addListener(DtaNodeListener * pListener)176 	void DtaScriptVariable::addListener(DtaNodeListener* pListener) {
177 		if (_pListeners == NULL) _pListeners = new DtaNodeListeners(this);
178 		_pListeners->addListener(pListener);
179 	}
180 
removeListener(DtaNodeListener * pListener)181 	bool DtaScriptVariable::removeListener(DtaNodeListener* pListener) {
182 		if (_pListeners == NULL) return false;
183 		return _pListeners->removeListener(pListener);
184 	}
185 
getReferencedVariable() const186 	DtaScriptVariable* DtaScriptVariable::getReferencedVariable() const {
187 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var;
188 		if (_eValueNode == INDEX_VALUE_NODE) {
189 			DtaScriptVariable* pVariable = (*_value.ind.var)->itemNoRef();
190 			return pVariable;
191 		}
192 		return NULL;
193 	}
194 
getRoot() const195 	DtaScriptVariable* DtaScriptVariable::getRoot() const {
196 		DtaScriptVariable* pVariable = const_cast<DtaScriptVariable*>(this);
197 		register DtaScriptVariable* pParent = _pParent;
198 		while ((pParent != NULL) && (strncmp(pParent->_tcName, "##stack##", 9) != 0)) {
199 			pVariable = pParent;
200 			pParent = pVariable->getParent();
201 		}
202 		return pVariable;
203 	}
204 
changeName(const char * tcName)205 	void DtaScriptVariable::changeName(const char* tcName) {
206 		if ((_pParent != NULL) && (_pParent->_pArray != NULL)) {
207 			if (_pParent->getNode(_tcName) != this) {
208 				// this node belongs to the array of its parent:
209 				// purge the cache: the key will change!
210 				delete _pParent->_pArray->cache;
211 				_pParent->_pArray->cache = NULL;
212 			}
213 		}
214 		delete _tcName;
215 #ifdef WIN32
216 		_tcName = ::_strdup(tcName);
217 #else
218 		_tcName = ::strdup(tcName);
219 #endif
220 	}
221 
isLocal() const222 	bool DtaScriptVariable::isLocal() const {
223 		const DtaScriptVariable* pVariable = this;
224 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
225 		if (pVariable->_pParent == NULL || pVariable->_pParent->getName() == NULL) return false;
226 		return (strncmp(pVariable->_pParent->getName(), "##", 2) == 0);
227 	}
228 
detachAttribute(const char * tcName)229 	DtaScriptVariable* DtaScriptVariable::detachAttribute(const char* tcName) {
230 		DtaScriptVariable* pNode = NULL;
231 		DtaScriptVariableList* pAttributes = _pAttributes;
232 		DtaScriptVariableList* pLastAttribute = NULL;
233 		while (pAttributes != NULL) {
234 			if (strcmp(pAttributes->getNode()->_tcName, tcName) == 0) {
235 				pNode = pAttributes->getNode();
236 				if (pLastAttribute == NULL) _pAttributes = pAttributes->getNext();
237 				else pLastAttribute->setNext(pAttributes->getNext());
238 				pAttributes->setNext(NULL);
239 				delete pAttributes;
240 				break;
241 			}
242 			pLastAttribute = pAttributes;
243 			pAttributes = pAttributes->getNext();
244 		}
245 		return pNode;
246 	}
247 
getArray() const248 	const std::list<DtaScriptVariable*>* DtaScriptVariable::getArray() const {
249 		const DtaScriptVariable* pVariable = this;
250 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
251 		return &(pVariable->_pArray->items);
252 	}
253 
getArraySize() const254 	int DtaScriptVariable::getArraySize() const {
255 		const DtaScriptVariable* pVariable = this;
256 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
257 		if (pVariable->_pArray == NULL) return 0;
258 		return pVariable->_pArray->items.size();
259 	}
260 
getSortedArray() const261 	const std::map<std::string, DtaScriptVariable*>* DtaScriptVariable::getSortedArray() const {
262 		const DtaScriptVariable* pVariable = this;
263 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
264 		NodeArrayType* pANT = pVariable->_pArray;
265 		if (pANT == NULL) return NULL;
266 		if (pANT->cache == NULL) {
267 			pANT->cache = new std::map<std::string, DtaScriptVariable*>();
268 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
269 				(*(pANT->cache))[(*i)->_tcName] = (*i);
270 			}
271 		}
272 		return pVariable->_pArray->cache;
273 	}
274 
getSortedNoCaseArray() const275 	std::auto_ptr<std::vector<DtaScriptVariable*> > DtaScriptVariable::getSortedNoCaseArray() const {
276 		const DtaScriptVariable* pVariable = this;
277 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
278 		std::vector<DtaScriptVariable*>* pListOfNodes = NULL;
279 		NodeArrayType* pANT = pVariable->_pArray;
280 		if (pANT != NULL) {
281 			std::map<std::string, std::map<std::string, DtaScriptVariable*> > mapOfNodes;
282 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
283 				std::string sKey = toLowercase((*i)->_tcName);
284 				mapOfNodes[sKey][(*i)->_tcName] = *i;
285 			}
286 			pListOfNodes = new std::vector<DtaScriptVariable*>(pANT->items.size());
287 			int iPosition = 0;
288 			for (std::map<std::string, std::map<std::string, DtaScriptVariable*> >::const_iterator j = mapOfNodes.begin(); j != mapOfNodes.end(); ++j) {
289 				for (std::map<std::string, DtaScriptVariable*>::const_iterator k = j->second.begin(); k != j->second.end(); ++k) {
290 					(*pListOfNodes)[iPosition++] = k->second;
291 				}
292 			}
293 		}
294 		return std::auto_ptr<std::vector<DtaScriptVariable*> >(pListOfNodes);
295 	}
296 
getSortedArrayOnValue() const297 	std::auto_ptr<std::vector<DtaScriptVariable*> > DtaScriptVariable::getSortedArrayOnValue() const {
298 		const DtaScriptVariable* pVariable = this;
299 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
300 		std::vector<DtaScriptVariable*>* pListOfNodes = NULL;
301 		NodeArrayType* pANT = pVariable->_pArray;
302 		if (pANT != NULL) {
303 			std::map<std::string, std::map<std::string, DtaScriptVariable*> > mapOfNodes;
304 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
305 				std::string sKey = (*i)->getValue();
306 				mapOfNodes[sKey][(*i)->_tcName] = *i;
307 			}
308 			pListOfNodes = new std::vector<DtaScriptVariable*>(pANT->items.size());
309 			int iPosition = 0;
310 			for (std::map<std::string, std::map<std::string, DtaScriptVariable*> >::const_iterator j = mapOfNodes.begin(); j != mapOfNodes.end(); ++j) {
311 				for (std::map<std::string, DtaScriptVariable*>::const_iterator k = j->second.begin(); k != j->second.end(); ++k) {
312 					(*pListOfNodes)[iPosition++] = k->second;
313 				}
314 			}
315 		}
316 		return std::auto_ptr<std::vector<DtaScriptVariable*> >(pListOfNodes);
317 	}
318 
getSortedNoCaseArrayOnValue() const319 	std::auto_ptr<std::vector<DtaScriptVariable*> > DtaScriptVariable::getSortedNoCaseArrayOnValue() const {
320 		const DtaScriptVariable* pVariable = this;
321 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
322 		std::vector<DtaScriptVariable*>* pListOfNodes = NULL;
323 		NodeArrayType* pANT = pVariable->_pArray;
324 		if (pANT != NULL) {
325 			std::map<std::string, std::map<std::string, DtaScriptVariable*> > mapOfNodes;
326 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
327 				std::string sKey = toLowercase((*i)->getValue());
328 				mapOfNodes[sKey][(*i)->_tcName] = *i;
329 			}
330 			pListOfNodes = new std::vector<DtaScriptVariable*>(pANT->items.size());
331 			int iPosition = 0;
332 			for (std::map<std::string, std::map<std::string, DtaScriptVariable*> >::const_iterator j = mapOfNodes.begin(); j != mapOfNodes.end(); ++j) {
333 				for (std::map<std::string, DtaScriptVariable*>::const_iterator k = j->second.begin(); k != j->second.end(); ++k) {
334 					(*pListOfNodes)[iPosition++] = k->second;
335 				}
336 			}
337 		}
338 		return std::auto_ptr<std::vector<DtaScriptVariable*> >(pListOfNodes);
339 	}
340 
getArrayElement(const std::string & sPosition) const341 	DtaScriptVariable* DtaScriptVariable::getArrayElement(const std::string& sPosition) const {
342 		if (getReferencedVariable() != NULL) return getReferencedVariable()->getArrayElement(sPosition);
343 		if (_pArray == NULL) return NULL;
344 		if (_pArray->cache != NULL) {
345 			std::map<std::string, DtaScriptVariable*>::const_iterator i = _pArray->cache->find(sPosition);
346 			if (i != _pArray->cache->end()) return i->second;
347 		} else if (_pArray->items.size() >= 12) {
348 			DtaScriptVariable* pVariable = NULL;
349 			_pArray->cache = new std::map<std::string, DtaScriptVariable*>();
350 			for (std::list<DtaScriptVariable*>::const_iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
351 				if (strcmp((*i)->_tcName, sPosition.c_str()) == 0) pVariable = (*i);
352 				(*_pArray->cache)[(*i)->_tcName] = (*i);
353 			}
354 			return pVariable;
355 		} else {
356 			for (std::list<DtaScriptVariable*>::const_iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
357 				if (strcmp((*i)->_tcName, sPosition.c_str()) == 0) return (*i);
358 			}
359 		}
360 		return NULL;
361 	}
362 
getArrayElement(int iPosition) const363 	DtaScriptVariable* DtaScriptVariable::getArrayElement(int iPosition) const {
364 		if (getReferencedVariable() != NULL) return getReferencedVariable()->getArrayElement(iPosition);
365 		if (_pArray == NULL) return NULL;
366 		if (iPosition >= 0) {
367 			for (std::list<DtaScriptVariable*>::const_iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
368 				if (iPosition == 0) return (*i);
369 				iPosition--;
370 			}
371 		}
372 		return NULL;
373 	}
374 
invertArray()375 	void DtaScriptVariable::invertArray() {
376 		if (getReferencedVariable() != NULL) {
377 			getReferencedVariable()->invertArray();
378 		} else if (_pArray != NULL) {
379 			std::list<DtaScriptVariable*> array;
380 			for (std::list<DtaScriptVariable*>::iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
381 				array.push_front(*i);
382 			}
383 			_pArray->items = array;
384 			if (_pListeners != NULL) _pListeners->onArrayHasChanged();
385 		}
386 	}
387 
insertElementAt(const std::string & sProposedKey,int iPosition)388 	DtaScriptVariable* DtaScriptVariable::insertElementAt(const std::string& sProposedKey, int iPosition) {
389 		if (getReferencedVariable() != NULL) {
390 			return getReferencedVariable()->insertElementAt(sProposedKey, iPosition);
391 		}
392 		DtaScriptVariable* pVariable = NULL;
393 		std::string sKey;
394 		if (sProposedKey.empty()) {
395 			char tcNumber[32];
396 			int iKey = ((_pArray != NULL) ? _pArray->items.size() : 0);
397 			do {
398 				sprintf(tcNumber, "%d", iKey);
399 				sKey = tcNumber;
400 				++iKey;
401 			} while (getArrayElement(sKey) != NULL);
402 		} else {
403 			sKey = sProposedKey;
404 			if (getArrayElement(sKey) != NULL) return NULL;
405 		}
406 		if (_pArray != NULL) {
407 			if (iPosition >= 0) {
408 				for (std::list<DtaScriptVariable*>::iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
409 					if (iPosition == 0) {
410 						pVariable = new DtaScriptVariable(this, sKey);
411 						_pArray->items.insert(i, pVariable);
412 						if (_pArray->cache != NULL) (*_pArray->cache)[sKey] = pVariable;
413 						if (_pListeners != NULL) _pListeners->onArrayHasChanged();
414 						return pVariable;
415 					}
416 					iPosition--;
417 				}
418 				if (iPosition == 0) {
419 					pVariable = addInternalElement(sKey);
420 				}
421 			}
422 		} else if (iPosition == 0) {
423 			pVariable = addInternalElement(sKey);
424 		}
425 		return pVariable;
426 	}
427 
removeArrayElement()428 	void DtaScriptVariable::removeArrayElement() {
429 		if (getReferencedVariable() != NULL) {
430 			getReferencedVariable()->removeArrayElement();
431 		} else {
432 			delete _pArray;
433 			_pArray = NULL;
434 			if (_pListeners != NULL) _pListeners->onArrayHasChanged();
435 		}
436 	}
437 
removeArrayElement(const char * sPosition)438 	void DtaScriptVariable::removeArrayElement(const char* sPosition) {
439 		if (getReferencedVariable() != NULL) getReferencedVariable()->removeArrayElement(sPosition);
440 		else if (_pArray != NULL) {
441 			for (std::list<DtaScriptVariable*>::iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
442 				if (strcmp((*i)->_tcName, sPosition) == 0) {
443 					delete (*i);
444 					_pArray->items.erase(i);
445 					if (_pArray->cache != NULL) _pArray->cache->erase(sPosition);
446 					if (_pListeners != NULL) _pListeners->onArrayHasChanged();
447 					break;
448 				}
449 			}
450 		}
451 	}
452 
removeArrayElement(int iPosition)453 	void DtaScriptVariable::removeArrayElement(int iPosition) {
454 		if (getReferencedVariable() != NULL) getReferencedVariable()->removeArrayElement(iPosition);
455 		else if (_pArray != NULL) {
456 			if (iPosition >= 0) {
457 				for (std::list<DtaScriptVariable*>::iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
458 					if (iPosition == 0) {
459 						if (_pArray->cache != NULL) _pArray->cache->erase((*i)->_tcName);
460 						delete *i;
461 						_pArray->items.erase(i);
462 						if (_pListeners != NULL) _pListeners->onArrayHasChanged();
463 						break;
464 					}
465 					iPosition--;
466 				}
467 			}
468 		}
469 	}
470 
removeFirstElement()471 	void DtaScriptVariable::removeFirstElement() {
472 		if (getReferencedVariable() != NULL) getReferencedVariable()->removeFirstElement();
473 		else if (_pArray != NULL) {
474 			std::list<DtaScriptVariable*>::iterator cursor = _pArray->items.begin();
475 			if (cursor != _pArray->items.end()) {
476 				if (_pArray->cache != NULL) _pArray->cache->erase((*cursor)->_tcName);
477 				delete *cursor;
478 				_pArray->items.erase(cursor);
479 				if (_pListeners != NULL) _pListeners->onArrayHasChanged();
480 			}
481 		}
482 	}
483 
removeLastElement()484 	void DtaScriptVariable::removeLastElement() {
485 		if (getReferencedVariable() != NULL) getReferencedVariable()->removeLastElement();
486 		else if ((_pArray != NULL) && !_pArray->items.empty()) {
487 			DtaScriptVariable* pElt = _pArray->items.back();
488 			if (_pArray->cache != NULL) _pArray->cache->erase(pElt->_tcName);
489 			_pArray->items.remove(pElt);
490 			delete pElt;
491 			if (_pListeners != NULL) _pListeners->onArrayHasChanged();
492 		}
493 	}
494 
getCompleteName() const495 	std::string DtaScriptVariable::getCompleteName() const {
496 		std::string sName;
497 		if (_pParent != NULL) {
498 			sName = _pParent->getCompleteName();
499 			DtaScriptVariableList* pAttributes = _pParent->_pAttributes;
500 			while (pAttributes != NULL) {
501 				if (strcmp(pAttributes->getNode()->_tcName, _tcName) == 0) {
502 					if (!sName.empty()) sName += ".";
503 					sName += _tcName;
504 					return sName;
505 				}
506 				pAttributes = pAttributes->getNext();
507 			}
508 			if (_pParent->_pArray != NULL) {
509 				const std::list<DtaScriptVariable*>& pList = _pParent->_pArray->items;
510 				for (std::list<DtaScriptVariable*>::const_iterator i = pList.begin(); i != pList.end(); i++) {
511 					if (((*i) != NULL) && (strcmp((*i)->_tcName, _tcName) == 0)) {
512 						sName += "[\"" + std::string(_tcName) + "\"]";
513 						return sName;
514 					}
515 				}
516 			}
517 			sName = "";
518 		} else if (_tcName != NULL) {
519 			sName = _tcName;
520 		} else {
521 			sName = "<unnamed>";
522 		}
523 		return sName;
524 	}
525 
clearArray()526 	void DtaScriptVariable::clearArray() {
527 		delete _pArray;
528 		_pArray = NULL;
529 		if (_pListeners != NULL) _pListeners->onArrayHasChanged();
530 	}
531 
sortArray()532 	void DtaScriptVariable::sortArray() {
533 		DtaScriptVariable* pVariable = this;
534 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
535 		NodeArrayType* pANT = pVariable->_pArray;
536 		if (pANT == NULL) return;
537 		bool bPurgeCacheAfter = (pANT->cache == NULL);
538 		if (bPurgeCacheAfter) {
539 			pANT->cache = new std::map<std::string, DtaScriptVariable*>();
540 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
541 				(*(pANT->cache))[(*i)->_tcName] = (*i);
542 			}
543 		}
544 		pANT->items = std::list<DtaScriptVariable*>();
545 		std::map<std::string, DtaScriptVariable*>* mapOfElts = pANT->cache;
546 		for (std::map<std::string, DtaScriptVariable*>::const_iterator j = mapOfElts->begin(); j != mapOfElts->end(); ++j) {
547 			pANT->items.push_back(j->second);
548 		}
549 		if (bPurgeCacheAfter) {
550 			delete pANT->cache;
551 			pANT->cache = NULL;
552 		}
553 		if (_pListeners != NULL) _pListeners->onArrayHasChanged();
554 	}
555 
removeReference()556 	void DtaScriptVariable::removeReference() {
557 		_value.var->_pReferencedByVariables->erase(this);
558 		_eValueNode = NO_VALUE_NODE;
559 		if (_pListeners != NULL) _pListeners->onSetValue(NULL);
560 	}
561 
addReferencedBy(DtaScriptVariable * pVariable)562 	void DtaScriptVariable::addReferencedBy(DtaScriptVariable* pVariable) {
563 		if (pVariable != NULL) {
564 			if (_pReferencedByVariables == NULL) _pReferencedByVariables = new std::set<DtaScriptVariable*>();
565 			_pReferencedByVariables->insert(pVariable);
566 		}
567 	}
568 
getInternalVariableExtraction(DtaScriptVariable & visibility,const ExprScriptVariable & exprVariable,bool bRecursiveSearch,bool bCreateIfUnknown,bool bReferencedVariable)569 	DtaScriptVariable* DtaScriptVariable::getInternalVariableExtraction(DtaScriptVariable& visibility, const ExprScriptVariable& exprVariable, bool bRecursiveSearch, bool bCreateIfUnknown, bool bReferencedVariable) {
570 		DtaScriptVariable* pVariable = NULL;
571 		if (exprVariable.isEvaluation()) {
572 			std::string sCommand = exprVariable.getExpression()->getValue(visibility);
573 			ScpStream theCommand(sCommand);
574 			DtaScript script;
575 			CGQuietOutput quiet;
576 			std::auto_ptr<ExprScriptVariable> pExprVariable(script.parseVariableExpression(script.getBlock(), theCommand));
577 			pVariable = getInternalVariableExtraction(visibility, *pExprVariable, bRecursiveSearch, bCreateIfUnknown, bReferencedVariable);
578 			return pVariable;
579 		}
580 		if (exprVariable.getPackage() != NULL) {
581 			// the variable comes from a package
582 			pVariable = exprVariable.getPackage()->getVariable(exprVariable.getName());
583 			if (pVariable == NULL) return NULL;
584 			if (bReferencedVariable || exprVariable.isNext()) {
585 				DtaScriptVariable* pRefVar = pVariable->getReferencedVariable();
586 				if (pRefVar != NULL) pVariable = pRefVar;
587 			}
588 		} else {
589 			if (bReferencedVariable || exprVariable.isNext()) pVariable = getReferencedVariable();
590 			if (pVariable == NULL) {
591 				bool bExtractVariableWithReference = bReferencedVariable || !exprVariable.isAttributeOnly();
592 				std::string sName = exprVariable.getName();
593 				pVariable = getVariable(sName.c_str(), bRecursiveSearch, bCreateIfUnknown, bExtractVariableWithReference);
594 				if (pVariable == NULL) return NULL;
595 			}
596 		}
597 		if (exprVariable.isArrayKey()) {
598 			std::string sPosition = exprVariable.getExpression()->getValue(visibility);
599 			DtaScriptVariable* pArrayElement = pVariable->getArrayElement(sPosition);
600 			if (pArrayElement == NULL) {
601 				if (bCreateIfUnknown) {
602 					pArrayElement = pVariable->addInternalElement(sPosition);
603 				} else {
604 					return NULL;
605 				}
606 				pVariable = pArrayElement;
607 			} else {
608 				if (bReferencedVariable || exprVariable.isNext()) {
609 					pVariable = pArrayElement->getReferencedVariable();
610 					if (pVariable == NULL) pVariable = pArrayElement;
611 				} else {
612 					pVariable = pArrayElement;
613 				}
614 			}
615 		} else if (exprVariable.isArrayPosition()) {
616 			std::string sPosition = exprVariable.getExpression()->getValue(visibility);
617 			if (sPosition == "parent") {
618 				register DtaScriptVariable* pParent = pVariable->getParent();
619 				if ((pParent != NULL) && (strncmp(pParent->_tcName, "##stack##", 9) != 0)) pVariable = pParent;
620 			} else if (sPosition == "root") {
621 				register DtaScriptVariable* pParent = pVariable->getParent();
622 				while ((pParent != NULL) && (strncmp(pParent->_tcName, "##stack##", 9) != 0)) {
623 					pVariable = pParent;
624 					pParent = pVariable->getParent();
625 				}
626 			} else {
627 				int iPosition;
628 				if (sPosition == "back") iPosition = pVariable->getArraySize() - 1;
629 				else iPosition = atoi(sPosition.c_str());
630 				DtaScriptVariable* pArrayElement = pVariable->getArrayElement(iPosition);
631 				if (pArrayElement == NULL) throw UtlException(std::string("Array index is out of bounds on variable '" + exprVariable.toString() + "': \"") + sPosition + "\"");
632 				pVariable = pArrayElement;
633 				if (bReferencedVariable || exprVariable.isNext()) {
634 					pVariable = pVariable->getReferencedVariable();
635 					if (pVariable == NULL) pVariable = pArrayElement;
636 				}
637 			}
638 		}
639 		if (exprVariable.isNext()) {
640 			pVariable = pVariable->getInternalVariableExtraction(visibility, *(exprVariable.getNext()), false, bCreateIfUnknown, bReferencedVariable);
641 		}
642 		return pVariable;
643 	}
644 
getVariable(const ExprScriptVariable & exprVariable)645 	DtaScriptVariable* DtaScriptVariable::getVariable(const ExprScriptVariable& exprVariable) {
646 		return getInternalVariableExtraction(*this, exprVariable, true, true, true);
647 	}
648 
getNonRecursiveVariable(DtaScriptVariable & visibility,const ExprScriptVariable & exprVariable)649 	DtaScriptVariable* DtaScriptVariable::getNonRecursiveVariable(DtaScriptVariable& visibility, const ExprScriptVariable& exprVariable) {
650 		return getInternalVariableExtraction(visibility, exprVariable, false, true, true);
651 	}
652 
getNonRecursiveNonReferencedVariable(DtaScriptVariable & visibility,const ExprScriptVariable & exprVariable)653 	DtaScriptVariable* DtaScriptVariable::getNonRecursiveNonReferencedVariable(DtaScriptVariable& visibility, const ExprScriptVariable& exprVariable) {
654 		return getInternalVariableExtraction(visibility, exprVariable, false, true, false);
655 	}
656 
getVariableForReferenceAssignment(const ExprScriptVariable & exprVariable)657 	DtaScriptVariable* DtaScriptVariable::getVariableForReferenceAssignment(const ExprScriptVariable& exprVariable) {
658 		return getInternalVariableExtraction(*this, exprVariable, true, true, false);
659 	}
660 
getExistingVariable(const ExprScriptVariable & exprVariable)661 	DtaScriptVariable* DtaScriptVariable::getExistingVariable(const ExprScriptVariable& exprVariable) {
662 		DtaScriptVariable* pVariable = getInternalVariableExtraction(*this, exprVariable, true, false, true);
663 		if ((pVariable == NULL) && Workspace::warningOnUnknownVariables()) {
664 			std::string sErrorMessage = "warning: variable '" + exprVariable.toString() + "' doesn't exist yet" + CGRuntime::endl();
665 			sErrorMessage += UtlTrace::getTraceStack();
666 			if (DtaProject::getInstance().addWarning(sErrorMessage) == 1) CGRuntime::traceLine(sErrorMessage);
667 		}
668 		return pVariable;
669 	}
670 
getNoWarningExistingVariable(const ExprScriptVariable & exprVariable)671 	DtaScriptVariable* DtaScriptVariable::getNoWarningExistingVariable(const ExprScriptVariable& exprVariable) {
672 		return getInternalVariableExtraction(*this, exprVariable, true, false, true);
673 	}
674 
675 
getNonRecursiveVariable(const char * sName)676 	DtaScriptVariable* DtaScriptVariable::getNonRecursiveVariable(const char* sName) {
677 		return getVariable(sName, false, true, true);
678 	}
679 
getVariable(const char * sName,bool bRecursiveSearch,bool bCreateIfUnknown,bool bReferencedVariable)680 	DtaScriptVariable* DtaScriptVariable::getVariable(const char* sName, bool bRecursiveSearch, bool bCreateIfUnknown, bool bReferencedVariable) {
681 		DtaScriptVariable* pVariable = NULL;
682 		if (*sName == '\0') return this;
683 		if (bRecursiveSearch) {
684 			if (strcmp(sName, "project") == 0) return &(DtaProject::getInstance());
685 			if (strcmp(sName, "this") == 0) {
686 				DtaScriptVariable* pThis = &CGRuntime::getThisInternalNode();
687 				if (pThis == NULL) throw UtlException("INTERNAL ERROR: NULL 'this'!");
688 				return pThis;
689 			}
690 			if (strcmp(sName, "null") == 0) return NULL;
691 		}
692 		DtaScriptVariableList* pAttributes = _pAttributes;
693 		DtaScriptVariableList* pLastAttribute = _pAttributes;
694 		while (pAttributes != NULL) {
695 			if (strcmp(pAttributes->getNode()->_tcName, sName) == 0) {
696 				pVariable = pAttributes->getNode();
697 				if (bReferencedVariable && (pVariable->getReferencedVariable() != NULL)) {
698 					do pVariable = pVariable->getReferencedVariable(); while (pVariable->getReferencedVariable() != NULL);
699 				}
700 				break;
701 			}
702 			if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
703 			pAttributes = pAttributes->getNext();
704 		}
705 		if (pAttributes == NULL) {
706 			if (bRecursiveSearch) {
707 	//			pVariable = _pParent->getVariable(sName, true, false, bReferencedVariable);
708 				// we are looking for the variable into local variables, above the function call
709 				DtaScriptVariable* pLocalScope = NULL;
710 				bool bClause = false;
711 				if ((strncmp(_tcName, "##stack## ", 10) == 0) && (strncmp(_tcName + 10, "function", 8) != 0) && (strncmp(_tcName + 10, "clause", 6) != 0)) {
712 					pLocalScope = getParent();
713 					while ((pVariable == NULL) && (pLocalScope != NULL) && (pLocalScope->_tcName != NULL) && (strncmp(pLocalScope->_tcName, "##stack##", 9) == 0)) {
714 						pVariable = pLocalScope->getVariable(sName, false, false, bReferencedVariable);
715 						const char* tcFunction = pLocalScope->_tcName + 10;
716 						if (strncmp(tcFunction, "function", 8) == 0) break;
717 						if (strncmp(tcFunction, "clause", 6) == 0) {
718 							bClause = true;
719 							break;
720 						}
721 						pLocalScope = pLocalScope->getParent();
722 					}
723 				}
724 				if ((pVariable == NULL) && !bClause) {
725 					// the variable doesn't belong to the stack, perhaps it is a node of the current subtree
726 					DtaScriptVariable* pThis = &CGRuntime::getThisInternalNode();
727 					if (pThis == 0) throw UtlException("INTERNAL ERROR: NULL 'this'!");
728 					pVariable = pThis->getVariable(sName, false, false, bReferencedVariable);
729 					int tiVersion[] = {1, 13, -1};
730 					if ((pVariable == NULL) && (pLocalScope != NULL) && DtaProject::getInstance().isScriptVersionOlderThan(tiVersion)) {
731 						// this is an old version of scripts, so variable may be stored
732 						// into the stack, above the function call
733 						while ((pVariable == NULL) && (pLocalScope->_tcName != NULL) && (strncmp(pLocalScope->_tcName, "##stack##", 9) == 0)) {
734 							pVariable = pLocalScope->getVariable(sName, false, false, bReferencedVariable);
735 							pLocalScope = pLocalScope->getParent();
736 						}
737 						if (pVariable != NULL) {
738 							std::string sErrorMessage = "since version 1.13, the scope of a local variable is restricted to the function it is declared into, so a change of behaviour may occur when looking at local variable '";
739 							sErrorMessage += sName;
740 							sErrorMessage += "'" + UtlTrace::getTraceStack();
741 							if (DtaProject::getInstance().addWarning(sErrorMessage) == 1) CGRuntime::traceLine(sErrorMessage);
742 							pVariable = NULL;
743 						}
744 					}
745 				}
746 			}
747 			if (pVariable == NULL) {
748 				if (bRecursiveSearch) pVariable = DtaProject::getInstance().getGlobalVariable(sName);
749 				if ((pVariable == NULL) && bCreateIfUnknown) {
750 					pVariable = new DtaScriptVariable(this, sName);
751 					if (_pAttributes == NULL) _pAttributes = new DtaScriptVariableList(pVariable);
752 					else pLastAttribute->pushBack(pVariable);
753 					if (_pListeners != NULL) _pListeners->onAddAttribute(pVariable);
754 				}
755 			}
756 		}
757 		return pVariable;
758 	}
759 
getNode(const char * sName)760 	DtaScriptVariable* DtaScriptVariable::getNode(const char* sName) {
761 		DtaScriptVariable* pVariable = this;
762 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
763 		return pVariable->getVariable(sName, false, false, true);
764 	}
765 
insertNode(const char * sName)766 	DtaScriptVariable* DtaScriptVariable::insertNode(const char* sName) {
767 		DtaScriptVariable* pVariable = this;
768 		while (pVariable->getReferencedVariable() != NULL) pVariable = pVariable->getReferencedVariable();
769 		return pVariable->getVariable(sName, false, true, true);
770 	}
771 
getEvaluatedNode(const std::string & sDynamicVariable)772 	DtaScriptVariable* DtaScriptVariable::getEvaluatedNode(const std::string& sDynamicVariable) {
773 		ScpStream theCommand(sDynamicVariable);
774 		DtaScript script;
775 		std::auto_ptr<ExprScriptVariable> pExprVariable(script.parseVariableExpression(script.getBlock(), theCommand));
776 		DtaScriptVariable* pVariable = getInternalVariableExtraction(*this, *pExprVariable, true/*bRecursiveSearch*/, false/*bCreateIfUnknown*/, true/*bReferencedVariable*/);
777 		return pVariable;
778 	}
779 
getOrCreateLocalEvaluatedNode(const std::string & sDynamicVariable)780 	DtaScriptVariable* DtaScriptVariable::getOrCreateLocalEvaluatedNode(const std::string& sDynamicVariable) {
781 		ScpStream theCommand(sDynamicVariable);
782 		DtaScript script;
783 		std::auto_ptr<ExprScriptVariable> pExprVariable(script.parseVariableExpression(script.getBlock(), theCommand));
784 		DtaScriptVariable* pVariable = getInternalVariableExtraction(*this, *pExprVariable, true/*bRecursiveSearch*/, true/*bCreateIfUnknown*/, true/*bReferencedVariable*/);
785 		return pVariable;
786 	}
787 
insertEvaluatedNode(const std::string & sDynamicVariable)788 	DtaScriptVariable* DtaScriptVariable::insertEvaluatedNode(const std::string& sDynamicVariable) {
789 		ScpStream theCommand(sDynamicVariable);
790 		DtaScript script;
791 		std::auto_ptr<ExprScriptVariable> pExprVariable(script.parseVariableExpression(script.getBlock(), theCommand));
792 		DtaScriptVariable* pVariable = getInternalVariableExtraction(*this, *pExprVariable, true/*bRecursiveSearch*/, true/*bCreateIfUnknown*/, true/*bReferencedVariable*/);
793 		return pVariable;
794 	}
795 
insertClassicalEvaluatedNode(const std::string & sDynamicVariable)796 	DtaScriptVariable* DtaScriptVariable::insertClassicalEvaluatedNode(const std::string& sDynamicVariable) {
797 		ScpStream theCommand(sDynamicVariable);
798 		DtaScript script;
799 		std::auto_ptr<ExprScriptVariable> pExprVariable(script.parseVariableExpression(script.getBlock(), theCommand));
800 		DtaScriptVariable* pVariable = getInternalVariableExtraction(*this, *pExprVariable, true/*bRecursiveSearch*/, true/*bCreateIfUnknown*/, true/*bReferencedVariable*/);
801 		return pVariable;
802 	}
803 
moveToNode(DtaScriptVariable & node)804 	void DtaScriptVariable::moveToNode(DtaScriptVariable& node) {
805 		if (node._pAttributes == NULL) {
806 			node._pAttributes = _pAttributes;
807 		} else {
808 			DtaScriptVariableList* pAttributes = node._pAttributes;
809 			while (pAttributes->getNext() != NULL) pAttributes = pAttributes->getNext();
810 			pAttributes->setNext(_pAttributes);
811 		}
812 		_pAttributes = NULL;
813 		if (node._pArray == NULL) {
814 			node._pArray = _pArray;
815 		} else {
816 			while (!_pArray->items.empty()) {
817 				node._pArray->items.push_back(_pArray->items.back());
818 				_pArray->items.pop_back();
819 			}
820 			delete node._pArray->cache;
821 			node._pArray->cache = NULL;
822 			delete _pArray;
823 		}
824 		_pArray = NULL;
825 		node._eValueNode = _eValueNode;
826 		node._value = _value;
827 		_eValueNode = NO_VALUE_NODE;
828 	}
829 
createNodeArgument(const char * sName,DtaScriptVariable * pParameter)830 	DtaScriptVariable* DtaScriptVariable::createNodeArgument(const char* sName, DtaScriptVariable* pParameter) {
831 		DtaScriptVariable* pIndex = NULL;
832 		DtaScriptVariableList* pAttributes = _pAttributes;
833 		DtaScriptVariableList* pLastAttribute = _pAttributes;
834 		while (pAttributes != NULL) {
835 			if (strcmp(pAttributes->getNode()->_tcName, sName) == 0) {
836 				pIndex = pAttributes->getNode();
837 				break;
838 			}
839 			if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
840 			pAttributes = pAttributes->getNext();
841 		}
842 		if (pAttributes == NULL) {
843 			pIndex = new DtaScriptVariable(this, sName);
844 			if (_pAttributes == NULL) _pAttributes = new DtaScriptVariableList(pIndex);
845 			else pLastAttribute->pushBack(pIndex);
846 			if (_pListeners != NULL) _pListeners->onAddAttribute(pIndex);
847 		}
848 		pIndex->setValue(pParameter);
849 		return pIndex;
850 	}
851 
getNodeArgument(const char * sName) const852 	DtaScriptVariable* DtaScriptVariable::getNodeArgument(const char* sName) const {
853 		DtaScriptVariable* pIndex = NULL;
854 		DtaScriptVariableList* pAttributes = _pAttributes;
855 		DtaScriptVariableList* pLastAttribute = _pAttributes;
856 		while (pAttributes != NULL) {
857 			if (strcmp(pAttributes->getNode()->_tcName, sName) == 0) {
858 				pIndex = pAttributes->getNode();
859 				break;
860 			}
861 			if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
862 			pAttributes = pAttributes->getNext();
863 		}
864 		if (pAttributes == NULL) {
865 			if (_pParent != NULL) pIndex = _pParent->getNodeArgument(sName);
866 			if (pIndex == NULL) {
867 				throw UtlException(std::string("unable to find argument called '") + sName + "'");
868 			}
869 		}
870 		return pIndex;
871 	}
872 
createIterator(const char * sName,DtaArrayIterator ** pIteratorData)873 	DtaScriptVariable* DtaScriptVariable::createIterator(const char* sName, DtaArrayIterator** pIteratorData) {
874 		DtaScriptVariable* pIndex = NULL;
875 		DtaScriptVariableList* pAttributes = _pAttributes;
876 		DtaScriptVariableList* pLastAttribute = _pAttributes;
877 		while (pAttributes != NULL) {
878 			if (strcmp(pAttributes->getNode()->_tcName, sName) == 0) {
879 				pIndex = pAttributes->getNode();
880 				break;
881 			}
882 			if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
883 			pAttributes = pAttributes->getNext();
884 		}
885 		if (pAttributes == NULL) {
886 			pIndex = new DtaScriptVariable(this, sName);
887 			if (_pAttributes == NULL) _pAttributes = new DtaScriptVariableList(pIndex);
888 			else pLastAttribute->pushBack(pIndex);
889 			if (_pListeners != NULL) _pListeners->onAddAttribute(pIndex);
890 		}
891 		pIndex->setIteratorData(pIteratorData);
892 		return pIndex;
893 	}
894 
getIterator(const char * sName) const895 	DtaScriptVariable* DtaScriptVariable::getIterator(const char* sName) const {
896 		DtaScriptVariable* pIndex = NULL;
897 		DtaScriptVariableList* pAttributes = _pAttributes;
898 		DtaScriptVariableList* pLastAttribute = _pAttributes;
899 		while (pAttributes != NULL) {
900 			if (strcmp(pAttributes->getNode()->_tcName, sName) == 0) {
901 				pIndex = pAttributes->getNode();
902 				break;
903 			}
904 			if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
905 			pAttributes = pAttributes->getNext();
906 		}
907 		if (pAttributes == NULL) {
908 			if (_pParent != NULL) pIndex = _pParent->getIterator(sName);
909 		}
910 		if (pIndex != NULL) {
911 			while (pIndex->_eValueNode == REFERENCE_VALUE_NODE) pIndex = pIndex->_value.var;
912 			if (pIndex->_eValueNode != INDEX_VALUE_NODE) return NULL;
913 		}
914 		return pIndex;
915 	}
916 
getIteratorData() const917 	DtaArrayIterator* DtaScriptVariable::getIteratorData() const {
918 		if (_eValueNode != INDEX_VALUE_NODE) return NULL;
919 		return *_value.ind.var;
920 	}
921 
addElement(int iKey)922 	DtaScriptVariable* DtaScriptVariable::addElement(int iKey) {
923 		char tcKey[32];
924 		sprintf(tcKey, "%d", iKey);
925 		return addElement(tcKey);
926 	}
927 
addElement(const std::string & sName)928 	DtaScriptVariable* DtaScriptVariable::addElement(const std::string& sName) {
929 		DtaScriptVariable* pVariable = getArrayElement(sName);
930 		if (pVariable == NULL) pVariable = addInternalElement(sName);
931 		return pVariable;
932 	}
933 
addInternalElement(const std::string & sName)934 	DtaScriptVariable* DtaScriptVariable::addInternalElement(const std::string& sName) {
935 		DtaScriptVariable* pVariable = new DtaScriptVariable(this, sName);
936 		if (_pArray == NULL) _pArray = new NodeArrayType(pVariable);
937 		else {
938 			_pArray->items.push_back(pVariable);
939 			if (_pArray->cache != NULL) (*_pArray->cache)[sName] = pVariable;
940 		}
941 		if (_pListeners != NULL) _pListeners->onArrayHasChanged();
942 		return pVariable;
943 	}
944 
setValueAtVariable(const char * sVariable,const char * sValue,bool bRecursiveSearch,bool bCreateIfUnknown)945 	void DtaScriptVariable::setValueAtVariable(const char* sVariable, const char* sValue, bool bRecursiveSearch, bool bCreateIfUnknown) {
946 		getVariable(sVariable, bRecursiveSearch, bCreateIfUnknown)->setValue(sValue);
947 	}
948 
getValue() const949 	const char* DtaScriptVariable::getValue() const {
950 		if (_eValueNode == STRING_VALUE_NODE) return _value.str.text;
951 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var->getValue();
952 		if (_eValueNode == EXTERNAL_VALUE_NODE) return _value.ext->getValue();
953 		if (_eValueNode == INDEX_VALUE_NODE) return (*_value.ind.var)->item()->getValue();
954 		return NULL;
955 	}
956 
getValueLength() const957 	size_t DtaScriptVariable::getValueLength() const {
958 		if (_eValueNode == STRING_VALUE_NODE) return _value.str.length;
959 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var->getValueLength();
960 		if (_eValueNode == EXTERNAL_VALUE_NODE) return _value.ext->getValueLength();
961 		if (_eValueNode == INDEX_VALUE_NODE) return (*_value.ind.var)->item()->getValueLength();
962 		return 0;
963 	}
964 
getDoubleValue() const965 	double DtaScriptVariable::getDoubleValue() const {
966 		if (_eValueNode == STRING_VALUE_NODE) return atof(_value.str.text);
967 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var->getDoubleValue();
968 		if (_eValueNode == EXTERNAL_VALUE_NODE) return _value.ext->getDoubleValue();
969 		if (_eValueNode == INDEX_VALUE_NODE) return (*_value.ind.var)->item()->getDoubleValue();
970 		return 0.0;
971 	}
972 
getBooleanValue() const973 	bool DtaScriptVariable::getBooleanValue() const {
974 		if (_eValueNode == STRING_VALUE_NODE) return (_value.str.length != 0);
975 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var->getBooleanValue();
976 		if (_eValueNode == EXTERNAL_VALUE_NODE) return _value.ext->getBooleanValue();
977 		if (_eValueNode == INDEX_VALUE_NODE) return (*_value.ind.var)->item()->getBooleanValue();
978 		return false;
979 	}
980 
getIntValue() const981 	int DtaScriptVariable::getIntValue() const {
982 		if (_eValueNode == STRING_VALUE_NODE) return atoi(_value.str.text);
983 		if (_eValueNode == REFERENCE_VALUE_NODE) return _value.var->getIntValue();
984 		if (_eValueNode == EXTERNAL_VALUE_NODE) return _value.ext->getIntValue();
985 		if (_eValueNode == INDEX_VALUE_NODE) return (*_value.ind.var)->item()->getIntValue();
986 		return 0;
987 	}
988 
clearValue()989 	void DtaScriptVariable::clearValue() {
990 		if (_eValueNode == REFERENCE_VALUE_NODE) {
991 			removeReference();
992 		} else if (_eValueNode == INDEX_VALUE_NODE) {
993 			if (_value.ind.own) {
994 				delete *_value.ind.var;
995 				delete _value.ind.var;
996 			}
997 		} else if (_eValueNode == STRING_VALUE_NODE) {
998 			delete [] _value.str.text;
999 		} else if (_eValueNode == EXTERNAL_VALUE_NODE) {
1000 			EXTERNAL_VALUE_NODE_DESTRUCTOR f = _value.ext->getDestructor();
1001 			if (f != NULL) f(_value.ext);
1002 		}
1003 		_eValueNode = NO_VALUE_NODE;
1004 	}
1005 
setValue(const char * tcValue)1006 	void DtaScriptVariable::setValue(const char* tcValue) {
1007 		if (_pListeners != NULL) _pListeners->onSetValue(tcValue);
1008 		if ((tcValue == NULL) || (*tcValue == '\0')) {
1009 			clearValue();
1010 		} else {
1011 			size_t iLength = strlen(tcValue);
1012 			if (_eValueNode == STRING_VALUE_NODE) {
1013 				if (iLength > _value.str.length) {
1014 					delete [] _value.str.text;
1015 					_value.str.text = new char[iLength + 1];
1016 				}
1017 			} else {
1018 				if (_eValueNode == REFERENCE_VALUE_NODE) {
1019 					removeReference();
1020 				} else if (_eValueNode == INDEX_VALUE_NODE) {
1021 					if (_value.ind.own) {
1022 						delete *_value.ind.var;
1023 						delete _value.ind.var;
1024 					}
1025 				} else if (_eValueNode == EXTERNAL_VALUE_NODE) {
1026 					EXTERNAL_VALUE_NODE_DESTRUCTOR f = _value.ext->getDestructor();
1027 					if (f != NULL) f(_value.ext);
1028 				}
1029 				_value.str.text = new char[iLength + 1];
1030 			}
1031 			strcpy(_value.str.text, tcValue);
1032 			_value.str.length = iLength;
1033 			_eValueNode = STRING_VALUE_NODE;
1034 		}
1035 	}
1036 
setValue(bool bValue)1037 	void DtaScriptVariable::setValue(bool bValue) {
1038 		setValue(((bValue) ? "true" : NULL));
1039 	}
1040 
setValue(double dValue)1041 	void DtaScriptVariable::setValue(double dValue) {
1042 		std::string sDouble = CGRuntime::toString(dValue);
1043 		setValue(sDouble.c_str());
1044 	}
1045 
setValue(int iValue)1046 	void DtaScriptVariable::setValue(int iValue) {
1047 		char tcNumber[16];
1048 		sprintf(tcNumber, "%d", iValue);
1049 		setValue(tcNumber);
1050 	}
1051 
setValue(const std::list<std::string> & listOfValues)1052 	void DtaScriptVariable::setValue(const std::list<std::string>& listOfValues) {
1053 		int iIndex = 0;
1054 		char sNumber[16];
1055 		clearArray();
1056 		for (std::list<std::string>::const_iterator i = listOfValues.begin(); i != listOfValues.end(); i++) {
1057 			sprintf(sNumber, "%d", iIndex);
1058 			addElement(sNumber)->setValue(i->c_str());
1059 			iIndex++;
1060 		}
1061 		if (_pListeners != NULL) _pListeners->onArrayHasChanged();
1062 	}
1063 
setValue(DtaScriptVariable * pVariable)1064 	void DtaScriptVariable::setValue(DtaScriptVariable* pVariable) {
1065 		if (pVariable != NULL) {
1066 			if (pVariable == this) throw UtlException("DtaScriptVariable::setValue() cyclic reference");
1067 			while (pVariable->_eValueNode == REFERENCE_VALUE_NODE) {
1068 				pVariable = pVariable->getReferencedVariable();
1069 				if (pVariable == this) throw UtlException("DtaScriptVariable::setValue() cyclic reference");
1070 			}
1071 		}
1072 		clearValue();
1073 		if (pVariable != NULL) {
1074 			_eValueNode = REFERENCE_VALUE_NODE;
1075 			_value.var = pVariable;
1076 			_value.var->addReferencedBy(this);
1077 			if (_pListeners != NULL) _pListeners->onSetReference(pVariable);
1078 		}
1079 	}
1080 
setValue(ExternalValueNode * pExternalValue)1081 	void DtaScriptVariable::setValue(ExternalValueNode* pExternalValue) {
1082 		if ((_eValueNode == EXTERNAL_VALUE_NODE) && (pExternalValue == _value.ext)) return;
1083 		clearValue();
1084 		_eValueNode = EXTERNAL_VALUE_NODE;
1085 		_value.ext = pExternalValue;
1086 		if (_pListeners != NULL) _pListeners->onSetExternal(pExternalValue);
1087 	}
1088 
setValue(DtaArrayIterator * pIteratorData)1089 	void DtaScriptVariable::setValue(DtaArrayIterator* pIteratorData) {
1090 		DtaArrayIterator** ppIteratorData = new DtaArrayIterator*;
1091 		*ppIteratorData = pIteratorData;
1092 		setIteratorData(ppIteratorData);
1093 		_value.ind.own = true;
1094 	}
1095 
setIteratorData(DtaArrayIterator ** pIteratorData)1096 	void DtaScriptVariable::setIteratorData(DtaArrayIterator** pIteratorData) {
1097 		clearValue();
1098 		_eValueNode = INDEX_VALUE_NODE;
1099 		_value.ind.var = pIteratorData;
1100 		_value.ind.own = false;
1101 		if (_pListeners != NULL) _pListeners->onSetIterator(pIteratorData);
1102 	}
1103 
concatValue(const char * tcValue)1104 	void DtaScriptVariable::concatValue(const char* tcValue) {
1105 		if (_pListeners != NULL) _pListeners->onConcatValue(tcValue);
1106 		if ((tcValue != NULL) && (*tcValue != '\0')) {
1107 			size_t iLength = strlen(tcValue);
1108 			if (_eValueNode == STRING_VALUE_NODE) {
1109 				char* tcOld = _value.str.text;
1110 				_value.str.text = new char[_value.str.length + iLength + 1];
1111 				memcpy(_value.str.text, tcOld, _value.str.length);
1112 				strcpy(_value.str.text + _value.str.length, tcValue);
1113 				_value.str.length += iLength;
1114 				delete [] tcOld;
1115 			} else {
1116 				if (_eValueNode == REFERENCE_VALUE_NODE) {
1117 					removeReference();
1118 				} else if (_eValueNode == INDEX_VALUE_NODE) {
1119 					if (_value.ind.own) {
1120 						delete *_value.ind.var;
1121 						delete _value.ind.var;
1122 					}
1123 				} else if (_eValueNode == EXTERNAL_VALUE_NODE) {
1124 					EXTERNAL_VALUE_NODE_DESTRUCTOR f = _value.ext->getDestructor();
1125 					if (f != NULL) f(_value.ext);
1126 				}
1127 				_value.str.text = new char[iLength + 1];
1128 				strcpy(_value.str.text, tcValue);
1129 				_value.str.length = iLength;
1130 				_eValueNode = STRING_VALUE_NODE;
1131 			}
1132 		}
1133 	}
1134 
remove(DtaScriptVariable * pVariable)1135 	void DtaScriptVariable::remove(DtaScriptVariable* pVariable) {
1136 		if (getReferencedVariable() != NULL) getReferencedVariable()->remove(pVariable);
1137 		else {
1138 			if (_pAttributes != NULL) {
1139 				if (_pAttributes->getNode() == pVariable) {
1140 					DtaScriptVariableList* pNext = _pAttributes->getNext();
1141 					if (_pListeners != NULL) _pListeners->onRemoveAttribute(pVariable);
1142 					delete pVariable;
1143 					_pAttributes->setNext(NULL);
1144 					delete _pAttributes;
1145 					_pAttributes = pNext;
1146 					return;
1147 				} else {
1148 					DtaScriptVariableList* pAttributes = _pAttributes;
1149 					DtaScriptVariableList* pNext = pAttributes->getNext();
1150 					while (pNext != NULL) {
1151 						if (pNext->getNode() == pVariable) {
1152 							if (_pListeners != NULL) _pListeners->onRemoveAttribute(pVariable);
1153 							pAttributes->setNext(pNext->getNext());
1154 							delete pVariable;
1155 							pNext->setNext(NULL);
1156 							delete pNext;
1157 							return;
1158 						}
1159 						pAttributes = pNext;
1160 						pNext = pNext->getNext();
1161 					}
1162 				}
1163 			}
1164 			if (_pArray != NULL) {
1165 				for (std::list<DtaScriptVariable*>::iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
1166 					if ((*i) == pVariable) {
1167 						std::string sPosition = pVariable->getName();
1168 						delete (*i);
1169 						_pArray->items.erase(i);
1170 						if (_pArray->cache != NULL) _pArray->cache->erase(sPosition);
1171 						if (_pListeners != NULL) _pListeners->onArrayHasChanged();
1172 						return;
1173 					}
1174 				}
1175 			}
1176 		}
1177 	}
1178 
remove(const char * sAttribute)1179 	void DtaScriptVariable::remove(const char* sAttribute) {
1180 		if (_pAttributes != NULL) {
1181 			if (strcmp(_pAttributes->getNode()->_tcName, sAttribute) == 0) {
1182 				if (_pListeners != NULL) _pListeners->onRemoveAttribute(_pAttributes->getNode());
1183 				DtaScriptVariableList* pNext = _pAttributes->getNext();
1184 				delete _pAttributes->getNode();
1185 				_pAttributes->setNext(NULL);
1186 				delete _pAttributes;
1187 				_pAttributes = pNext;
1188 			} else {
1189 				DtaScriptVariableList* pAttributes = _pAttributes;
1190 				DtaScriptVariableList* pNext = pAttributes->getNext();
1191 				while (pNext != NULL) {
1192 					if (strcmp(pNext->getNode()->_tcName, sAttribute) == 0) {
1193 						if (_pListeners != NULL) _pListeners->onRemoveAttribute(pNext->getNode());
1194 						pAttributes->setNext(pNext->getNext());
1195 						delete pNext->getNode();
1196 						pNext->setNext(NULL);
1197 						delete pNext;
1198 						break;
1199 					}
1200 					pAttributes = pNext;
1201 					pNext = pNext->getNext();
1202 				}
1203 			}
1204 		}
1205 	}
1206 
removeRecursive(const char * sAttribute)1207 	void DtaScriptVariable::removeRecursive(const char* sAttribute) {
1208 		remove(sAttribute);
1209 		if (_pAttributes != NULL) {
1210 			DtaScriptVariableList* pAttributes = _pAttributes;
1211 			while (pAttributes != NULL) {
1212 				pAttributes->getNode()->removeRecursive(sAttribute);
1213 				pAttributes = pAttributes->getNext();
1214 			}
1215 		}
1216 		if (_pArray != NULL) {
1217 			for (std::list<DtaScriptVariable*>::iterator j = _pArray->items.begin(); j != _pArray->items.end(); j++) {
1218 				if ((*j)->getParent() == this) (*j)->removeRecursive(sAttribute);
1219 			}
1220 		}
1221 	}
1222 
clearContent()1223 	void DtaScriptVariable::clearContent() {
1224 		clearValue();
1225 		while (_pAttributes != NULL) {
1226 			DtaScriptVariableList* pCurrent = _pAttributes;
1227 			_pAttributes = pCurrent->getNext();
1228 			delete pCurrent->getNode();
1229 			pCurrent->setNext(NULL);
1230 			delete pCurrent;
1231 		}
1232 		clearArray();
1233 		if (_pListeners != NULL) _pListeners->onClearContent();
1234 	}
1235 
addArrayElements(const DtaScriptVariable & variable)1236 	void DtaScriptVariable::addArrayElements(const DtaScriptVariable& variable) {
1237 		NodeArrayType* pANT = variable._pArray;
1238 		if ((pANT != NULL) && !pANT->items.empty()) {
1239 			if (_pArray == NULL) _pArray = new NodeArrayType;
1240 			for (std::list<DtaScriptVariable*>::const_iterator j = pANT->items.begin(); j != pANT->items.end(); j++) {
1241 				DtaScriptVariable* pVariable = new DtaScriptVariable(this, (*j)->_tcName);
1242 				pVariable->copyAll(*(*j), false);
1243 				pVariable->setValue((*j)->getValue());
1244 				_pArray->items.push_back(pVariable);
1245 				if (_pArray->cache != NULL) (*_pArray->cache)[pVariable->_tcName] = pVariable;
1246 			}
1247 			if (_pListeners != NULL) _pListeners->onArrayHasChanged();
1248 		}
1249 	}
1250 
getNumberOfAttributes() const1251 	int DtaScriptVariable::getNumberOfAttributes() const {
1252 		int iSize = 0;
1253 		DtaScriptVariableList* pVariableAttributes = _pAttributes;
1254 		while (pVariableAttributes != NULL) {
1255 			iSize++;
1256 			pVariableAttributes = pVariableAttributes->getNext();
1257 		}
1258 		return iSize;
1259 	}
1260 
equal(const DtaScriptVariable & variable)1261 	bool DtaScriptVariable::equal(const DtaScriptVariable& variable) {
1262 		if (_pArray == NULL) {
1263 			if (variable._pArray != NULL) {
1264 				if (!variable._pArray->items.empty()) return false;
1265 			}
1266 		} else if (variable._pArray == NULL) {
1267 			if (!_pArray->items.empty()) return false;
1268 			delete _pArray;
1269 			_pArray = NULL;
1270 		} else if (_pArray->items.size() != variable._pArray->items.size()) return false;
1271 		if (_eValueNode != variable._eValueNode) return false;
1272 		if (_eValueNode == REFERENCE_VALUE_NODE) {
1273 			if (_value.var != variable._value.var) return false;
1274 		} else if (_eValueNode == INDEX_VALUE_NODE) {
1275 			if ((*_value.ind.var)->item() != (*variable._value.ind.var)->item()) return false;
1276 		} else if (_eValueNode == STRING_VALUE_NODE) {
1277 			if (strcmp(_value.str.text, variable._value.str.text) != 0) return false;
1278 		} else if (_eValueNode == EXTERNAL_VALUE_NODE) {
1279 			if (_value.ext != variable._value.ext) return false;
1280 		}
1281 		DtaScriptVariableList* pAttributes = _pAttributes;
1282 		if (getNumberOfAttributes() != variable.getNumberOfAttributes()) return false;
1283 		while (pAttributes != NULL) {
1284 			DtaScriptVariableList* pVariableAttributes = variable._pAttributes;
1285 			DtaScriptVariable* pVariable = pAttributes->getNode();
1286 			while (pVariableAttributes != NULL) {
1287 				if (strcmp(pVariable->_tcName, pVariableAttributes->getNode()->_tcName) == 0) {
1288 					if (!pVariable->equal(*(pVariableAttributes->getNode()))) return false;
1289 					break;
1290 				}
1291 				pVariableAttributes = pVariableAttributes->getNext();
1292 			}
1293 			if (pVariableAttributes == NULL) return false;
1294 			pAttributes = pAttributes->getNext();
1295 		}
1296 		std::list<DtaScriptVariable*>::iterator i;
1297 		std::list<DtaScriptVariable*>::const_iterator j;
1298 		if (_pArray != NULL) {
1299 			if (getArraySize() != variable.getArraySize()) return false;
1300 			for (i = _pArray->items.begin(); i != _pArray->items.end(); i++) {
1301 				for (j = variable._pArray->items.begin(); j != variable._pArray->items.end(); ++j) {
1302 					if (strcmp((*i)->_tcName, (*j)->_tcName) == 0) {
1303 						if (!(*i)->equal(*(*j))) return false;
1304 						break;
1305 					}
1306 				}
1307 				if (j == variable._pArray->items.end()) return false;
1308 			}
1309 		}
1310 		return true;
1311 	}
1312 
copyAll(const DtaScriptVariable & variable,bool bMerge)1313 	void DtaScriptVariable::copyAll(const DtaScriptVariable& variable, bool bMerge) {
1314 		if (!bMerge) clearContent();
1315 		const char* tcValue = variable.getValue();
1316 		if ((tcValue != NULL) && (*tcValue != '\0')) setValue(tcValue);
1317 		DtaScriptVariableList* pVariableAttributes = variable._pAttributes;
1318 		while (pVariableAttributes != NULL) {
1319 			const char* tcName = pVariableAttributes->getNode()->_tcName;
1320 			DtaScriptVariable* pVariable = NULL;
1321 			DtaScriptVariableList* pAttributes = _pAttributes;
1322 			DtaScriptVariableList* pLastAttribute = NULL;
1323 			while (pAttributes != NULL) {
1324 				if (strcmp(pAttributes->getNode()->_tcName, tcName) == 0) {
1325 					pVariable = pAttributes->getNode();
1326 					break;
1327 				}
1328 				if (pAttributes->getNext() == NULL) pLastAttribute = pAttributes;
1329 				pAttributes = pAttributes->getNext();
1330 			}
1331 			if (pVariable == NULL) {
1332 				pVariable = new DtaScriptVariable(this, tcName);
1333 				if (pLastAttribute == NULL) _pAttributes = new DtaScriptVariableList(pVariable);
1334 				else pLastAttribute->pushBack(pVariable);
1335 				if (_pListeners != NULL) _pListeners->onAddAttribute(pVariable);
1336 			}
1337 			if (pVariableAttributes->getNode()->_eValueNode == REFERENCE_VALUE_NODE) {
1338 				pVariable->_eValueNode = REFERENCE_VALUE_NODE;
1339 				pVariable->_value.var = pVariableAttributes->getNode()->_value.var;
1340 				pVariable->_value.var->addReferencedBy(pVariable);
1341 			} else if (pVariableAttributes->getNode()->_eValueNode == INDEX_VALUE_NODE) {
1342 				pVariable->_eValueNode = REFERENCE_VALUE_NODE;
1343 				pVariable->_value.var = (*pVariableAttributes->getNode()->_value.ind.var)->item();
1344 				pVariable->_value.var->addReferencedBy(pVariable);
1345 			} else {
1346 				pVariable->copyAll(*(pVariableAttributes->getNode()), bMerge);
1347 			}
1348 			pVariableAttributes = pVariableAttributes->getNext();
1349 		}
1350 		NodeArrayType* pANT = variable._pArray;
1351 		if ((pANT != NULL) && !pANT->items.empty()) {
1352 			if (_pArray == NULL) {
1353 				_pArray = new NodeArrayType;
1354 				_pArray->cache = new std::map<std::string, DtaScriptVariable*>();
1355 			} else if (_pArray->cache == NULL) {
1356 				_pArray->cache = new std::map<std::string, DtaScriptVariable*>();
1357 				for (std::list<DtaScriptVariable*>::const_iterator i = _pArray->items.begin(); i != _pArray->items.end(); i++) (*_pArray->cache)[(*i)->_tcName] = (*i);
1358 			}
1359 			for (std::list<DtaScriptVariable*>::const_iterator i = pANT->items.begin(); i != pANT->items.end(); i++) {
1360 				const char* tcName = (*i)->_tcName;
1361 				std::map<std::string, DtaScriptVariable*>::const_iterator cursor = _pArray->cache->find(tcName);
1362 				DtaScriptVariable* pVariable = NULL;
1363 				if (cursor != _pArray->cache->end()) {
1364 					pVariable = cursor->second;
1365 				} else {
1366 					pVariable = new DtaScriptVariable(this, tcName);
1367 					_pArray->items.push_back(pVariable);
1368 					(*_pArray->cache)[tcName] = pVariable;
1369 				}
1370 				if ((*i)->_eValueNode == REFERENCE_VALUE_NODE) {
1371 					pVariable->_eValueNode = REFERENCE_VALUE_NODE;
1372 					pVariable->_value.var = (*i)->_value.var;
1373 					pVariable->_value.var->addReferencedBy(pVariable);
1374 				} else if ((*i)->_eValueNode == INDEX_VALUE_NODE) {
1375 					pVariable->_eValueNode = REFERENCE_VALUE_NODE;
1376 					pVariable->_value.var = (*(*i)->_value.ind.var)->item();
1377 					pVariable->_value.var->addReferencedBy(pVariable);
1378 				} else {
1379 					pVariable->copyAll(*(*i), bMerge);
1380 				}
1381 			}
1382 		}
1383 	}
1384 
pushItem(const std::string & sValue)1385 	DtaScriptVariable* DtaScriptVariable::pushItem(const std::string& sValue) {
1386 		char tcNumber[32];
1387 		if (_pArray == NULL) _pArray = new NodeArrayType;
1388 		sprintf(tcNumber, "%d", _pArray->items.size());
1389 		std::string sNumber = tcNumber;
1390 		DtaScriptVariable* pVariable = new DtaScriptVariable(this, sNumber);
1391 		_pArray->items.push_back(pVariable);
1392 		if (_pArray->cache != NULL) {
1393 			(*_pArray->cache)[sNumber] = pVariable;
1394 		}
1395 		if (!sValue.empty()) pVariable->setValue(sValue.c_str());
1396 		if (_pListeners != NULL) _pListeners->onArrayHasChanged();
1397 		return pVariable;
1398 	}
1399 
slideNodeContent(DtaScriptVariable & visibility,const ExprScriptVariable & varExpr)1400 	void DtaScriptVariable::slideNodeContent(DtaScriptVariable& visibility, const ExprScriptVariable& varExpr) {
1401 		DtaScriptVariable* pTemporary = new DtaScriptVariable;
1402 		pTemporary->copyAll(*this);
1403 		clearContent();
1404 		DtaScriptVariable* pDestVariable = getNonRecursiveVariable(visibility, varExpr);
1405 		DtaScriptVariable* pParent = pDestVariable->getParent();
1406 		DtaScriptVariableList* pParentAttributes = pParent->_pAttributes;
1407 		while (pParentAttributes != NULL) {
1408 			if (pParentAttributes->getNode() == pDestVariable) {
1409 				pParentAttributes->setNode(pTemporary);
1410 				free((char*) pTemporary->_tcName);
1411 #ifdef WIN32
1412 				pTemporary->_tcName = ::_strdup(pDestVariable->_tcName);
1413 #else
1414 				pTemporary->_tcName = ::strdup(pDestVariable->_tcName);
1415 #endif
1416 				pTemporary->_pParent = pParent;
1417 				break;
1418 			}
1419 			pParentAttributes = pParentAttributes->getNext();
1420 		}
1421 		if (pParentAttributes == NULL) {
1422 			NodeArrayType* pANT = pParent->_pArray;
1423 			if (pANT != NULL) {
1424 				std::list<DtaScriptVariable*>::iterator i;
1425 				for (i = pANT->items.begin(); i != pANT->items.end(); i++) {
1426 					if ((*i) == pDestVariable) {
1427 						(*i) = pTemporary;
1428 						free((char*) pTemporary->_tcName);
1429 #ifdef WIN32
1430 						pTemporary->_tcName = ::_strdup(pDestVariable->_tcName);
1431 #else
1432 						pTemporary->_tcName = ::strdup(pDestVariable->_tcName);
1433 #endif
1434 						pTemporary->_pParent = pParent;
1435 						break;
1436 					}
1437 				}
1438 				if (i == pANT->items.end()) {
1439 					delete pTemporary;
1440 					throw UtlException("internal error: unable to slide a node content because destination node isn't attached to its parent properly");
1441 				}
1442 			} else {
1443 				delete pTemporary;
1444 				throw UtlException("internal error: unable to slide a node content because destination node isn't attached to its parent properly");
1445 			}
1446 		}
1447 		delete pDestVariable;
1448 	}
1449 
traceValue(int iDepth,const std::string & sIndent,const std::string & sPrefix)1450 	bool DtaScriptVariable::traceValue(int iDepth, const std::string& sIndent, const std::string& sPrefix) {
1451 		if (_eValueNode == STRING_VALUE_NODE) {
1452 			if (_value.str.length != 0) CGRuntime::traceLine(sPrefix + "\"" + std::string(_value.str.text) + "\"");
1453 			else return false;
1454 		} else if ((_eValueNode & 0x0FF) == INDEX_VALUE_NODE) {
1455 			DtaScriptVariable* pNode = (*_value.ind.var)->item();
1456 			const char* tcValue = pNode->getValue();
1457 			if (tcValue != NULL) {
1458 				CGRuntime::traceLine(sPrefix + "<index> '" + pNode->getCompleteName() + "' = \"" + std::string(tcValue) + "\"");
1459 			} else {
1460 				CGRuntime::traceLine(sPrefix + "<index> '" + pNode->getCompleteName() + "'");
1461 			}
1462 			pNode->traceObject(iDepth, sIndent);
1463 		} else if ((_eValueNode & 0x0FF) == REFERENCE_VALUE_NODE) {
1464 			const char* tcValue = _value.var->getValue();
1465 			if (tcValue != NULL) {
1466 				CGRuntime::traceLine(sPrefix + "-> '" + _value.var->getCompleteName() + "' = \"" + std::string(tcValue) + "\"");
1467 			} else {
1468 				CGRuntime::traceLine(sPrefix + "-> '" + _value.var->getCompleteName() + "'");
1469 			}
1470 			_value.var->traceObject(iDepth, sIndent);
1471 		} else if (_eValueNode == EXTERNAL_VALUE_NODE) {
1472 			const char* tcValue = _value.ext->getValue();
1473 			if (tcValue != NULL) {
1474 				CGRuntime::traceLine(sPrefix + ">> external value node = \"" + std::string(tcValue) + "\"");
1475 			} else {
1476 				CGRuntime::traceLine(sPrefix + ">> external value node");
1477 			}
1478 		} else {
1479 			return false;
1480 		}
1481 		return true;
1482 	}
1483 
traceObject(int iDepth,const std::string & sIndent)1484 	void DtaScriptVariable::traceObject(int iDepth, const std::string& sIndent) {
1485 		if (iDepth < 0) return;
1486 		std::string sCurrentIndent = sIndent + "    ";
1487 		std::string sNextIndent = sCurrentIndent;
1488 		if (sIndent.empty()) {
1489 			char tcMessage[64];
1490 			if (iDepth > 0) sprintf(tcMessage, "' to depth %d:", iDepth);
1491 			else strcpy(tcMessage, "':");
1492 			CGRuntime::traceLine("Tracing variable '" + getCompleteName() + tcMessage);
1493 			if (_eValueNode == INDEX_VALUE_NODE) traceValue(iDepth, sNextIndent, "\t");
1494 			else traceValue(iDepth - 1, sNextIndent, "\t");
1495 		} else if (_pAttributes != NULL) {
1496 			CGRuntime::traceLine(sNextIndent + "|--+");
1497 			sNextIndent += "    ";
1498 		}
1499 		DtaScriptVariableList* pAttributes = _pAttributes;
1500 		while (pAttributes != NULL) {
1501 			DtaScriptVariable* pNode = pAttributes->getNode();
1502 			const char* tcValue = pNode->getValue();
1503 			std::string sAttribute = sNextIndent + pNode->_tcName;
1504 			if (!pNode->traceValue(iDepth - 1, sNextIndent, sAttribute + " = ")) {
1505 				CGRuntime::traceLine(sAttribute);
1506 			}
1507 			if (iDepth > 0) {
1508 				pNode->traceObject(iDepth - 1, sNextIndent);
1509 			} else {
1510 				NodeArrayType* pANT = pNode->_pArray;
1511 				if ((pANT != NULL) && !pANT->items.empty()) {
1512 					CGRuntime::traceText(sCurrentIndent + std::string(pNode->_tcName) + "[");
1513 					for (std::list<DtaScriptVariable*>::iterator j = pANT->items.begin(); j != pANT->items.end(); j++) {
1514 						if (j != pANT->items.begin()) CGRuntime::traceText(", ");
1515 						CGRuntime::traceText("\"" + std::string((*j)->_tcName) + "\"");
1516 					}
1517 					CGRuntime::traceLine("]");
1518 				}
1519 			}
1520 			pAttributes = pAttributes->getNext();
1521 		}
1522 		if ((_pArray != NULL) && !_pArray->items.empty()) {
1523 			if (iDepth <= 0) {
1524 				CGRuntime::traceText(sCurrentIndent + "[");
1525 				for (std::list<DtaScriptVariable*>::iterator k = _pArray->items.begin(); k != _pArray->items.end(); k++) {
1526 					if (k != _pArray->items.begin()) CGRuntime::traceText(", ");
1527 					CGRuntime::traceText("\"" + std::string((*k)->_tcName) + "\"");
1528 					const char* tcValue = (*k)->getValue();
1529 					if ((tcValue != NULL) && (*tcValue != '\0')) CGRuntime::traceText(" -> \"" + std::string(tcValue) + "\"");
1530 				}
1531 				CGRuntime::traceLine("]");
1532 			} else {
1533 				for (std::list<DtaScriptVariable*>::iterator k = _pArray->items.begin(); k != _pArray->items.end(); k++) {
1534 					CGRuntime::traceText(sCurrentIndent + "[\"" + std::string((*k)->_tcName) + "\"]");
1535 					if (!(*k)->traceValue(iDepth - 1, sCurrentIndent, " = ")) CGRuntime::traceLine("");
1536 					(*k)->traceObject(iDepth - 1, sCurrentIndent);
1537 				}
1538 			}
1539 		}
1540 		if (sIndent.empty()) {
1541 			CGRuntime::traceLine("End of variable's trace '" + getCompleteName() + "'.");
1542 		}
1543 	}
1544 
traceStack()1545 	void DtaScriptVariable::traceStack() {
1546 		if (strcmp(_tcName, "project") == 0) return;
1547 		if (_pParent != 0) _pParent->traceStack();
1548 		CGRuntime::traceLine(std::string(_tcName) + ":");
1549 		DtaScriptVariableList* pAttributes = _pAttributes;
1550 		while (pAttributes != NULL) {
1551 			DtaScriptVariable* pNode = pAttributes->getNode();
1552 			if (pNode->getReferencedVariable() != NULL) {
1553 				std::string sReference = pNode->getReferencedVariable()->getCompleteName();
1554 				CGRuntime::traceLine(std::string(pNode->_tcName) + " = " + sReference);
1555 			} else {
1556 				const char* tcValue = pNode->getValue();
1557 				if (tcValue != NULL) {
1558 					CGRuntime::traceLine(std::string(pNode->_tcName) + " = \"" + std::string(tcValue) + "\"");
1559 				} else {
1560 					CGRuntime::traceLine(pNode->_tcName);
1561 				}
1562 			}
1563 			NodeArrayType* pANT = pNode->_pArray;
1564 			if ((pANT != NULL) && !pANT->items.empty()) {
1565 				CGRuntime::traceText("\t" + std::string(pNode->_tcName) + "[");
1566 				for (std::list<DtaScriptVariable*>::iterator j = pANT->items.begin(); j != pANT->items.end(); j++) {
1567 					if (j != pANT->items.begin()) CGRuntime::traceText(", ");
1568 					CGRuntime::traceText("\"" + std::string((*j)->_tcName) + "\"");
1569 				}
1570 				CGRuntime::traceLine("]");
1571 			}
1572 			pAttributes = pAttributes->getNext();
1573 		}
1574 		if ((_pArray != NULL) && !_pArray->items.empty()) {
1575 			CGRuntime::traceText("\t" + std::string(_tcName) + "[");
1576 			for (std::list<DtaScriptVariable*>::iterator k = _pArray->items.begin(); k != _pArray->items.end(); k++) {
1577 				if (k != _pArray->items.begin()) CGRuntime::traceText(", ");
1578 				CGRuntime::traceText("\"" + std::string((*k)->_tcName) + "\"");
1579 			}
1580 			CGRuntime::traceLine("]");
1581 		}
1582 	}
1583 }
1584