Commit | Line | Data |
---|---|---|
b36dc6ff VK |
1 | /* |
2 | ** NetXMS - Network Management System | |
6b29839d | 3 | ** Copyright (C) 2003-2014 Victor Kirhenshtein |
b36dc6ff VK |
4 | ** |
5 | ** This program is free software; you can redistribute it and/or modify | |
65d2c384 VK |
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 | |
b36dc6ff VK |
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 | ** | |
65d2c384 | 15 | ** You should have received a copy of the GNU Lesser General Public License |
b36dc6ff VK |
16 | ** along with this program; if not, write to the Free Software |
17 | ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
18 | ** | |
ccc34207 | 19 | ** File: nxsl_classes.h |
b36dc6ff VK |
20 | ** |
21 | **/ | |
22 | ||
23 | #ifndef _nxsl_classes_h_ | |
24 | #define _nxsl_classes_h_ | |
25 | ||
adbf1a29 VK |
26 | #include <nms_threads.h> |
27 | #include <nms_util.h> | |
9f2ad16c | 28 | #include <nxcpapi.h> |
bf9daa23 | 29 | #include <geolocation.h> |
adbf1a29 | 30 | |
b36dc6ff | 31 | // |
2c75fa6f VK |
32 | // Constants |
33 | // | |
34 | ||
35 | #define MAX_CLASS_NAME 64 | |
6b29839d | 36 | #define INVALID_ADDRESS ((UINT32)0xFFFFFFFF) |
2c75fa6f | 37 | |
6b29839d VK |
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, | |
06f09671 VK |
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 | |
6b29839d | 54 | }; |
b36dc6ff | 55 | |
49fbe41f VK |
56 | /** |
57 | * NXSL stack class | |
58 | */ | |
b36dc6ff VK |
59 | class LIBNXSL_EXPORTABLE NXSL_Stack |
60 | { | |
61 | private: | |
62 | int m_nStackSize; | |
63 | int m_nStackPos; | |
64 | void **m_ppData; | |
65 | ||
66 | public: | |
bb5365ed | 67 | NXSL_Stack(); |
b36dc6ff VK |
68 | ~NXSL_Stack(); |
69 | ||
bb5365ed VK |
70 | void push(void *pData); |
71 | void *pop(); | |
72 | void *peek(); | |
7de1151b | 73 | void *peekAt(int offset); |
bb5365ed | 74 | void **peekList(int nLevel) { return &m_ppData[m_nStackPos - nLevel]; } |
b36dc6ff | 75 | |
bb5365ed | 76 | int getSize() { return m_nStackPos; } |
b36dc6ff VK |
77 | }; |
78 | ||
2c75fa6f VK |
79 | class NXSL_Value; |
80 | class NXSL_Object; | |
6b29839d | 81 | class NXSL_VM; |
2c75fa6f | 82 | |
49fbe41f | 83 | /** |
55bdca5a VK |
84 | * External method structure |
85 | */ | |
86 | struct NXSL_ExtMethod | |
87 | { | |
6b29839d | 88 | int (* handler)(NXSL_Object *object, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm); |
55bdca5a VK |
89 | int numArgs; // Number of arguments or -1 for variable number |
90 | }; | |
91 | ||
63e99e56 VK |
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) | |
55bdca5a | 94 | |
63e99e56 | 95 | #define NXSL_REGISTER_METHOD(clazz, name, argc) { \ |
55bdca5a | 96 | NXSL_ExtMethod *m = new NXSL_ExtMethod; \ |
63e99e56 | 97 | m->handler = M_##clazz##_##name; \ |
55bdca5a VK |
98 | m->numArgs = argc; \ |
99 | m_methods->set(_T(#name), m); \ | |
100 | } | |
101 | ||
102 | /** | |
49fbe41f VK |
103 | * Class representing NXSL class |
104 | */ | |
2c75fa6f VK |
105 | class LIBNXSL_EXPORTABLE NXSL_Class |
106 | { | |
e2845745 | 107 | private: |
c42b4551 | 108 | TCHAR m_name[MAX_CLASS_NAME]; |
e2845745 VK |
109 | StringList m_classHierarchy; |
110 | ||
111 | protected: | |
55bdca5a | 112 | StringObjectMap<NXSL_ExtMethod> *m_methods; |
2c75fa6f | 113 | |
e2845745 VK |
114 | void setName(const TCHAR *name); |
115 | ||
2c75fa6f VK |
116 | public: |
117 | NXSL_Class(); | |
118 | virtual ~NXSL_Class(); | |
119 | ||
63e99e56 VK |
120 | virtual NXSL_Value *getAttr(NXSL_Object *object, const TCHAR *attr); |
121 | virtual bool setAttr(NXSL_Object *object, const TCHAR *attr, NXSL_Value *value); | |
2c75fa6f | 122 | |
6b29839d | 123 | virtual int callMethod(const TCHAR *name, NXSL_Object *object, int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm); |
49fbe41f | 124 | |
25e5c41d | 125 | virtual void onObjectCreate(NXSL_Object *object); |
bb5365ed | 126 | virtual void onObjectDelete(NXSL_Object *object); |
84ae3a17 | 127 | |
e2845745 VK |
128 | const TCHAR *getName() const { return m_name; } |
129 | bool instanceOf(const TCHAR *name) const { return !_tcscmp(name, m_name) || m_classHierarchy.contains(name); } | |
2c75fa6f VK |
130 | }; |
131 | ||
49fbe41f VK |
132 | /** |
133 | * Class data - object and reference count | |
134 | */ | |
bdd1560b VK |
135 | struct __nxsl_class_data |
136 | { | |
137 | void *data; | |
138 | int refCount; | |
139 | }; | |
140 | ||
49fbe41f VK |
141 | /** |
142 | * Object instance | |
143 | */ | |
2c75fa6f VK |
144 | class LIBNXSL_EXPORTABLE NXSL_Object |
145 | { | |
146 | private: | |
bdd1560b VK |
147 | NXSL_Class *m_class; |
148 | __nxsl_class_data *m_data; | |
2c75fa6f VK |
149 | |
150 | public: | |
25e5c41d VK |
151 | NXSL_Object(NXSL_Object *object); |
152 | NXSL_Object(NXSL_Class *nxslClass, void *data); | |
2c75fa6f | 153 | ~NXSL_Object(); |
9e52272a | 154 | |
bdd1560b VK |
155 | NXSL_Class *getClass() { return m_class; } |
156 | void *getData() { return m_data->data; } | |
2c75fa6f VK |
157 | }; |
158 | ||
49fbe41f | 159 | /** |
28e4009a VK |
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 | /** | |
49fbe41f VK |
180 | * Array element |
181 | */ | |
ffee16a5 VK |
182 | struct NXSL_ArrayElement |
183 | { | |
184 | int index; | |
185 | NXSL_Value *value; | |
186 | }; | |
187 | ||
49fbe41f VK |
188 | /** |
189 | * NXSL array | |
190 | */ | |
28e4009a | 191 | class LIBNXSL_EXPORTABLE NXSL_Array : public NXSL_HandleCountObject |
45ae7827 VK |
192 | { |
193 | private: | |
ffee16a5 VK |
194 | int m_size; |
195 | int m_allocated; | |
196 | NXSL_ArrayElement *m_data; | |
45ae7827 VK |
197 | |
198 | public: | |
199 | NXSL_Array(); | |
01116597 VK |
200 | NXSL_Array(const NXSL_Array *src); |
201 | NXSL_Array(const StringList *values); | |
45ae7827 VK |
202 | ~NXSL_Array(); |
203 | ||
503b147f VK |
204 | int size() const { return m_size; } |
205 | int getMinIndex() const { return (m_size > 0) ? m_data[0].index : 0; } | |
bc217f1b | 206 | int getMaxIndex() const { return (m_size > 0) ? m_data[m_size - 1].index : 0; } |
d32e7ef1 | 207 | |
503b147f VK |
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); | |
738119a1 VK |
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); | |
22aa5156 VK |
219 | }; |
220 | ||
55bdca5a | 221 | /** |
06f09671 VK |
222 | * NXSL hash map |
223 | */ | |
28e4009a | 224 | class LIBNXSL_EXPORTABLE NXSL_HashMap : public NXSL_HandleCountObject |
06f09671 VK |
225 | { |
226 | private: | |
06f09671 VK |
227 | StringObjectMap<NXSL_Value> *m_values; |
228 | ||
229 | public: | |
230 | NXSL_HashMap(); | |
231 | NXSL_HashMap(const NXSL_HashMap *src); | |
232 | ~NXSL_HashMap(); | |
233 | ||
06f09671 VK |
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); } | |
503b147f VK |
236 | NXSL_Value *getKeys() const; |
237 | NXSL_Value *getValues() const; | |
06f09671 | 238 | |
24bfa28b VK |
239 | StringMap *toStringMap() const; |
240 | ||
06f09671 VK |
241 | int size() const { return m_values->size(); } |
242 | }; | |
243 | ||
244 | /** | |
55bdca5a VK |
245 | * Iterator for arrays |
246 | */ | |
22aa5156 VK |
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--; } | |
28e4009a | 263 | bool isUnused() { return m_refCount < 1; } |
22aa5156 VK |
264 | |
265 | NXSL_Value *next(); | |
266 | ||
267 | static int createIterator(NXSL_Stack *stack); | |
45ae7827 VK |
268 | }; |
269 | ||
55bdca5a | 270 | /** |
28e4009a VK |
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 | /** | |
55bdca5a VK |
316 | * Variable or constant value |
317 | */ | |
b36dc6ff VK |
318 | class LIBNXSL_EXPORTABLE NXSL_Value |
319 | { | |
320 | protected: | |
967893bb | 321 | UINT32 m_dwStrLen; |
512623c4 | 322 | TCHAR *m_pszValStr; |
977e7d9d VK |
323 | #ifdef UNICODE |
324 | char *m_valueMBStr; // value as MB string; NULL until first request | |
325 | #endif | |
512623c4 | 326 | TCHAR *m_name; |
bd40de8f VK |
327 | BYTE m_nDataType; |
328 | BYTE m_bStringIsValid; | |
329 | union | |
330 | { | |
967893bb VK |
331 | INT32 nInt32; |
332 | UINT32 uInt32; | |
bd40de8f | 333 | INT64 nInt64; |
967893bb | 334 | UINT64 uInt64; |
bd40de8f | 335 | double dReal; |
06f09671 | 336 | NXSL_Object *object; |
06f09671 | 337 | NXSL_Iterator *iterator; |
28e4009a VK |
338 | NXSL_Handle<NXSL_Array> *arrayHandle; |
339 | NXSL_Handle<NXSL_HashMap> *hashMapHandle; | |
2c75fa6f | 340 | } m_value; |
bd40de8f | 341 | |
bb5365ed VK |
342 | void updateNumber(); |
343 | void updateString(); | |
b36dc6ff | 344 | |
bb5365ed | 345 | void invalidateString() |
9e52272a | 346 | { |
977e7d9d VK |
347 | safe_free_and_null(m_pszValStr); |
348 | #ifdef UNICODE | |
349 | safe_free_and_null(m_valueMBStr); | |
350 | #endif | |
9e52272a VK |
351 | m_bStringIsValid = FALSE; |
352 | } | |
353 | ||
b36dc6ff | 354 | public: |
bb5365ed | 355 | NXSL_Value(); |
06f09671 VK |
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); | |
967893bb | 361 | NXSL_Value(INT32 nValue); |
bd40de8f | 362 | NXSL_Value(INT64 nValue); |
967893bb VK |
363 | NXSL_Value(UINT32 uValue); |
364 | NXSL_Value(UINT64 uValue); | |
b36dc6ff | 365 | NXSL_Value(double dValue); |
06f09671 VK |
366 | NXSL_Value(const TCHAR *value); |
367 | NXSL_Value(const TCHAR *value, UINT32 len); | |
08b214c6 | 368 | #ifdef UNICODE |
06f09671 | 369 | NXSL_Value(const char *value); |
08b214c6 | 370 | #endif |
b36dc6ff VK |
371 | ~NXSL_Value(); |
372 | ||
06f09671 | 373 | void set(INT32 value); |
bb5365ed | 374 | |
06f09671 | 375 | void setName(const TCHAR *name) { safe_free(m_name); m_name = _tcsdup_ex(name); } |
4b47d7d7 | 376 | const TCHAR *getName() const { return m_name; } |
512623c4 | 377 | |
bb5365ed | 378 | bool convert(int nDataType); |
4b47d7d7 VK |
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); } | |
06f09671 | 385 | bool isHashMap() const { return (m_nDataType == NXSL_DT_HASHMAP); } |
4b47d7d7 VK |
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; | |
bb5365ed | 394 | |
06f09671 | 395 | const TCHAR *getValueAsString(UINT32 *len); |
bb5365ed | 396 | const TCHAR *getValueAsCString(); |
977e7d9d VK |
397 | #ifdef UNICODE |
398 | const char *getValueAsMBString(); | |
399 | #else | |
400 | const char *getValueAsMBString() { return getValueAsCString(); } | |
401 | #endif | |
967893bb VK |
402 | INT32 getValueAsInt32(); |
403 | UINT32 getValueAsUInt32(); | |
bb5365ed | 404 | INT64 getValueAsInt64(); |
967893bb | 405 | UINT64 getValueAsUInt64(); |
bb5365ed | 406 | double getValueAsReal(); |
034e2615 | 407 | bool getValueAsBoolean() { return getValueAsInt32() != 0; } |
06f09671 | 408 | NXSL_Object *getValueAsObject() { return (m_nDataType == NXSL_DT_OBJECT) ? m_value.object : NULL; } |
28e4009a VK |
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; } | |
06f09671 | 411 | NXSL_Iterator *getValueAsIterator() { return (m_nDataType == NXSL_DT_ITERATOR) ? m_value.iterator : NULL; } |
bb5365ed | 412 | |
06f09671 | 413 | void concatenate(const TCHAR *string, UINT32 len); |
bd40de8f | 414 | |
bb5365ed VK |
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); | |
bd40de8f VK |
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); | |
4b47d7d7 | 436 | |
28e4009a VK |
437 | void copyOnWrite(); |
438 | void onVariableSet(); | |
439 | ||
4b47d7d7 VK |
440 | bool equals(const NXSL_Value *v) const; |
441 | void serialize(ByteStream& s) const; | |
442 | ||
443 | static NXSL_Value *load(ByteStream& s); | |
b36dc6ff VK |
444 | }; |
445 | ||
49fbe41f VK |
446 | /** |
447 | * NXSL function definition structure | |
448 | */ | |
6b29839d | 449 | class NXSL_Function |
b36dc6ff | 450 | { |
6b29839d | 451 | public: |
c42b4551 | 452 | TCHAR m_name[MAX_FUNCTION_NAME]; |
967893bb | 453 | UINT32 m_dwAddr; |
6b29839d | 454 | |
c42b4551 VK |
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; } | |
4b47d7d7 | 457 | NXSL_Function(const TCHAR *name, UINT32 addr) { nx_strncpy(m_name, name, MAX_FUNCTION_NAME); m_dwAddr = addr; } |
b36dc6ff VK |
458 | }; |
459 | ||
49fbe41f VK |
460 | /** |
461 | * External function structure | |
462 | */ | |
b36dc6ff VK |
463 | struct NXSL_ExtFunction |
464 | { | |
c42b4551 | 465 | TCHAR m_name[MAX_FUNCTION_NAME]; |
6b29839d | 466 | int (* m_pfHandler)(int argc, NXSL_Value **argv, NXSL_Value **result, NXSL_VM *vm); |
bb5365ed | 467 | int m_iNumArgs; // Number of arguments or -1 for variable number |
b36dc6ff VK |
468 | }; |
469 | ||
f11423ed VK |
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 | ||
7e32778c VK |
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 | ||
fd421eca | 488 | class NXSL_Library; |
2791a0c9 | 489 | |
55bdca5a VK |
490 | /** |
491 | * Environment for NXSL program | |
492 | */ | |
b36dc6ff VK |
493 | class LIBNXSL_EXPORTABLE NXSL_Environment |
494 | { | |
495 | private: | |
bf9daa23 | 496 | int m_numFunctions; |
f11423ed | 497 | NXSL_ExtFunction *m_functions; |
b36dc6ff | 498 | |
bf9daa23 | 499 | int m_numSelectors; |
f11423ed VK |
500 | NXSL_ExtSelector *m_selectors; |
501 | ||
502 | NXSL_Library *m_library; | |
fd421eca | 503 | |
b36dc6ff VK |
504 | public: |
505 | NXSL_Environment(); | |
c5e1f0bb | 506 | virtual ~NXSL_Environment(); |
b36dc6ff | 507 | |
2773ef30 | 508 | virtual void print(NXSL_Value *value); |
bb5365ed VK |
509 | virtual void trace(int level, const TCHAR *text); |
510 | ||
6b1f3e44 VK |
511 | virtual void configureVM(NXSL_VM *vm); |
512 | ||
f11423ed VK |
513 | void setLibrary(NXSL_Library *lib) { m_library = lib; } |
514 | ||
515 | NXSL_ExtFunction *findFunction(const TCHAR *name); | |
bf9daa23 | 516 | void registerFunctionSet(int count, NXSL_ExtFunction *list); |
fd421eca | 517 | |
f11423ed | 518 | NXSL_ExtSelector *findSelector(const TCHAR *name); |
bf9daa23 | 519 | void registerSelectorSet(int count, NXSL_ExtSelector *list); |
2791a0c9 | 520 | |
7e32778c | 521 | bool loadModule(NXSL_VM *vm, const NXSL_ModuleImport *importInfo); |
b36dc6ff VK |
522 | }; |
523 | ||
3993eba0 VK |
524 | /** |
525 | * Runtime variable information | |
526 | */ | |
b36dc6ff VK |
527 | class LIBNXSL_EXPORTABLE NXSL_Variable |
528 | { | |
529 | protected: | |
530 | TCHAR *m_pszName; | |
531 | NXSL_Value *m_pValue; | |
c742e8c8 | 532 | bool m_isConstant; |
b36dc6ff VK |
533 | |
534 | public: | |
1b41ebe2 | 535 | NXSL_Variable(const TCHAR *pszName); |
c742e8c8 | 536 | NXSL_Variable(const TCHAR *pszName, NXSL_Value *pValue, bool constant = false); |
b36dc6ff VK |
537 | NXSL_Variable(NXSL_Variable *pSrc); |
538 | ~NXSL_Variable(); | |
539 | ||
bb5365ed VK |
540 | const TCHAR *getName() { return m_pszName; } |
541 | NXSL_Value *getValue() { return m_pValue; } | |
542 | void setValue(NXSL_Value *pValue); | |
c742e8c8 | 543 | bool isConstant() { return m_isConstant; } |
b36dc6ff VK |
544 | }; |
545 | ||
18321496 VK |
546 | /** |
547 | * Varable system | |
548 | */ | |
b36dc6ff VK |
549 | class LIBNXSL_EXPORTABLE NXSL_VariableSystem |
550 | { | |
551 | protected: | |
6b29839d | 552 | ObjectArray<NXSL_Variable> *m_variables; |
c742e8c8 | 553 | bool m_isConstant; |
b36dc6ff VK |
554 | |
555 | public: | |
c742e8c8 | 556 | NXSL_VariableSystem(bool constant = false); |
6b29839d | 557 | NXSL_VariableSystem(NXSL_VariableSystem *src); |
b36dc6ff VK |
558 | ~NXSL_VariableSystem(); |
559 | ||
bb5365ed VK |
560 | NXSL_Variable *find(const TCHAR *pszName); |
561 | NXSL_Variable *create(const TCHAR *pszName, NXSL_Value *pValue = NULL); | |
c742e8c8 | 562 | void merge(NXSL_VariableSystem *src); |
6b29839d VK |
563 | void addAll(StringObjectMap<NXSL_Value> *src); |
564 | void clear() { m_variables->clear(); } | |
c742e8c8 | 565 | bool isConstant() { return m_isConstant; } |
b36dc6ff VK |
566 | }; |
567 | ||
18321496 | 568 | /** |
4b47d7d7 VK |
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 | /** | |
18321496 VK |
580 | * Single execution instruction |
581 | */ | |
b36dc6ff VK |
582 | class LIBNXSL_EXPORTABLE NXSL_Instruction |
583 | { | |
584 | friend class NXSL_Program; | |
6b29839d | 585 | friend class NXSL_VM; |
b36dc6ff VK |
586 | |
587 | protected: | |
4b47d7d7 VK |
588 | INT16 m_nOpCode; |
589 | INT16 m_nStackItems; | |
b36dc6ff VK |
590 | union |
591 | { | |
592 | NXSL_Value *m_pConstant; | |
08b214c6 | 593 | TCHAR *m_pszString; |
967893bb | 594 | UINT32 m_dwAddr; |
b36dc6ff | 595 | } m_operand; |
4b47d7d7 | 596 | INT32 m_nSourceLine; |
b36dc6ff VK |
597 | |
598 | public: | |
57f34c0a VK |
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); | |
2791a0c9 | 605 | NXSL_Instruction(NXSL_Instruction *pSrc); |
b36dc6ff | 606 | ~NXSL_Instruction(); |
4b47d7d7 VK |
607 | |
608 | OperandType getOperandType(); | |
b36dc6ff VK |
609 | }; |
610 | ||
55bdca5a VK |
611 | /** |
612 | * NXSL module information | |
613 | */ | |
2791a0c9 VK |
614 | struct NXSL_Module |
615 | { | |
6b29839d VK |
616 | TCHAR m_name[MAX_PATH]; |
617 | UINT32 m_codeStart; | |
618 | int m_codeSize; | |
619 | int m_functionStart; | |
620 | int m_numFunctions; | |
2791a0c9 VK |
621 | }; |
622 | ||
55bdca5a | 623 | /** |
6b29839d | 624 | * Compiled NXSL program |
55bdca5a | 625 | */ |
b36dc6ff VK |
626 | class LIBNXSL_EXPORTABLE NXSL_Program |
627 | { | |
6b29839d VK |
628 | friend class NXSL_VM; |
629 | ||
b36dc6ff | 630 | protected: |
6b29839d | 631 | ObjectArray<NXSL_Instruction> *m_instructionSet; |
7e32778c | 632 | ObjectArray<NXSL_ModuleImport> *m_requiredModules; |
6b29839d VK |
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); } | |
f11423ed | 645 | void resolveLastJump(int opcode, int offset = 0); |
6b29839d | 646 | void createJumpAt(UINT32 dwOpAddr, UINT32 dwJumpAddr); |
7e32778c | 647 | void addRequiredModule(const char *name, int lineNumber); |
6b29839d VK |
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); | |
4b47d7d7 VK |
655 | void serialize(ByteStream& s); |
656 | ||
657 | static NXSL_Program *load(ByteStream& s, TCHAR *errMsg, size_t errMsgSize); | |
6b29839d VK |
658 | }; |
659 | ||
660 | /** | |
0207b7dd EJ |
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 | /** | |
6b29839d VK |
694 | * Script library |
695 | */ | |
696 | class LIBNXSL_EXPORTABLE NXSL_Library | |
697 | { | |
698 | private: | |
0207b7dd | 699 | ObjectArray<NXSL_LibraryScript> *m_scriptList; |
6b29839d VK |
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); } | |
b36dc6ff | 710 | |
0207b7dd | 711 | BOOL addScript(NXSL_LibraryScript *script); |
6b29839d VK |
712 | void deleteScript(const TCHAR *name); |
713 | void deleteScript(UINT32 id); | |
0207b7dd EJ |
714 | NXSL_Program *findNxslProgram(const TCHAR *name); |
715 | NXSL_LibraryScript *findScript(UINT32 id); | |
6b29839d | 716 | NXSL_VM *createVM(const TCHAR *name, NXSL_Environment *env); |
b36dc6ff | 717 | |
0207b7dd | 718 | void fillMessage(NXCPMessage *msg); |
6b29839d VK |
719 | }; |
720 | ||
721 | /** | |
a3906178 VK |
722 | * Catch point information |
723 | */ | |
724 | struct NXSL_CatchPoint | |
725 | { | |
726 | UINT32 addr; | |
727 | UINT32 subLevel; | |
728 | int dataStackSize; | |
729 | }; | |
730 | ||
731 | /** | |
19eae342 VK |
732 | * NXSL storage class - base class for actual persistent storage |
733 | */ | |
734 | class LIBNXSL_EXPORTABLE NXSL_Storage | |
735 | { | |
c73892ef VK |
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 | { | |
19eae342 VK |
757 | protected: |
758 | StringObjectMap<NXSL_Value> *m_values; | |
759 | ||
760 | public: | |
c73892ef VK |
761 | NXSL_LocalStorage(); |
762 | virtual ~NXSL_LocalStorage(); | |
19eae342 VK |
763 | |
764 | virtual void write(const TCHAR *name, NXSL_Value *value); | |
765 | virtual NXSL_Value *read(const TCHAR *name); | |
766 | }; | |
767 | ||
768 | /** | |
6b29839d VK |
769 | * NXSL virtual machine |
770 | */ | |
771 | class LIBNXSL_EXPORTABLE NXSL_VM | |
772 | { | |
400e55c4 | 773 | private: |
53c3d1e7 | 774 | static EnumerationCallbackResult createConstantsCallback(const TCHAR *key, const void *value, void *data); |
400e55c4 | 775 | |
6b29839d VK |
776 | protected: |
777 | NXSL_Environment *m_env; | |
778 | void *m_userData; | |
779 | ||
780 | ObjectArray<NXSL_Instruction> *m_instructionSet; | |
781 | UINT32 m_cp; | |
2791a0c9 | 782 | |
967893bb | 783 | UINT32 m_dwSubLevel; |
a3906178 VK |
784 | NXSL_Stack *m_dataStack; |
785 | NXSL_Stack *m_codeStack; | |
786 | NXSL_Stack *m_catchStack; | |
b36dc6ff VK |
787 | int m_nBindPos; |
788 | ||
400e55c4 VK |
789 | NXSL_VariableSystem *m_constants; |
790 | NXSL_VariableSystem *m_globals; | |
791 | NXSL_VariableSystem *m_locals; | |
b36dc6ff | 792 | |
19eae342 VK |
793 | NXSL_Storage *m_storage; |
794 | NXSL_Storage *m_localStorage; | |
795 | ||
6b29839d VK |
796 | ObjectArray<NXSL_Function> *m_functions; |
797 | ObjectArray<NXSL_Module> *m_modules; | |
2791a0c9 | 798 | |
9e52272a | 799 | NXSL_Value *m_pRetValue; |
a3906178 VK |
800 | int m_errorCode; |
801 | int m_errorLine; | |
802 | TCHAR *m_errorText; | |
b36dc6ff | 803 | |
bb5365ed | 804 | void execute(); |
a3906178 | 805 | bool unwind(); |
bb5365ed | 806 | void callFunction(int nArgCount); |
f11423ed | 807 | UINT32 callSelector(const TCHAR *name, int numElements); |
bb5365ed VK |
808 | void doUnaryOperation(int nOpCode); |
809 | void doBinaryOperation(int nOpCode); | |
06f09671 VK |
810 | void getOrUpdateArrayElement(int opcode, NXSL_Value *array, NXSL_Value *index); |
811 | bool setArrayElement(NXSL_Value *array, NXSL_Value *index, NXSL_Value *value); | |
bc217f1b | 812 | void getArrayAttribute(NXSL_Array *a, const TCHAR *attribute, bool safe); |
06f09671 VK |
813 | void getOrUpdateHashMapElement(int opcode, NXSL_Value *hashMap, NXSL_Value *key); |
814 | bool setHashMapElement(NXSL_Value *hashMap, NXSL_Value *key, NXSL_Value *value); | |
bc217f1b | 815 | void getHashMapAttribute(NXSL_HashMap *m, const TCHAR *attribute, bool safe); |
7e32778c | 816 | void error(int errorCode, int sourceLine = -1); |
bb5365ed | 817 | NXSL_Value *matchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp, BOOL bIgnoreCase); |
b36dc6ff | 818 | |
bd9ffdf0 | 819 | NXSL_Variable *findVariable(const TCHAR *pszName); |
22aa5156 VK |
820 | NXSL_Variable *findOrCreateVariable(const TCHAR *pszName); |
821 | NXSL_Variable *createVariable(const TCHAR *pszName); | |
b36dc6ff | 822 | |
967893bb | 823 | void relocateCode(UINT32 dwStartOffset, UINT32 dwLen, UINT32 dwShift); |
6b29839d | 824 | UINT32 getFunctionAddress(const TCHAR *pszName); |
2791a0c9 | 825 | |
b36dc6ff | 826 | public: |
19eae342 | 827 | NXSL_VM(NXSL_Environment *env = NULL, NXSL_Storage *storage = NULL); |
6b29839d | 828 | ~NXSL_VM(); |
b36dc6ff | 829 | |
7e32778c | 830 | void loadModule(NXSL_Program *module, const NXSL_ModuleImport *importInfo); |
b36dc6ff | 831 | |
bb5365ed | 832 | void setGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue); |
400e55c4 | 833 | NXSL_Variable *findGlobalVariable(const TCHAR *pszName) { return m_globals->find(pszName); } |
1b41ebe2 | 834 | |
99730c0c VK |
835 | bool addConstant(const TCHAR *name, NXSL_Value *value); |
836 | ||
0a96e4e9 VK |
837 | void setStorage(NXSL_Storage *storage); |
838 | ||
19eae342 VK |
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 | ||
6b29839d | 848 | bool load(NXSL_Program *program); |
17b1ab4a | 849 | bool run(ObjectArray<NXSL_Value> *args, NXSL_VariableSystem *pUserLocals = NULL, |
0fa2aacc VK |
850 | NXSL_VariableSystem **ppGlobals = NULL, NXSL_VariableSystem *pConstants = NULL, |
851 | const TCHAR *entryPoint = NULL); | |
17b1ab4a | 852 | bool run(int argc, NXSL_Value **argv, NXSL_VariableSystem *pUserLocals = NULL, |
6b29839d VK |
853 | NXSL_VariableSystem **ppGlobals = NULL, NXSL_VariableSystem *pConstants = NULL, |
854 | const TCHAR *entryPoint = NULL); | |
17b1ab4a | 855 | bool run() { ObjectArray<NXSL_Value> args(1, 1, false); return run(&args); } |
b36dc6ff | 856 | |
6b29839d | 857 | UINT32 getCodeSize() { return m_instructionSet->size(); } |
1f564860 | 858 | |
bb5365ed VK |
859 | void trace(int level, const TCHAR *text); |
860 | void dump(FILE *pFile); | |
a3906178 VK |
861 | int getErrorCode() { return m_errorCode; } |
862 | int getErrorLine() { return m_errorLine; } | |
863 | const TCHAR *getErrorText() { return CHECK_NULL_EX(m_errorText); } | |
bb5365ed | 864 | NXSL_Value *getResult() { return m_pRetValue; } |
f76f2296 VK |
865 | |
866 | void *getUserData() { return m_userData; } | |
867 | void setUserData(void *data) { m_userData = data; } | |
b36dc6ff VK |
868 | }; |
869 | ||
55bdca5a | 870 | /** |
594b54e7 VK |
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 | /** | |
967893bb VK |
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 | /** | |
55bdca5a VK |
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 | }; | |
2791a0c9 | 908 | |
adf6f870 | 909 | /** |
7de1151b VK |
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 | /** | |
adf6f870 AK |
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 | ||
7de1151b | 934 | /** |
bf9daa23 | 935 | * NXSL "GeoLocation" class |
63e99e56 VK |
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); | |
bf9daa23 VK |
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); | |
63e99e56 VK |
962 | }; |
963 | ||
964 | /** | |
7de1151b VK |
965 | * Class definition instances |
966 | */ | |
967 | extern NXSL_TableClass LIBNXSL_EXPORTABLE g_nxslTableClass; | |
968 | extern NXSL_StaticTableClass LIBNXSL_EXPORTABLE g_nxslStaticTableClass; | |
594b54e7 | 969 | extern NXSL_TableRowClass LIBNXSL_EXPORTABLE g_nxslTableRowClass; |
967893bb | 970 | extern NXSL_TableColumnClass LIBNXSL_EXPORTABLE g_nxslTableColumnClass; |
7de1151b | 971 | extern NXSL_ConnectorClass LIBNXSL_EXPORTABLE g_nxslConnectorClass; |
63e99e56 | 972 | extern NXSL_GeoLocationClass LIBNXSL_EXPORTABLE g_nxslGeoLocationClass; |
bf9daa23 | 973 | extern NXSL_InetAddressClass LIBNXSL_EXPORTABLE g_nxslInetAddressClass; |
7de1151b | 974 | |
b36dc6ff | 975 | #endif |