NXSL: arrays implemented
[public/netxms.git] / include / nxsl_classes.h
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2005, 2006 Victor Kirhenshtein
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 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 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 ** $module: 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
30
31 //
32 // Constants
33 //
34
35 #define MAX_CLASS_NAME 64
36
37
38 //
39 // Data types
40 //
41
42 #define NXSL_DT_NULL 0
43 #define NXSL_DT_OBJECT 1
44 #define NXSL_DT_ARRAY 2
45 #define NXSL_DT_STRING 3
46 #define NXSL_DT_REAL 4
47 #define NXSL_DT_INT32 5
48 #define NXSL_DT_INT64 6
49 #define NXSL_DT_UINT32 7
50 #define NXSL_DT_UINT64 8
51
52
53 //
54 // Simple stack class
55 //
56
57 class LIBNXSL_EXPORTABLE NXSL_Stack
58 {
59 private:
60 int m_nStackSize;
61 int m_nStackPos;
62 void **m_ppData;
63
64 public:
65 NXSL_Stack(void);
66 ~NXSL_Stack();
67
68 void Push(void *pData);
69 void *Pop(void);
70 void *Peek(void);
71 void **PeekList(int nLevel) { return &m_ppData[m_nStackPos - nLevel]; }
72
73 int Size(void) { return m_nStackPos; }
74 };
75
76
77 //
78 // Class representing NXSL class
79 //
80
81 class NXSL_Value;
82 class NXSL_Object;
83
84 class LIBNXSL_EXPORTABLE NXSL_Class
85 {
86 protected:
87 char m_szName[MAX_CLASS_NAME];
88
89 public:
90 NXSL_Class();
91 virtual ~NXSL_Class();
92
93 virtual NXSL_Value *GetAttr(NXSL_Object *pObject, char *pszAttr);
94 virtual BOOL SetAttr(NXSL_Object *pObject, char *pszAttr, NXSL_Value *pValue);
95
96 virtual void OnObjectDelete(NXSL_Object *object);
97
98 char *Name(void) { return m_szName; }
99 };
100
101
102 //
103 // Object instance
104 //
105
106 class LIBNXSL_EXPORTABLE NXSL_Object
107 {
108 private:
109 NXSL_Class *m_pClass;
110 void *m_pData;
111
112 public:
113 NXSL_Object(NXSL_Object *pObject);
114 NXSL_Object(NXSL_Class *pClass, void *pData);
115 ~NXSL_Object();
116
117 NXSL_Class *Class() { return m_pClass; }
118 void *Data() { return m_pData; }
119 };
120
121
122 //
123 // Array
124 //
125
126 struct NXSL_ArrayElement
127 {
128 int index;
129 NXSL_Value *value;
130 };
131
132 class LIBNXSL_EXPORTABLE NXSL_Array
133 {
134 private:
135 int m_refCount;
136 int m_size;
137 int m_allocated;
138 NXSL_ArrayElement *m_data;
139
140 public:
141 NXSL_Array();
142 NXSL_Array(NXSL_Array *src);
143 ~NXSL_Array();
144
145 void IncRefCount() { m_refCount++; }
146 void DecRefCount() { m_refCount--; }
147 BOOL IsUnused() { return m_refCount < 1; }
148
149 void Set(int index, NXSL_Value *value);
150 NXSL_Value *Get(int index);
151 };
152
153
154 //
155 // Variable or constant value
156 //
157
158 class LIBNXSL_EXPORTABLE NXSL_Value
159 {
160 protected:
161 DWORD m_dwStrLen;
162 char *m_pszValStr;
163 BYTE m_nDataType;
164 BYTE m_bStringIsValid;
165 union
166 {
167 LONG nInt32;
168 DWORD uInt32;
169 INT64 nInt64;
170 QWORD uInt64;
171 double dReal;
172 NXSL_Object *pObject;
173 NXSL_Array *pArray;
174 } m_value;
175
176 void UpdateNumber(void);
177 void UpdateString(void);
178
179 void InvalidateString(void)
180 {
181 safe_free(m_pszValStr);
182 m_pszValStr = NULL;
183 m_bStringIsValid = FALSE;
184 }
185
186 public:
187 NXSL_Value(void);
188 NXSL_Value(const NXSL_Value *);
189 NXSL_Value(NXSL_Object *pObject);
190 NXSL_Value(NXSL_Array *pArray);
191 NXSL_Value(LONG nValue);
192 NXSL_Value(INT64 nValue);
193 NXSL_Value(DWORD uValue);
194 NXSL_Value(QWORD uValue);
195 NXSL_Value(double dValue);
196 NXSL_Value(const TCHAR *pszValue);
197 NXSL_Value(const TCHAR *pszValue, DWORD dwLen);
198 ~NXSL_Value();
199
200 void Set(LONG nValue);
201
202 BOOL Convert(int nDataType);
203 int DataType(void) { return m_nDataType; }
204
205 BOOL IsNull(void) { return (m_nDataType == NXSL_DT_NULL); }
206 BOOL IsObject(void) { return (m_nDataType == NXSL_DT_OBJECT); }
207 BOOL IsArray(void) { return (m_nDataType == NXSL_DT_ARRAY); }
208 BOOL IsString(void) { return (m_nDataType >= NXSL_DT_STRING); }
209 BOOL IsNumeric(void) { return (m_nDataType > NXSL_DT_STRING); }
210 BOOL IsReal(void) { return (m_nDataType == NXSL_DT_REAL); }
211 BOOL IsInteger(void) { return (m_nDataType > NXSL_DT_REAL); }
212 BOOL IsUnsigned(void) { return (m_nDataType >= NXSL_DT_UINT32); }
213 BOOL IsZero(void);
214 BOOL IsNonZero(void);
215
216 char *GetValueAsString(DWORD *pdwLen);
217 char *GetValueAsCString(void);
218 LONG GetValueAsInt32(void);
219 DWORD GetValueAsUInt32(void);
220 INT64 GetValueAsInt64(void);
221 QWORD GetValueAsUInt64(void);
222 double GetValueAsReal(void);
223 NXSL_Object *GetValueAsObject(void) { return (m_nDataType == NXSL_DT_OBJECT) ? m_value.pObject : NULL; }
224 NXSL_Array *GetValueAsArray(void) { return (m_nDataType == NXSL_DT_ARRAY) ? m_value.pArray : NULL; }
225
226 void Concatenate(char *pszString, DWORD dwLen);
227
228 void Increment(void);
229 void Decrement(void);
230 void Negate(void);
231 void BitNot(void);
232
233 void Add(NXSL_Value *pVal);
234 void Sub(NXSL_Value *pVal);
235 void Mul(NXSL_Value *pVal);
236 void Div(NXSL_Value *pVal);
237 void Rem(NXSL_Value *pVal);
238 void BitAnd(NXSL_Value *pVal);
239 void BitOr(NXSL_Value *pVal);
240 void BitXor(NXSL_Value *pVal);
241 void LShift(int nBits);
242 void RShift(int nBits);
243
244 BOOL EQ(NXSL_Value *pVal);
245 BOOL LT(NXSL_Value *pVal);
246 BOOL LE(NXSL_Value *pVal);
247 BOOL GT(NXSL_Value *pVal);
248 BOOL GE(NXSL_Value *pVal);
249 };
250
251
252 //
253 // Function structure
254 //
255
256 struct NXSL_Function
257 {
258 char m_szName[MAX_FUNCTION_NAME];
259 DWORD m_dwAddr;
260 };
261
262
263 //
264 // External function structure
265 //
266
267 struct NXSL_ExtFunction
268 {
269 char m_szName[MAX_FUNCTION_NAME];
270 int (* m_pfHandler)(int argc, NXSL_Value **argv, NXSL_Value **ppResult);
271 int m_iNumArgs; // Number of arguments or -1 fo variable number
272 };
273
274
275 //
276 // Environment for NXSL program
277 //
278
279 class NXSL_Program;
280 class NXSL_Library;
281
282 class LIBNXSL_EXPORTABLE NXSL_Environment
283 {
284 private:
285 DWORD m_dwNumFunctions;
286 NXSL_ExtFunction *m_pFunctionList;
287
288 NXSL_Library *m_pLibrary;
289
290 FILE *m_pStdIn;
291 FILE *m_pStdOut;
292
293 public:
294 NXSL_Environment();
295 ~NXSL_Environment();
296
297 void SetIO(FILE *pIn, FILE *pOut) { m_pStdIn = pIn; m_pStdOut = pOut; }
298 FILE *GetStdIn(void) { return m_pStdIn; }
299 FILE *GetStdOut(void) { return m_pStdOut; }
300
301 void SetLibrary(NXSL_Library *pLib) { m_pLibrary = pLib; }
302
303 NXSL_ExtFunction *FindFunction(char *pszName);
304 void RegisterFunctionSet(DWORD dwNumFunctions, NXSL_ExtFunction *pList);
305
306 BOOL UseModule(NXSL_Program *pMain, char *pszName);
307 };
308
309
310 //
311 // Runtime variable information
312 //
313
314 class LIBNXSL_EXPORTABLE NXSL_Variable
315 {
316 protected:
317 TCHAR *m_pszName;
318 NXSL_Value *m_pValue;
319
320 public:
321 NXSL_Variable(const TCHAR *pszName);
322 NXSL_Variable(const TCHAR *pszName, NXSL_Value *pValue);
323 NXSL_Variable(NXSL_Variable *pSrc);
324 ~NXSL_Variable();
325
326 const TCHAR *Name(void) { return m_pszName; }
327 NXSL_Value *Value(void) { return m_pValue; }
328 void Set(NXSL_Value *pValue);
329 };
330
331
332 //
333 // Varable system
334 //
335
336 class LIBNXSL_EXPORTABLE NXSL_VariableSystem
337 {
338 protected:
339 DWORD m_dwNumVariables;
340 NXSL_Variable **m_ppVariableList;
341
342 public:
343 NXSL_VariableSystem(void);
344 NXSL_VariableSystem(NXSL_VariableSystem *pSrc);
345 ~NXSL_VariableSystem();
346
347 NXSL_Variable *Find(const TCHAR *pszName);
348 NXSL_Variable *Create(const TCHAR *pszName, NXSL_Value *pValue = NULL);
349 };
350
351
352 //
353 // Single execution instruction
354 //
355
356 class LIBNXSL_EXPORTABLE NXSL_Instruction
357 {
358 friend class NXSL_Program;
359
360 protected:
361 int m_nOpCode;
362 union
363 {
364 NXSL_Value *m_pConstant;
365 char *m_pszString;
366 DWORD m_dwAddr;
367 } m_operand;
368 int m_nStackItems;
369 int m_nSourceLine;
370
371 public:
372 NXSL_Instruction(int nLine, int nOpCode);
373 NXSL_Instruction(int nLine, int nOpCode, NXSL_Value *pValue);
374 NXSL_Instruction(int nLine, int nOpCode, char *pszString);
375 NXSL_Instruction(int nLine, int nOpCode, char *pszString, int nStackItems);
376 NXSL_Instruction(int nLine, int nOpCode, DWORD dwAddr);
377 NXSL_Instruction(int nLine, int nOpCode, int nStackItems);
378 NXSL_Instruction(NXSL_Instruction *pSrc);
379 ~NXSL_Instruction();
380 };
381
382
383 //
384 // Used module information
385 //
386
387 struct NXSL_Module
388 {
389 char m_szName[MAX_PATH];
390 DWORD m_dwCodeStart;
391 DWORD m_dwCodeSize;
392 DWORD m_dwFunctionStart;
393 DWORD m_dwNumFunctions;
394 };
395
396
397 //
398 // Class representing compiled NXSL program
399 //
400
401 class LIBNXSL_EXPORTABLE NXSL_Program
402 {
403 protected:
404 NXSL_Environment *m_pEnv;
405
406 NXSL_Instruction **m_ppInstructionSet;
407 DWORD m_dwCodeSize;
408 DWORD m_dwCurrPos;
409
410 DWORD m_dwNumPreloads;
411 char **m_ppszPreloadList;
412
413 DWORD m_dwSubLevel;
414 NXSL_Stack *m_pDataStack;
415 NXSL_Stack *m_pCodeStack;
416 int m_nBindPos;
417
418 NXSL_VariableSystem *m_pConstants;
419 NXSL_VariableSystem *m_pGlobals;
420 NXSL_VariableSystem *m_pLocals;
421
422 DWORD m_dwNumFunctions;
423 NXSL_Function *m_pFunctionList;
424
425 DWORD m_dwNumModules;
426 NXSL_Module *m_pModuleList;
427
428 NXSL_Value *m_pRetValue;
429 int m_nErrorCode;
430 TCHAR *m_pszErrorText;
431
432 void Execute(void);
433 void CallFunction(int nArgCount);
434 void DoUnaryOperation(int nOpCode);
435 void DoBinaryOperation(int nOpCode);
436 void Error(int nError);
437 NXSL_Value *MatchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp, BOOL bIgnoreCase);
438
439 NXSL_Variable *FindOrCreateVariable(TCHAR *pszName);
440 NXSL_Variable *CreateVariable(TCHAR *pszName);
441
442 DWORD GetFunctionAddress(char *pszName);
443 void RelocateCode(DWORD dwStartOffset, DWORD dwLen, DWORD dwShift);
444 DWORD FinalJumpDestination(DWORD dwAddr);
445
446 public:
447 NXSL_Program(void);
448 ~NXSL_Program();
449
450 BOOL AddFunction(const char *pszName, DWORD dwAddr, char *pszError);
451 void ResolveFunctions(void);
452 void AddInstruction(NXSL_Instruction *pInstruction);
453 void ResolveLastJump(int nOpCode);
454 void CreateJumpAt(DWORD dwOpAddr, DWORD dwJumpAddr);
455 void AddPreload(char *pszName);
456 void UseModule(NXSL_Program *pModule, const char *pszName);
457 void Optimize(void);
458
459 void SetGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue);
460 NXSL_Variable *FindGlobalVariable(const TCHAR *pszName) { return m_pGlobals->Find(pszName); }
461
462 int Run(NXSL_Environment *pEnv = NULL, DWORD argc = 0,
463 NXSL_Value **argv = NULL, NXSL_VariableSystem *pUserLocals = NULL,
464 NXSL_VariableSystem **ppGlobals = NULL);
465
466 DWORD CodeSize(void) { return m_dwCodeSize; }
467
468 void Dump(FILE *pFile);
469 TCHAR *GetErrorText(void) { return m_pszErrorText; }
470 NXSL_Value *GetResult(void) { return m_pRetValue; }
471 };
472
473
474 //
475 // Script library
476 //
477
478 class LIBNXSL_EXPORTABLE NXSL_Library
479 {
480 private:
481 DWORD m_dwNumScripts;
482 NXSL_Program **m_ppScriptList;
483 char **m_ppszNames;
484 DWORD *m_pdwIdList;
485 MUTEX m_mutex;
486
487 void Delete(int nIndex);
488
489 public:
490 NXSL_Library(void);
491 ~NXSL_Library();
492
493 void Lock(void) { MutexLock(m_mutex, INFINITE); }
494 void Unlock(void) { MutexUnlock(m_mutex); }
495
496 BOOL AddScript(DWORD dwId, char *pszName, NXSL_Program *pScript);
497 void DeleteScript(char *pszName);
498 void DeleteScript(DWORD dwId);
499 NXSL_Program *FindScript(char *pszName);
500
501 void FillMessage(CSCPMessage *pMsg);
502 };
503
504
505 #endif