change log updated
[public/netxms.git] / include / nxsl_classes.h
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2014 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published by
7 ** the Free Software Foundation; either version 3 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program 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
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: nxsl_classes.h
20 **
21 **/
22
23 #ifndef _nxsl_classes_h_
24 #define _nxsl_classes_h_
25
26 #include <nms_threads.h>
27 #include <nms_util.h>
28 #include <nxcpapi.h>
29 #include <geolocation.h>
30
31 //
32 // Constants
33 //
34
35 #define MAX_CLASS_NAME 64
36 #define INVALID_ADDRESS ((UINT32)0xFFFFFFFF)
37
38 /**
39 * NXSL data types
40 */
41 enum NXSL_DataTypes
42 {
43 NXSL_DT_NULL = 0,
44 NXSL_DT_OBJECT = 1,
45 NXSL_DT_ARRAY = 2,
46 NXSL_DT_ITERATOR = 3,
47 NXSL_DT_HASHMAP = 4,
48 NXSL_DT_STRING = 5,
49 NXSL_DT_REAL = 6,
50 NXSL_DT_INT32 = 7,
51 NXSL_DT_INT64 = 8,
52 NXSL_DT_UINT32 = 9,
53 NXSL_DT_UINT64 = 10
54 };
55
56 /**
57 * NXSL stack class
58 */
59 class LIBNXSL_EXPORTABLE NXSL_Stack
60 {
61 private:
62 int m_nStackSize;
63 int m_nStackPos;
64 void **m_ppData;
65
66 public:
67 NXSL_Stack();
68 ~NXSL_Stack();
69
70 void push(void *pData);
71 void *pop();
72 void *peek();
73 void *peekAt(int offset);
74 void **peekList(int nLevel) { return &m_ppData[m_nStackPos - nLevel]; }
75
76 int getSize() { return m_nStackPos; }
77 };
78
79 class NXSL_Value;
80 class NXSL_Object;
81 class NXSL_VM;
82
83 /**
84 * External method structure
85 */
86 struct NXSL_ExtMethod
87 {
88 int (* handler)(NXSL_Object *object, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
89 int numArgs; // Number of arguments or -1 for variable number
90 };
91
92 #define NXSL_METHOD_DEFINITION(clazz, name) \
93 static int M_##clazz##_##name (NXSL_Object *object, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm)
94
95 #define NXSL_REGISTER_METHOD(clazz, name, argc) { \
96 NXSL_ExtMethod *m = new NXSL_ExtMethod; \
97 m->handler = M_##clazz##_##name; \
98 m->numArgs = argc; \
99 m_methods->set(_T(#name), m); \
100 }
101
102 /**
103 * Class representing NXSL class
104 */
105 class LIBNXSL_EXPORTABLE NXSL_Class
106 {
107 private:
108 TCHAR m_name[MAX_CLASS_NAME];
109 StringList m_classHierarchy;
110
111 protected:
112 StringObjectMap<NXSL_ExtMethod> *m_methods;
113
114 void setName(const TCHAR *name);
115
116 public:
117 NXSL_Class();
118 virtual ~NXSL_Class();
119
120 virtual NXSL_Value *getAttr(NXSL_Object *object, const TCHAR *attr);
121 virtual bool setAttr(NXSL_Object *object, const TCHAR *attr, NXSL_Value *value);
122
123 virtual int callMethod(const TCHAR *name, NXSL_Object *object, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
124
125 virtual void onObjectCreate(NXSL_Object *object);
126 virtual void onObjectDelete(NXSL_Object *object);
127
128 const TCHAR *getName() const { return m_name; }
129 bool instanceOf(const TCHAR *name) const { return !_tcscmp(name, m_name) || m_classHierarchy.contains(name); }
130 };
131
132 /**
133 * Class data - object and reference count
134 */
135 struct __nxsl_class_data
136 {
137 void *data;
138 int refCount;
139 };
140
141 /**
142 * Object instance
143 */
144 class LIBNXSL_EXPORTABLE NXSL_Object
145 {
146 private:
147 NXSL_Class *m_class;
148 __nxsl_class_data *m_data;
149
150 public:
151 NXSL_Object(NXSL_Object *object);
152 NXSL_Object(NXSL_Class *nxslClass, void *data);
153 ~NXSL_Object();
154
155 NXSL_Class *getClass() { return m_class; }
156 void *getData() { return m_data->data; }
157 };
158
159 /**
160 * Reference counting object
161 */
162 class LIBNXSL_EXPORTABLE NXSL_HandleCountObject
163 {
164 protected:
165 int m_handleCount;
166
167 public:
168 NXSL_HandleCountObject()
169 {
170 m_handleCount = 0;
171 }
172
173 void incHandleCount() { m_handleCount++; }
174 void decHandleCount() { m_handleCount--; }
175 bool isUnused() { return m_handleCount < 1; }
176 bool isShared() { return m_handleCount > 1; }
177 };
178
179 /**
180 * Array element
181 */
182 struct NXSL_ArrayElement
183 {
184 int index;
185 NXSL_Value *value;
186 };
187
188 /**
189 * NXSL array
190 */
191 class LIBNXSL_EXPORTABLE NXSL_Array : public NXSL_HandleCountObject
192 {
193 private:
194 int m_size;
195 int m_allocated;
196 NXSL_ArrayElement *m_data;
197
198 public:
199 NXSL_Array();
200 NXSL_Array(const NXSL_Array *src);
201 NXSL_Array(const StringList *values);
202 ~NXSL_Array();
203
204 int size() const { return m_size; }
205 int getMinIndex() const { return (m_size > 0) ? m_data[0].index : 0; }
206 int getMaxIndex() const { return (m_size > 0) ? m_data[m_size - 1].index : 0; }
207
208 StringList *toStringList() const;
209
210 NXSL_Value *get(int index) const;
211 NXSL_Value *getByPosition(int position) const;
212
213 void set(int index, NXSL_Value *value);
214 void append(NXSL_Value *value) { if (m_size == 0) { set(0, value); } else { set(getMaxIndex() + 1, value); } }
215 void insert(int index, NXSL_Value *value);
216 void remove(int index);
217
218 int callMethod(const TCHAR *name, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
219 };
220
221 /**
222 * NXSL hash map
223 */
224 class LIBNXSL_EXPORTABLE NXSL_HashMap : public NXSL_HandleCountObject
225 {
226 private:
227 StringObjectMap<NXSL_Value> *m_values;
228
229 public:
230 NXSL_HashMap();
231 NXSL_HashMap(const NXSL_HashMap *src);
232 ~NXSL_HashMap();
233
234 void set(const TCHAR *key, NXSL_Value *value) { m_values->set(key, value); }
235 NXSL_Value *get(const TCHAR *key) const { return m_values->get(key); }
236 NXSL_Value *getKeys() const;
237 NXSL_Value *getValues() const;
238
239 StringMap *toStringMap() const;
240
241 int size() const { return m_values->size(); }
242 };
243
244 /**
245 * Iterator for arrays
246 */
247 class LIBNXSL_EXPORTABLE NXSL_Iterator
248 {
249 private:
250 int m_refCount;
251 TCHAR *m_variable;
252 NXSL_Array *m_array;
253 int m_position;
254
255 public:
256 NXSL_Iterator(const TCHAR *variable, NXSL_Array *array);
257 ~NXSL_Iterator();
258
259 const TCHAR *getVariableName() { return m_variable; }
260
261 void incRefCount() { m_refCount++; }
262 void decRefCount() { m_refCount--; }
263 bool isUnused() { return m_refCount < 1; }
264
265 NXSL_Value *next();
266
267 static int createIterator(NXSL_Stack *stack);
268 };
269
270 /**
271 * Object handle
272 */
273 template <class T> class NXSL_Handle
274 {
275 private:
276 T *m_object;
277 int m_refCount;
278
279 public:
280 NXSL_Handle(T *o)
281 {
282 m_object = o;
283 o->incHandleCount();
284 m_refCount = 0;
285 }
286 NXSL_Handle(NXSL_Handle<T> *h)
287 {
288 m_object = h->m_object;
289 m_object->incHandleCount();
290 m_refCount = 0;
291 }
292 ~NXSL_Handle()
293 {
294 m_object->decHandleCount();
295 if (m_object->isUnused())
296 delete m_object;
297 }
298
299 void incRefCount() { m_refCount++; }
300 void decRefCount() { m_refCount--; }
301 bool isUnused() { return m_refCount < 1; }
302 bool isShared() { return m_refCount > 1; }
303
304 T *getObject() { return m_object; }
305 bool isSharedObject() { return m_object->isShared(); }
306
307 void cloneObject()
308 {
309 m_object->decHandleCount();
310 m_object = new T(m_object);
311 m_object->incHandleCount();
312 }
313 };
314
315 /**
316 * Variable or constant value
317 */
318 class LIBNXSL_EXPORTABLE NXSL_Value
319 {
320 protected:
321 UINT32 m_dwStrLen;
322 TCHAR *m_pszValStr;
323 #ifdef UNICODE
324 char *m_valueMBStr; // value as MB string; NULL until first request
325 #endif
326 TCHAR *m_name;
327 BYTE m_nDataType;
328 BYTE m_bStringIsValid;
329 union
330 {
331 INT32 nInt32;
332 UINT32 uInt32;
333 INT64 nInt64;
334 UINT64 uInt64;
335 double dReal;
336 NXSL_Object *object;
337 NXSL_Iterator *iterator;
338 NXSL_Handle<NXSL_Array> *arrayHandle;
339 NXSL_Handle<NXSL_HashMap> *hashMapHandle;
340 } m_value;
341
342 void updateNumber();
343 void updateString();
344
345 void invalidateString()
346 {
347 safe_free_and_null(m_pszValStr);
348 #ifdef UNICODE
349 safe_free_and_null(m_valueMBStr);
350 #endif
351 m_bStringIsValid = FALSE;
352 }
353
354 public:
355 NXSL_Value();
356 NXSL_Value(const NXSL_Value *src);
357 NXSL_Value(NXSL_Object *object);
358 NXSL_Value(NXSL_Array *array);
359 NXSL_Value(NXSL_Iterator *iterator);
360 NXSL_Value(NXSL_HashMap *hashMap);
361 NXSL_Value(INT32 nValue);
362 NXSL_Value(INT64 nValue);
363 NXSL_Value(UINT32 uValue);
364 NXSL_Value(UINT64 uValue);
365 NXSL_Value(double dValue);
366 NXSL_Value(const TCHAR *value);
367 NXSL_Value(const TCHAR *value, UINT32 len);
368 #ifdef UNICODE
369 NXSL_Value(const char *value);
370 #endif
371 ~NXSL_Value();
372
373 void set(INT32 value);
374
375 void setName(const TCHAR *name) { safe_free(m_name); m_name = _tcsdup_ex(name); }
376 const TCHAR *getName() const { return m_name; }
377
378 bool convert(int nDataType);
379 int getDataType() const { return m_nDataType; }
380
381 bool isNull() const { return (m_nDataType == NXSL_DT_NULL); }
382 bool isObject() const { return (m_nDataType == NXSL_DT_OBJECT); }
383 bool isObject(const TCHAR *className) const;
384 bool isArray() const { return (m_nDataType == NXSL_DT_ARRAY); }
385 bool isHashMap() const { return (m_nDataType == NXSL_DT_HASHMAP); }
386 bool isIterator() const { return (m_nDataType == NXSL_DT_ITERATOR); }
387 bool isString() const { return (m_nDataType >= NXSL_DT_STRING); }
388 bool isNumeric() const { return (m_nDataType > NXSL_DT_STRING); }
389 bool isReal() const { return (m_nDataType == NXSL_DT_REAL); }
390 bool isInteger() const { return (m_nDataType > NXSL_DT_REAL); }
391 bool isUnsigned() const { return (m_nDataType >= NXSL_DT_UINT32); }
392 bool isZero() const;
393 bool isNonZero() const;
394
395 const TCHAR *getValueAsString(UINT32 *len);
396 const TCHAR *getValueAsCString();
397 #ifdef UNICODE
398 const char *getValueAsMBString();
399 #else
400 const char *getValueAsMBString() { return getValueAsCString(); }
401 #endif
402 INT32 getValueAsInt32();
403 UINT32 getValueAsUInt32();
404 INT64 getValueAsInt64();
405 UINT64 getValueAsUInt64();
406 double getValueAsReal();
407 bool getValueAsBoolean() { return getValueAsInt32() != 0; }
408 NXSL_Object *getValueAsObject() { return (m_nDataType == NXSL_DT_OBJECT) ? m_value.object : NULL; }
409 NXSL_Array *getValueAsArray() { return (m_nDataType == NXSL_DT_ARRAY) ? m_value.arrayHandle->getObject() : NULL; }
410 NXSL_HashMap *getValueAsHashMap() { return (m_nDataType == NXSL_DT_HASHMAP) ? m_value.hashMapHandle->getObject() : NULL; }
411 NXSL_Iterator *getValueAsIterator() { return (m_nDataType == NXSL_DT_ITERATOR) ? m_value.iterator : NULL; }
412
413 void concatenate(const TCHAR *string, UINT32 len);
414
415 void increment();
416 void decrement();
417 void negate();
418 void bitNot();
419
420 void add(NXSL_Value *pVal);
421 void sub(NXSL_Value *pVal);
422 void mul(NXSL_Value *pVal);
423 void div(NXSL_Value *pVal);
424 void rem(NXSL_Value *pVal);
425 void bitAnd(NXSL_Value *pVal);
426 void bitOr(NXSL_Value *pVal);
427 void bitXor(NXSL_Value *pVal);
428 void lshift(int nBits);
429 void rshift(int nBits);
430
431 BOOL EQ(NXSL_Value *pVal);
432 BOOL LT(NXSL_Value *pVal);
433 BOOL LE(NXSL_Value *pVal);
434 BOOL GT(NXSL_Value *pVal);
435 BOOL GE(NXSL_Value *pVal);
436
437 void copyOnWrite();
438 void onVariableSet();
439
440 bool equals(const NXSL_Value *v) const;
441 void serialize(ByteStream& s) const;
442
443 static NXSL_Value *load(ByteStream& s);
444 };
445
446 /**
447 * NXSL function definition structure
448 */
449 class NXSL_Function
450 {
451 public:
452 TCHAR m_name[MAX_FUNCTION_NAME];
453 UINT32 m_dwAddr;
454
455 NXSL_Function() { m_name[0] = 0; m_dwAddr = INVALID_ADDRESS; }
456 NXSL_Function(NXSL_Function *src) { nx_strncpy(m_name, src->m_name, MAX_FUNCTION_NAME); m_dwAddr = src->m_dwAddr; }
457 NXSL_Function(const TCHAR *name, UINT32 addr) { nx_strncpy(m_name, name, MAX_FUNCTION_NAME); m_dwAddr = addr; }
458 };
459
460 /**
461 * External function structure
462 */
463 struct NXSL_ExtFunction
464 {
465 TCHAR m_name[MAX_FUNCTION_NAME];
466 int (* m_pfHandler)(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm);
467 int m_iNumArgs; // Number of arguments or -1 for variable number
468 };
469
470 /**
471 * External selector structure
472 */
473 struct NXSL_ExtSelector
474 {
475 TCHAR m_name[MAX_FUNCTION_NAME];
476 int (* m_handler)(const TCHAR *name, NXSL_Value *options, int argc, NXSL_Value **argv, int *selection, NXSL_VM *vm);
477 };
478
479 /**
480 * NXSL module import information
481 */
482 struct NXSL_ModuleImport
483 {
484 TCHAR name[MAX_PATH];
485 int lineNumber; // line number in source code where module was referenced
486 };
487
488 class NXSL_Library;
489
490 /**
491 * Environment for NXSL program
492 */
493 class LIBNXSL_EXPORTABLE NXSL_Environment
494 {
495 private:
496 int m_numFunctions;
497 NXSL_ExtFunction *m_functions;
498
499 int m_numSelectors;
500 NXSL_ExtSelector *m_selectors;
501
502 NXSL_Library *m_library;
503
504 public:
505 NXSL_Environment();
506 virtual ~NXSL_Environment();
507
508 virtual void print(NXSL_Value *value);
509 virtual void trace(int level, const TCHAR *text);
510
511 virtual void configureVM(NXSL_VM *vm);
512
513 void setLibrary(NXSL_Library *lib) { m_library = lib; }
514
515 NXSL_ExtFunction *findFunction(const TCHAR *name);
516 void registerFunctionSet(int count, NXSL_ExtFunction *list);
517
518 NXSL_ExtSelector *findSelector(const TCHAR *name);
519 void registerSelectorSet(int count, NXSL_ExtSelector *list);
520
521 bool loadModule(NXSL_VM *vm, const NXSL_ModuleImport *importInfo);
522 };
523
524 /**
525 * Runtime variable information
526 */
527 class LIBNXSL_EXPORTABLE NXSL_Variable
528 {
529 protected:
530 TCHAR *m_pszName;
531 NXSL_Value *m_pValue;
532 bool m_isConstant;
533
534 public:
535 NXSL_Variable(const TCHAR *pszName);
536 NXSL_Variable(const TCHAR *pszName, NXSL_Value *pValue, bool constant = false);
537 NXSL_Variable(NXSL_Variable *pSrc);
538 ~NXSL_Variable();
539
540 const TCHAR *getName() { return m_pszName; }
541 NXSL_Value *getValue() { return m_pValue; }
542 void setValue(NXSL_Value *pValue);
543 bool isConstant() { return m_isConstant; }
544 };
545
546 /**
547 * Varable system
548 */
549 class LIBNXSL_EXPORTABLE NXSL_VariableSystem
550 {
551 protected:
552 ObjectArray<NXSL_Variable> *m_variables;
553 bool m_isConstant;
554
555 public:
556 NXSL_VariableSystem(bool constant = false);
557 NXSL_VariableSystem(NXSL_VariableSystem *src);
558 ~NXSL_VariableSystem();
559
560 NXSL_Variable *find(const TCHAR *pszName);
561 NXSL_Variable *create(const TCHAR *pszName, NXSL_Value *pValue = NULL);
562 void merge(NXSL_VariableSystem *src);
563 void addAll(StringObjectMap<NXSL_Value> *src);
564 void clear() { m_variables->clear(); }
565 bool isConstant() { return m_isConstant; }
566 };
567
568 /**
569 * Instruction's operand type
570 */
571 enum OperandType
572 {
573 OP_TYPE_NONE = 0,
574 OP_TYPE_ADDR = 1,
575 OP_TYPE_STRING = 2,
576 OP_TYPE_CONST = 3
577 };
578
579 /**
580 * Single execution instruction
581 */
582 class LIBNXSL_EXPORTABLE NXSL_Instruction
583 {
584 friend class NXSL_Program;
585 friend class NXSL_VM;
586
587 protected:
588 INT16 m_nOpCode;
589 INT16 m_nStackItems;
590 union
591 {
592 NXSL_Value *m_pConstant;
593 TCHAR *m_pszString;
594 UINT32 m_dwAddr;
595 } m_operand;
596 INT32 m_nSourceLine;
597
598 public:
599 NXSL_Instruction(int nLine, short nOpCode);
600 NXSL_Instruction(int nLine, short nOpCode, NXSL_Value *pValue);
601 NXSL_Instruction(int nLine, short nOpCode, char *pszString);
602 NXSL_Instruction(int nLine, short nOpCode, char *pszString, short nStackItems);
603 NXSL_Instruction(int nLine, short nOpCode, UINT32 dwAddr);
604 NXSL_Instruction(int nLine, short nOpCode, short nStackItems);
605 NXSL_Instruction(NXSL_Instruction *pSrc);
606 ~NXSL_Instruction();
607
608 OperandType getOperandType();
609 };
610
611 /**
612 * NXSL module information
613 */
614 struct NXSL_Module
615 {
616 TCHAR m_name[MAX_PATH];
617 UINT32 m_codeStart;
618 int m_codeSize;
619 int m_functionStart;
620 int m_numFunctions;
621 };
622
623 /**
624 * Compiled NXSL program
625 */
626 class LIBNXSL_EXPORTABLE NXSL_Program
627 {
628 friend class NXSL_VM;
629
630 protected:
631 ObjectArray<NXSL_Instruction> *m_instructionSet;
632 ObjectArray<NXSL_ModuleImport> *m_requiredModules;
633 StringObjectMap<NXSL_Value> *m_constants;
634 ObjectArray<NXSL_Function> *m_functions;
635
636 UINT32 getFinalJumpDestination(UINT32 dwAddr, int srcJump);
637
638 public:
639 NXSL_Program();
640 ~NXSL_Program();
641
642 bool addFunction(const char *pszName, UINT32 dwAddr, char *pszError);
643 void resolveFunctions();
644 void addInstruction(NXSL_Instruction *pInstruction) { m_instructionSet->add(pInstruction); }
645 void resolveLastJump(int opcode, int offset = 0);
646 void createJumpAt(UINT32 dwOpAddr, UINT32 dwJumpAddr);
647 void addRequiredModule(const char *name, int lineNumber);
648 void optimize();
649 void removeInstructions(UINT32 start, int count);
650 bool addConstant(const char *name, NXSL_Value *value);
651
652 UINT32 getCodeSize() { return m_instructionSet->size(); }
653
654 void dump(FILE *pFile);
655 void serialize(ByteStream& s);
656
657 static NXSL_Program *load(ByteStream& s, TCHAR *errMsg, size_t errMsgSize);
658 };
659
660 /**
661 * NXSL Script
662 */
663 class LIBNXSL_EXPORTABLE NXSL_LibraryScript
664 {
665 protected:
666 UINT32 m_id;
667 uuid m_guid;
668 TCHAR m_name[1024];
669 TCHAR *m_source;
670 NXSL_Program *m_program;
671 TCHAR m_error[1024];
672
673 public:
674 NXSL_LibraryScript();
675 NXSL_LibraryScript(UINT32 id, uuid guid, const TCHAR *name, TCHAR *source);
676 ~NXSL_LibraryScript();
677
678 bool isValid() const { return m_program != NULL; }
679
680 const uuid& getGuid() { return m_guid; }
681 UINT32 getId() { return m_id; }
682
683 const TCHAR *getName() { return m_name; }
684 const TCHAR *getCode() { return m_source; }
685 const TCHAR *getError() { return m_error; }
686
687 NXSL_Program *getProgram() { return m_program; }
688
689 void fillMessage(NXCPMessage *msg, UINT32 base);
690 void fillMessage(NXCPMessage *msg);
691 };
692
693 /**
694 * Script library
695 */
696 class LIBNXSL_EXPORTABLE NXSL_Library
697 {
698 private:
699 ObjectArray<NXSL_LibraryScript> *m_scriptList;
700 MUTEX m_mutex;
701
702 void deleteInternal(int nIndex);
703
704 public:
705 NXSL_Library();
706 ~NXSL_Library();
707
708 void lock() { MutexLock(m_mutex); }
709 void unlock() { MutexUnlock(m_mutex); }
710
711 BOOL addScript(NXSL_LibraryScript *script);
712 void deleteScript(const TCHAR *name);
713 void deleteScript(UINT32 id);
714 NXSL_Program *findNxslProgram(const TCHAR *name);
715 NXSL_LibraryScript *findScript(UINT32 id);
716 NXSL_VM *createVM(const TCHAR *name, NXSL_Environment *env);
717
718 void fillMessage(NXCPMessage *msg);
719 };
720
721 /**
722 * Catch point information
723 */
724 struct NXSL_CatchPoint
725 {
726 UINT32 addr;
727 UINT32 subLevel;
728 int dataStackSize;
729 };
730
731 /**
732 * NXSL storage class - base class for actual persistent storage
733 */
734 class LIBNXSL_EXPORTABLE NXSL_Storage
735 {
736 public:
737 NXSL_Storage();
738 virtual ~NXSL_Storage();
739
740 /**
741 * Write to storage. Storage becomes owner of provided value.
742 * Passing NULL value will effectively remove value from storage.
743 */
744 virtual void write(const TCHAR *name, NXSL_Value *value) = 0;
745
746 /**
747 * Read from storage. Returns new value owned by caller. Returns NXSL NULL if there are no value with given name.
748 */
749 virtual NXSL_Value *read(const TCHAR *name) = 0;
750 };
751
752 /**
753 * NXSL storage local implementation
754 */
755 class LIBNXSL_EXPORTABLE NXSL_LocalStorage : public NXSL_Storage
756 {
757 protected:
758 StringObjectMap<NXSL_Value> *m_values;
759
760 public:
761 NXSL_LocalStorage();
762 virtual ~NXSL_LocalStorage();
763
764 virtual void write(const TCHAR *name, NXSL_Value *value);
765 virtual NXSL_Value *read(const TCHAR *name);
766 };
767
768 /**
769 * NXSL virtual machine
770 */
771 class LIBNXSL_EXPORTABLE NXSL_VM
772 {
773 private:
774 static EnumerationCallbackResult createConstantsCallback(const TCHAR *key, const void *value, void *data);
775
776 protected:
777 NXSL_Environment *m_env;
778 void *m_userData;
779
780 ObjectArray<NXSL_Instruction> *m_instructionSet;
781 UINT32 m_cp;
782
783 UINT32 m_dwSubLevel;
784 NXSL_Stack *m_dataStack;
785 NXSL_Stack *m_codeStack;
786 NXSL_Stack *m_catchStack;
787 int m_nBindPos;
788
789 NXSL_VariableSystem *m_constants;
790 NXSL_VariableSystem *m_globals;
791 NXSL_VariableSystem *m_locals;
792
793 NXSL_Storage *m_storage;
794 NXSL_Storage *m_localStorage;
795
796 ObjectArray<NXSL_Function> *m_functions;
797 ObjectArray<NXSL_Module> *m_modules;
798
799 NXSL_Value *m_pRetValue;
800 int m_errorCode;
801 int m_errorLine;
802 TCHAR *m_errorText;
803
804 void execute();
805 bool unwind();
806 void callFunction(int nArgCount);
807 UINT32 callSelector(const TCHAR *name, int numElements);
808 void doUnaryOperation(int nOpCode);
809 void doBinaryOperation(int nOpCode);
810 void getOrUpdateArrayElement(int opcode, NXSL_Value *array, NXSL_Value *index);
811 bool setArrayElement(NXSL_Value *array, NXSL_Value *index, NXSL_Value *value);
812 void getArrayAttribute(NXSL_Array *a, const TCHAR *attribute, bool safe);
813 void getOrUpdateHashMapElement(int opcode, NXSL_Value *hashMap, NXSL_Value *key);
814 bool setHashMapElement(NXSL_Value *hashMap, NXSL_Value *key, NXSL_Value *value);
815 void getHashMapAttribute(NXSL_HashMap *m, const TCHAR *attribute, bool safe);
816 void error(int errorCode, int sourceLine = -1);
817 NXSL_Value *matchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp, BOOL bIgnoreCase);
818
819 NXSL_Variable *findVariable(const TCHAR *pszName);
820 NXSL_Variable *findOrCreateVariable(const TCHAR *pszName);
821 NXSL_Variable *createVariable(const TCHAR *pszName);
822
823 void relocateCode(UINT32 dwStartOffset, UINT32 dwLen, UINT32 dwShift);
824 UINT32 getFunctionAddress(const TCHAR *pszName);
825
826 public:
827 NXSL_VM(NXSL_Environment *env = NULL, NXSL_Storage *storage = NULL);
828 ~NXSL_VM();
829
830 void loadModule(NXSL_Program *module, const NXSL_ModuleImport *importInfo);
831
832 void setGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue);
833 NXSL_Variable *findGlobalVariable(const TCHAR *pszName) { return m_globals->find(pszName); }
834
835 bool addConstant(const TCHAR *name, NXSL_Value *value);
836
837 void setStorage(NXSL_Storage *storage);
838
839 void storageWrite(const TCHAR *name, NXSL_Value *value) { m_storage->write(name, value); }
840 void storageWrite(const TCHAR *name, const TCHAR *value) { m_storage->write(name, new NXSL_Value(value)); }
841 void storageWrite(const TCHAR *name, INT32 value) { m_storage->write(name, new NXSL_Value(value)); }
842 void storageWrite(const TCHAR *name, UINT32 value) { m_storage->write(name, new NXSL_Value(value)); }
843 void storageWrite(const TCHAR *name, INT64 value) { m_storage->write(name, new NXSL_Value(value)); }
844 void storageWrite(const TCHAR *name, UINT64 value) { m_storage->write(name, new NXSL_Value(value)); }
845 void storageWrite(const TCHAR *name, double value) { m_storage->write(name, new NXSL_Value(value)); }
846 NXSL_Value *storageRead(const TCHAR *name) { return m_storage->read(name); }
847
848 bool load(NXSL_Program *program);
849 bool run(ObjectArray<NXSL_Value> *args, NXSL_VariableSystem *pUserLocals = NULL,
850 NXSL_VariableSystem **ppGlobals = NULL, NXSL_VariableSystem *pConstants = NULL,
851 const TCHAR *entryPoint = NULL);
852 bool run(int argc, NXSL_Value **argv, NXSL_VariableSystem *pUserLocals = NULL,
853 NXSL_VariableSystem **ppGlobals = NULL, NXSL_VariableSystem *pConstants = NULL,
854 const TCHAR *entryPoint = NULL);
855 bool run() { ObjectArray<NXSL_Value> args(1, 1, false); return run(&args); }
856
857 UINT32 getCodeSize() { return m_instructionSet->size(); }
858
859 void trace(int level, const TCHAR *text);
860 void dump(FILE *pFile);
861 int getErrorCode() { return m_errorCode; }
862 int getErrorLine() { return m_errorLine; }
863 const TCHAR *getErrorText() { return CHECK_NULL_EX(m_errorText); }
864 NXSL_Value *getResult() { return m_pRetValue; }
865
866 void *getUserData() { return m_userData; }
867 void setUserData(void *data) { m_userData = data; }
868 };
869
870 /**
871 * NXSL "TableRow" class
872 */
873 class LIBNXSL_EXPORTABLE NXSL_TableRowClass : public NXSL_Class
874 {
875 public:
876 NXSL_TableRowClass();
877 virtual ~NXSL_TableRowClass();
878
879 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
880 virtual void onObjectDelete(NXSL_Object *object);
881 };
882
883 /**
884 * NXSL "TableColumn" class
885 */
886 class LIBNXSL_EXPORTABLE NXSL_TableColumnClass : public NXSL_Class
887 {
888 public:
889 NXSL_TableColumnClass();
890 virtual ~NXSL_TableColumnClass();
891
892 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
893 virtual void onObjectDelete(NXSL_Object *object);
894 };
895
896 /**
897 * NXSL "Table" class
898 */
899 class LIBNXSL_EXPORTABLE NXSL_TableClass : public NXSL_Class
900 {
901 public:
902 NXSL_TableClass();
903 virtual ~NXSL_TableClass();
904
905 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
906 virtual void onObjectDelete(NXSL_Object *object);
907 };
908
909 /**
910 * NXSL "StaticTable" class - table that is not deleted when ref count reaches 0
911 */
912 class LIBNXSL_EXPORTABLE NXSL_StaticTableClass : public NXSL_TableClass
913 {
914 public:
915 NXSL_StaticTableClass();
916 virtual ~NXSL_StaticTableClass();
917
918 virtual void onObjectDelete(NXSL_Object *object);
919 };
920
921 /**
922 * NXSL "Connector" class
923 */
924 class LIBNXSL_EXPORTABLE NXSL_ConnectorClass : public NXSL_Class
925 {
926 public:
927 NXSL_ConnectorClass();
928 virtual ~NXSL_ConnectorClass();
929
930 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
931 virtual void onObjectDelete(NXSL_Object *object);
932 };
933
934 /**
935 * NXSL "GeoLocation" class
936 */
937 class LIBNXSL_EXPORTABLE NXSL_GeoLocationClass : public NXSL_Class
938 {
939 public:
940 NXSL_GeoLocationClass();
941 virtual ~NXSL_GeoLocationClass();
942
943 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
944 virtual void onObjectDelete(NXSL_Object *object);
945
946 static NXSL_Value *createObject(const GeoLocation& gl);
947 };
948
949 /**
950 * NXSL "InetAddress" class
951 */
952 class LIBNXSL_EXPORTABLE NXSL_InetAddressClass : public NXSL_Class
953 {
954 public:
955 NXSL_InetAddressClass();
956 virtual ~NXSL_InetAddressClass();
957
958 virtual NXSL_Value *getAttr(NXSL_Object *pObject, const TCHAR *pszAttr);
959 virtual void onObjectDelete(NXSL_Object *object);
960
961 static NXSL_Value *createObject(const InetAddress& addr);
962 };
963
964 /**
965 * Class definition instances
966 */
967 extern NXSL_TableClass LIBNXSL_EXPORTABLE g_nxslTableClass;
968 extern NXSL_StaticTableClass LIBNXSL_EXPORTABLE g_nxslStaticTableClass;
969 extern NXSL_TableRowClass LIBNXSL_EXPORTABLE g_nxslTableRowClass;
970 extern NXSL_TableColumnClass LIBNXSL_EXPORTABLE g_nxslTableColumnClass;
971 extern NXSL_ConnectorClass LIBNXSL_EXPORTABLE g_nxslConnectorClass;
972 extern NXSL_GeoLocationClass LIBNXSL_EXPORTABLE g_nxslGeoLocationClass;
973 extern NXSL_InetAddressClass LIBNXSL_EXPORTABLE g_nxslInetAddressClass;
974
975 #endif