- DCI transformations implemented
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Jan 2006 20:17:16 +0000 (20:17 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Jan 2006 20:17:16 +0000 (20:17 +0000)
- Added possibility to pass parameters to script
- Other changes in NXSL interpreter

19 files changed:
ChangeLog
include/nxsl.h
include/nxsl_classes.h
src/libnxsl/class.cpp
src/libnxsl/env.cpp
src/libnxsl/libnxsl.h
src/libnxsl/main.cpp
src/libnxsl/parser.l
src/libnxsl/parser.y
src/libnxsl/program.cpp
src/libnxsl/value.cpp
src/nxscript/nxscript.cpp
src/nxscript/nxscript.dsp
src/nxscript/nxscript.h
src/server/core/dbwrite.cpp
src/server/core/dcitem.cpp
src/server/core/nxcore.dsp
src/server/include/nms_core.h
src/server/include/nms_dcoll.h

index 18351b6..38ace14 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,8 @@
 * 0.2.9
 *
 
+- Added built-in scripting language
+- Implemented DCI transformations
 - Fixed issues: #68
 
 
index 542f78a..6a3b3d9 100644 (file)
@@ -58,6 +58,8 @@
 #define NXSL_ERR_NO_FUNCTION              11
 #define NXSL_ERR_INVALID_ARGUMENT_COUNT   12
 #define NXSL_ERR_TYPE_CAST                13
+#define NXSL_ERR_NOT_OBJECT               14
+#define NXSL_ERR_NO_SUCH_ATTRIBUTE        15
 
 
 //
index 88b0c71..17a14cb 100644 (file)
@@ -103,8 +103,12 @@ private:
    void *m_pData;
 
 public:
+   NXSL_Object(NXSL_Object *pObject);
    NXSL_Object(NXSL_Class *pClass, void *pData);
    ~NXSL_Object();
+
+   NXSL_Class *Class(void) { return m_pClass; }
+   void *Data(void) { return m_pData; }
 };
 
 
@@ -132,9 +136,17 @@ protected:
    void UpdateNumber(void);
    void UpdateString(void);
 
+   void InvalidateString(void)
+   {
+      safe_free(m_pszValStr);
+      m_pszValStr = NULL;
+      m_bStringIsValid = FALSE;
+   }
+
 public:
    NXSL_Value(void);
    NXSL_Value(NXSL_Value *);
+   NXSL_Value(NXSL_Object *pObject);
    NXSL_Value(LONG nValue);
    NXSL_Value(INT64 nValue);
    NXSL_Value(DWORD uValue);
@@ -149,6 +161,7 @@ public:
    int DataType(void) { return m_nDataType; }
 
    BOOL IsNull(void) { return (m_nDataType == NXSL_DT_NULL); }
+   BOOL IsObject(void) { return (m_nDataType == NXSL_DT_OBJECT); }
    BOOL IsNumeric(void) { return (m_nDataType > NXSL_DT_STRING); }
    BOOL IsReal(void) { return (m_nDataType == NXSL_DT_REAL); }
    BOOL IsInteger(void) { return (m_nDataType > NXSL_DT_REAL); }
@@ -163,6 +176,7 @@ public:
    INT64 GetValueAsInt64(void);
    QWORD GetValueAsUInt64(void);
    double GetValueAsReal(void);
+   NXSL_Object *GetValueAsObject(void) { return (m_nDataType == NXSL_DT_OBJECT) ? m_value.pObject : NULL; }
 
    void Concatenate(char *pszString, DWORD dwLen);
    
@@ -235,6 +249,7 @@ public:
    FILE *GetStdOut(void) { return m_pStdOut; }
 
    NXSL_ExtFunction *FindFunction(char *pszName);
+   void RegisterFunctionSet(DWORD dwNumFunctions, NXSL_ExtFunction *pList);
 };
 
 
@@ -335,6 +350,7 @@ protected:
    DWORD m_dwNumFunctions;
    NXSL_Function *m_pFunctionList;
 
+   NXSL_Value *m_pRetValue;
    int m_nErrorCode;
    TCHAR *m_pszErrorText;
 
@@ -354,10 +370,11 @@ public:
    void AddInstruction(NXSL_Instruction *pInstruction);
    void ResolveLastJump(int nOpCode);
 
-   int Run(NXSL_Environment *pEnv);
+   int Run(NXSL_Environment *pEnv = NULL, DWORD argc = 0, NXSL_Value **argv = NULL);
 
    void Dump(FILE *pFile);
    TCHAR *GetErrorText(void) { return m_pszErrorText; }
+   NXSL_Value *GetResult(void) { return m_pRetValue; }
 };
 
 
index 624ef77..70ab956 100644 (file)
@@ -30,6 +30,7 @@
 
 NXSL_Class::NXSL_Class(void)
 {
+   strcpy(m_szName, "generic");
 }
 
 
@@ -62,3 +63,29 @@ BOOL NXSL_Class::SetAttr(NXSL_Object *pObject, char *pszAttr, NXSL_Value *pValue
 {
    return FALSE;
 }
+
+
+//
+// Object constructors
+//
+
+NXSL_Object::NXSL_Object(NXSL_Class *pClass, void *pData)
+{
+   m_pClass = pClass;
+   m_pData = pData;
+}
+
+NXSL_Object::NXSL_Object(NXSL_Object *pObject)
+{
+   m_pClass = pObject->m_pClass;
+   m_pData = pObject->m_pData;
+}
+
+
+//
+// Object destructor
+//
+
+NXSL_Object::~NXSL_Object()
+{
+}
index f107aa0..f462789 100644 (file)
@@ -81,3 +81,15 @@ NXSL_ExtFunction *NXSL_Environment::FindFunction(char *pszName)
          return &m_pFunctionList[i];
    return NULL;
 }
+
+
+//
+// Register function set
+//
+
+void NXSL_Environment::RegisterFunctionSet(DWORD dwNumFunctions, NXSL_ExtFunction *pList)
+{
+   m_pFunctionList = (NXSL_ExtFunction *)realloc(m_pFunctionList, sizeof(NXSL_ExtFunction) * (m_dwNumFunctions + dwNumFunctions));
+   memcpy(&m_pFunctionList[m_dwNumFunctions], pList, sizeof(NXSL_ExtFunction) * dwNumFunctions);
+   m_dwNumFunctions += dwNumFunctions;
+}
index d33c7d0..70c5883 100644 (file)
@@ -84,6 +84,7 @@ union YYSTYPE;
 #define OPCODE_NOT            36
 #define OPCODE_BIT_NOT        37
 #define OPCODE_CAST           38
+#define OPCODE_REFERENCE      39
 
 
 //
index 46e16da..d03140d 100644 (file)
@@ -37,7 +37,8 @@ NXSL_SCRIPT LIBNXSL_EXPORTABLE NXSLCompile(TCHAR *pszSource,
    pResult = compiler.Compile(pszSource);
    if (pResult == NULL)
    {
-      nx_strncpy(pszError, compiler.GetErrorText(), nBufSize);
+      if (pszError != NULL)
+         nx_strncpy(pszError, compiler.GetErrorText(), nBufSize);
    }
    return pResult;
 }
index f27f5f7..75cc7c1 100644 (file)
@@ -71,6 +71,7 @@ escape                \\[bnrt0\"]
 <INITIAL>"||"  return T_OR;
 <INITIAL>"++"  return T_INC;
 <INITIAL>"--"  return T_DEC;
+<INITIAL>"->"  return T_REF;
 <INITIAL>"."   return '.';
 <INITIAL>"{"   return '{';
 <INITIAL>"}"   return '}';
index 12ed65e..d78393d 100644 (file)
@@ -69,7 +69,7 @@ int yylex(YYSTYPE *lvalp, NXSL_Lexer *pLexer);
 %left '+' '-'
 %left '*' '/' '%'
 %right T_INC T_DEC '!' '~' NEGATE
-%left T_POST_INC T_POST_DEC
+%left T_POST_INC T_POST_DEC T_REF
 
 %type <pConstant> Constant
 %type <valStr> FunctionName
@@ -180,6 +180,10 @@ Expression:
 {
        pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_SET, $1));
 }
+|      Expression T_REF T_IDENTIFIER
+{
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_REFERENCE, $3));
+}
 |      '-' Expression          %prec NEGATE
 {
        pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_NEG));
index 56df018..5e2d9eb 100644 (file)
@@ -28,7 +28,7 @@
 // Constants
 //
 
-#define MAX_ERROR_NUMBER         13
+#define MAX_ERROR_NUMBER         15
 #define CONTROL_STACK_LIMIT      32768
 
 
@@ -46,7 +46,7 @@ static char *m_szCommandMnemonic[] =
    "AND", "OR", "LSHIFT", "RSHIFT",
    "NRET", "JZ", "PRINT", "CONCAT",
    "BIND", "INC", "DEC", "NEG", "NOT",
-   "BITNOT", "CAST"
+   "BITNOT", "CAST", "REF"
 };
 
 
@@ -68,7 +68,9 @@ static TCHAR *m_szErrorMessage[MAX_ERROR_NUMBER] =
    _T("Invalid operation with real numbers"),
    _T("Function not found"),
    _T("Invalid number of function's arguments"),
-   _T("Cannot do automatic type cast")
+   _T("Cannot do automatic type cast"),
+   _T("Left argument of -> must be a reference to object"),
+   _T("Unknown object's attribute")
 };
 
 
@@ -137,6 +139,7 @@ NXSL_Program::NXSL_Program(void)
    m_pFunctionList = NULL;
    m_dwSubLevel = 0;    // Level of current subroutine
    m_pEnv = NULL;
+   m_pRetValue = NULL;
 }
 
 
@@ -160,6 +163,7 @@ NXSL_Program::~NXSL_Program(void)
    delete m_pLocals;
 
    delete m_pEnv;
+   delete m_pRetValue;
 
    safe_free(m_pFunctionList);
 
@@ -283,6 +287,7 @@ void NXSL_Program::Dump(FILE *pFile)
          case OPCODE_BIND:
          case OPCODE_INC:
          case OPCODE_DEC:
+         case OPCODE_REFERENCE:
             fprintf(pFile, "%s\n", m_ppInstructionSet[i]->m_operand.m_pszString);
             break;
          case OPCODE_PUSH_CONSTANT:
@@ -327,10 +332,16 @@ void NXSL_Program::Error(int nError)
 // Run program
 //
 
-int NXSL_Program::Run(NXSL_Environment *pEnv)
+int NXSL_Program::Run(NXSL_Environment *pEnv, DWORD argc, NXSL_Value **argv)
 {
    DWORD i;
    NXSL_VariableSystem *pSavedGlobals;
+   NXSL_Value *pValue;
+   char szBuffer[32];
+
+   // Delete previous return value
+   delete m_pRetValue;
+   m_pRetValue = NULL;
 
    // Use provided environment or create default
    if (pEnv != NULL)
@@ -342,8 +353,13 @@ int NXSL_Program::Run(NXSL_Environment *pEnv)
    m_pDataStack = new NXSL_Stack;
    m_pCodeStack = new NXSL_Stack;
 
-   // Create local variable system for main()
+   // Create local variable system for main() and bind arguments
    m_pLocals = new NXSL_VariableSystem;
+   for(i = 0; i < argc; i++)
+   {
+      sprintf(szBuffer, "$%d", i + 1);
+      m_pLocals->Create(szBuffer, argv[i]);
+   }
 
    // Preserve original global variables
    pSavedGlobals = new NXSL_VariableSystem(m_pGlobals);
@@ -357,10 +373,12 @@ int NXSL_Program::Run(NXSL_Environment *pEnv)
       m_dwCurrPos = m_pFunctionList[i].m_dwAddr;
       while(m_dwCurrPos < m_dwCodeSize)
          Execute();
+      if (m_dwCurrPos != INVALID_ADDRESS)
+         m_pRetValue = (NXSL_Value *)m_pDataStack->Pop();
    }
    else
    {
-      Error(7);
+      Error(NXSL_ERR_NO_MAIN);
    }
 
    // Restore global variables
@@ -368,7 +386,16 @@ int NXSL_Program::Run(NXSL_Environment *pEnv)
    m_pGlobals = pSavedGlobals;
 
    // Cleanup
+   while((pValue = (NXSL_Value *)m_pDataStack->Pop()) != NULL)
+      delete pValue;
+   while(m_dwSubLevel > 0)
+   {
+      m_dwSubLevel--;
+      delete (NXSL_VariableSystem *)m_pCodeStack->Pop();
+      m_pCodeStack->Pop();
+   }
    delete_and_null(m_pEnv);
+   delete_and_null(m_pLocals);
    delete_and_null(m_pDataStack);
    delete_and_null(m_pCodeStack);
 
@@ -648,7 +675,45 @@ void NXSL_Program::Execute(void)
          }
          else
          {
-            Error(4);
+            Error(NXSL_ERR_NOT_NUMBER);
+         }
+         break;
+      case OPCODE_REFERENCE:
+         pValue = (NXSL_Value *)m_pDataStack->Pop();
+         if (pValue != NULL)
+         {
+            if (pValue->DataType() == NXSL_DT_OBJECT)
+            {
+               NXSL_Object *pObj;
+               NXSL_Value *pAttr;
+
+               pObj = pValue->GetValueAsObject();
+               if (pObj != NULL)
+               {
+                  pAttr = pObj->Class()->GetAttr(pObj, cp->m_operand.m_pszString);
+                  if (pAttr != NULL)
+                  {
+                     m_pDataStack->Push(pAttr);
+                  }
+                  else
+                  {
+                     Error(NXSL_ERR_NO_SUCH_ATTRIBUTE);
+                  }
+               }
+               else
+               {
+                  Error(NXSL_ERR_INTERNAL);
+               }
+            }
+            else
+            {
+               Error(NXSL_ERR_NOT_OBJECT);
+            }
+            delete pValue;
+         }
+         else
+         {
+            Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
          }
          break;
       default:
@@ -827,7 +892,7 @@ void NXSL_Program::DoBinaryOperation(int nOpCode)
                case OPCODE_CONCAT:
                   if (pVal1->IsNull() || pVal2->IsNull())
                   {
-                     Error(5);
+                     Error(NXSL_ERR_NULL_VALUE);
                   }
                   else
                   {
@@ -853,22 +918,22 @@ void NXSL_Program::DoBinaryOperation(int nOpCode)
                case OPCODE_BIT_XOR:
                case OPCODE_LSHIFT:
                case OPCODE_RSHIFT:
-                  Error(4);
+                  Error(NXSL_ERR_NOT_NUMBER);
                   break;
                default:
-                  Error(6);
+                  Error(NXSL_ERR_INTERNAL);
                   break;
             }
          }
       }
       else
       {
-         Error(5);
+         Error(NXSL_ERR_NULL_VALUE);
       }
    }
    else
    {
-      Error(1);
+      Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
    }
 
    if (pRes != NULL)
index 98aad49..dc89e4f 100644 (file)
@@ -99,7 +99,14 @@ NXSL_Value::NXSL_Value(NXSL_Value *pValue)
    if (pValue != NULL)
    {
       m_nDataType = pValue->m_nDataType;
-      memcpy(&m_value, &pValue->m_value, sizeof(m_value));
+      if (m_nDataType == NXSL_DT_OBJECT)
+      {
+         m_value.pObject = new NXSL_Object(pValue->m_value.pObject);
+      }
+      else
+      {
+         memcpy(&m_value, &pValue->m_value, sizeof(m_value));
+      }
       m_bStringIsValid = pValue->m_bStringIsValid;
       if (m_bStringIsValid)
       {
@@ -118,6 +125,14 @@ NXSL_Value::NXSL_Value(NXSL_Value *pValue)
    }
 }
 
+NXSL_Value::NXSL_Value(NXSL_Object *pObject)
+{
+   m_nDataType = NXSL_DT_OBJECT;
+   m_value.pObject = pObject;
+   m_pszValStr = NULL;
+   m_bStringIsValid = FALSE;
+}
+
 NXSL_Value::NXSL_Value(LONG nValue)
 {
    m_nDataType = NXSL_DT_INT32;
@@ -175,6 +190,8 @@ NXSL_Value::NXSL_Value(char *pszValue)
 NXSL_Value::~NXSL_Value()
 {
    safe_free(m_pszValStr);
+   if (m_nDataType == NXSL_DT_OBJECT)
+      delete m_value.pObject;
 }
 
 
@@ -318,6 +335,8 @@ BOOL NXSL_Value::Convert(int nDataType)
          bRet = FALSE;
          break;
    }
+   if (bRet)
+      InvalidateString();
    return bRet;
 }
 
@@ -328,7 +347,7 @@ BOOL NXSL_Value::Convert(int nDataType)
 
 char *NXSL_Value::GetValueAsCString(void)
 {
-   if (IsNull())
+   if (IsNull() || IsObject())
       return NULL;
 
    if (!m_bStringIsValid)
@@ -343,7 +362,7 @@ char *NXSL_Value::GetValueAsCString(void)
 
 char *NXSL_Value::GetValueAsString(DWORD *pdwLen)
 {
-   if (IsNull())
+   if (IsNull() || IsObject())
       return NULL;
 
    if (!m_bStringIsValid)
@@ -482,9 +501,7 @@ void NXSL_Value::Increment(void)
          default:
             break;
       }
-      safe_free(m_pszValStr);
-      m_pszValStr = NULL;
-      m_bStringIsValid = FALSE;
+      InvalidateString();
    }
 }
 
@@ -517,9 +534,7 @@ void NXSL_Value::Decrement(void)
          default:
             break;
       }
-      safe_free(m_pszValStr);
-      m_pszValStr = NULL;
-      m_bStringIsValid = FALSE;
+      InvalidateString();
    }
 }
 
@@ -554,9 +569,7 @@ void NXSL_Value::Negate(void)
          default:
             break;
       }
-      safe_free(m_pszValStr);
-      m_pszValStr = NULL;
-      m_bStringIsValid = FALSE;
+      InvalidateString();
    }
 }
 
@@ -586,9 +599,7 @@ void NXSL_Value::BitNot(void)
          default:
             break;
       }
-      safe_free(m_pszValStr);
-      m_pszValStr = NULL;
-      m_bStringIsValid = FALSE;
+      InvalidateString();
    }
 }
 
@@ -825,6 +836,7 @@ void NXSL_Value::Add(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::Sub(NXSL_Value *pVal)
@@ -849,6 +861,7 @@ void NXSL_Value::Sub(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::Mul(NXSL_Value *pVal)
@@ -873,6 +886,7 @@ void NXSL_Value::Mul(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::Div(NXSL_Value *pVal)
@@ -897,6 +911,7 @@ void NXSL_Value::Div(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::Rem(NXSL_Value *pVal)
@@ -918,6 +933,7 @@ void NXSL_Value::Rem(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::BitAnd(NXSL_Value *pVal)
@@ -939,6 +955,7 @@ void NXSL_Value::BitAnd(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::BitOr(NXSL_Value *pVal)
@@ -960,6 +977,7 @@ void NXSL_Value::BitOr(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::BitXor(NXSL_Value *pVal)
@@ -981,6 +999,7 @@ void NXSL_Value::BitXor(NXSL_Value *pVal)
       default:
          break;
    }
+   InvalidateString();
 }
 
 
@@ -1007,6 +1026,7 @@ void NXSL_Value::LShift(int nBits)
       default:
          break;
    }
+   InvalidateString();
 }
 
 void NXSL_Value::RShift(int nBits)
@@ -1028,4 +1048,5 @@ void NXSL_Value::RShift(int nBits)
       default:
          break;
    }
+   InvalidateString();
 }
index d4cfc11..15669b0 100644 (file)
@@ -24,6 +24,9 @@
 #include "nxscript.h"
 
 
+static NXSL_TestClass *m_pTestClass;
+
+
 static char *LoadFile(char *pszFileName, DWORD *pdwFileSize)
 {
    int fd, iBufPos, iNumBytes, iBytesRead;
@@ -57,6 +60,13 @@ static char *LoadFile(char *pszFileName, DWORD *pdwFileSize)
 }
 
 
+int F_new(int argc, NXSL_Value **argv, NXSL_Value **ppResult)
+{
+   *ppResult = new NXSL_Value(new NXSL_Object(m_pTestClass, NULL));
+   return 0;
+}
+
+
 //
 // main()
 //
@@ -67,6 +77,15 @@ int main(int argc, char *argv[])
    DWORD dwSize;
    NXSL_Program *pScript;
    NXSL_Environment *pEnv;
+   NXSL_Value **ppArgs;
+   NXSL_ExtFunction func;
+   int i;
+
+   func.m_iNumArgs = 0;
+   func.m_pfHandler = F_new;
+   strcpy(func.m_szName, "new");
+
+   m_pTestClass = new NXSL_TestClass;
 
    printf("NetXMS Scripting Host  Version " NETXMS_VERSION_STRING "\n"
           "Copyright (c) 2005 Victor Kirhenshtein\n\n");
@@ -84,11 +103,26 @@ int main(int argc, char *argv[])
       pScript->Dump(stdout);
       pEnv = new NXSL_Environment;
       pEnv->SetIO(stdin, stdout);
-      if (pScript->Run(pEnv) == -1)
+      pEnv->RegisterFunctionSet(1, &func);
+
+      // Prepare arguments
+      if (argc > 2)
+      {
+         ppArgs = (NXSL_Value **)malloc(sizeof(NXSL_Value *) * (argc - 2));
+         for(i = 2; i < argc; i++)
+            ppArgs[i - 2] = new NXSL_Value(argv[i]);
+      }
+      else
+      {
+         ppArgs = NULL;
+      }
+
+      if (pScript->Run(pEnv, argc - 2, ppArgs) == -1)
       {
          printf("%s\n", pScript->GetErrorText());
       }
       delete pScript;
+      safe_free(ppArgs);
    }
    else
    {
index efec052..4a70605 100644 (file)
@@ -97,6 +97,10 @@ PostBuild_Cmds=copy Debug\nxscript.exe ..\..\bin
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 # Begin Source File
 
+SOURCE=.\class.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\nxscript.cpp
 # End Source File
 # End Group
index fc08772..a05e1d9 100644 (file)
 #include <getopt.h>
 #include <nxsl.h>
 
+
+//
+// Test class
+//
+
+class NXSL_TestClass : public NXSL_Class
+{
+public:
+   NXSL_TestClass();
+
+   virtual NXSL_Value *GetAttr(NXSL_Object *pObject, char *pszAttr);
+   virtual BOOL SetAttr(NXSL_Object *pObject, char *pszAttr, NXSL_Value *pValue);
+};
+
 #endif
index ec41e40..b0a181b 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** NetXMS - Network Management System
-** Copyright (C) 2003, 2004 Victor Kirhenshtein
+** Copyright (C) 2003, 2004, 2005, 2006 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
-** $module: hk.cpp
+** $module: dbwrite.cpp
 **
 **/
 
index f9cdc24..c55dfe1 100644 (file)
@@ -45,7 +45,8 @@ DCItem::DCItem()
    m_szDescription[0] = 0;
    m_szInstance[0] = 0;
    m_tLastPoll = 0;
-   m_pszFormula = _tcsdup(_T(""));
+   m_pszFormula = NULL;
+   m_pScript = NULL;
    m_pNode = NULL;
    m_hMutex = MutexCreate();
    m_dwCacheSize = 0;
@@ -81,7 +82,9 @@ DCItem::DCItem(const DCItem *pSrc)
    _tcscpy(m_szDescription, pSrc->m_szDescription);
    _tcscpy(m_szInstance, pSrc->m_szInstance);
    m_tLastPoll = 0;
-   m_pszFormula = _tcsdup(pSrc->m_pszFormula);
+   m_pszFormula = NULL;
+   m_pScript = NULL;
+   NewFormula(pSrc->m_pszFormula);
    m_pNode = NULL;
    m_hMutex = MutexCreate();
    m_dwCacheSize = 0;
@@ -118,7 +121,7 @@ DCItem::DCItem(const DCItem *pSrc)
 
 DCItem::DCItem(DB_RESULT hResult, int iRow, Template *pNode)
 {
-   char szQuery[256];
+   TCHAR *pszTmp, szQuery[256];
    DB_RESULT hTempResult;
    DWORD i;
 
@@ -131,8 +134,12 @@ DCItem::DCItem(DB_RESULT hResult, int iRow, Template *pNode)
    m_iRetentionTime = DBGetFieldLong(hResult, iRow, 5);
    m_iStatus = (BYTE)DBGetFieldLong(hResult, iRow, 6);
    m_iDeltaCalculation = (BYTE)DBGetFieldLong(hResult, iRow, 7);
-   m_pszFormula = strdup(DBGetField(hResult, iRow, 8));
-   DecodeSQLString(m_pszFormula);
+   m_pszFormula = NULL;
+   m_pScript = NULL;
+   pszTmp = _tcsdup(DBGetField(hResult, iRow, 8));
+   DecodeSQLString(pszTmp);
+   NewFormula(pszTmp);
+   free(pszTmp);
    m_dwTemplateId = DBGetFieldULong(hResult, iRow, 9);
    nx_strncpy(m_szDescription, DBGetField(hResult, iRow, 10), MAX_DB_STRING);
    DecodeSQLString(m_szDescription);
@@ -220,7 +227,8 @@ DCItem::DCItem(DWORD dwId, char *szName, int iSource, int iDataType,
    m_iStatus = ITEM_STATUS_ACTIVE;
    m_iBusy = 0;
    m_tLastPoll = 0;
-   m_pszFormula = strdup("");
+   m_pszFormula = NULL;
+   m_pScript = NULL;
    m_dwNumThresholds = 0;
    m_ppThresholdList = NULL;
    m_pNode = pNode;
@@ -253,6 +261,7 @@ DCItem::~DCItem()
       free(m_ppScheduleList[i]);
    safe_free(m_ppScheduleList);
    safe_free(m_pszFormula);
+   delete m_pScript;
    ClearCache();
    MutexDestroy(m_hMutex);
 }
@@ -332,7 +341,7 @@ BOOL DCItem::SaveToDB(DB_HANDLE hdb)
 
    // Prepare and execute query
    pszEscName = EncodeSQLString(m_szName);
-   pszEscFormula = EncodeSQLString(m_pszFormula);
+   pszEscFormula = EncodeSQLString(CHECK_NULL_EX(m_pszFormula));
    pszEscDescr = EncodeSQLString(m_szDescription);
    pszEscInstance = EncodeSQLString(m_szInstance);
    if (bNewObject)
@@ -490,7 +499,7 @@ void DCItem::CreateMessage(CSCPMessage *pMsg)
    pMsg->SetVariable(VID_DCI_DATA_TYPE, (WORD)m_iDataType);
    pMsg->SetVariable(VID_DCI_STATUS, (WORD)m_iStatus);
    pMsg->SetVariable(VID_DCI_DELTA_CALCULATION, (WORD)m_iDeltaCalculation);
-   pMsg->SetVariable(VID_DCI_FORMULA, m_pszFormula);
+   pMsg->SetVariable(VID_DCI_FORMULA, CHECK_NULL_EX(m_pszFormula));
    pMsg->SetVariable(VID_NUM_THRESHOLDS, m_dwNumThresholds);
    for(i = 0, dwId = VID_DCI_THRESHOLD_BASE; i < m_dwNumThresholds; i++, dwId++)
    {
@@ -548,8 +557,9 @@ void DCItem::UpdateFromMessage(CSCPMessage *pMsg, DWORD *pdwNumMaps,
    m_iRetentionTime = pMsg->GetVariableLong(VID_RETENTION_TIME);
    m_iStatus = (BYTE)pMsg->GetVariableShort(VID_DCI_STATUS);
    m_iDeltaCalculation = (BYTE)pMsg->GetVariableShort(VID_DCI_DELTA_CALCULATION);
-   safe_free(m_pszFormula);
-   m_pszFormula = pMsg->GetVariableStr(VID_DCI_FORMULA);
+   pszStr = pMsg->GetVariableStr(VID_DCI_FORMULA);
+   NewFormula(pszStr);
+   free(pszStr);
 
    // Update schedules
    for(i = 0; i < m_dwNumSchedules; i++)
@@ -775,6 +785,73 @@ void DCItem::Transform(ItemValue &value, time_t nElapsedTime)
       default:    // Default is no transformation
          break;
    }
+
+   if (m_pScript != NULL)
+   {
+      NXSL_Value *pValue;
+
+printf("RUNNING SCRIPT\n");
+      switch(m_iDataType)
+      {
+         case DCI_DT_INT:
+            pValue = new NXSL_Value((LONG)value);
+            break;
+         case DCI_DT_UINT:
+            pValue = new NXSL_Value((DWORD)value);
+            break;
+         case DCI_DT_INT64:
+            pValue = new NXSL_Value((INT64)value);
+            break;
+         case DCI_DT_UINT64:
+            pValue = new NXSL_Value((QWORD)value);
+            break;
+         case DCI_DT_FLOAT:
+            pValue = new NXSL_Value((double)value);
+            break;
+         case DCI_DT_STRING:
+            pValue = new NXSL_Value((char *)((const char *)value));
+            break;
+         default:
+            pValue = new NXSL_Value;
+            break;
+      }
+      if (m_pScript->Run(NULL, 1, &pValue) == 0)
+      {
+printf("SCRIPT OK\n");
+         pValue = m_pScript->GetResult();
+         if (pValue != NULL)
+         {
+printf("Value: %s\n", pValue->GetValueAsCString());
+            switch(m_iDataType)
+            {
+               case DCI_DT_INT:
+                  value = pValue->GetValueAsInt32();
+                  break;
+               case DCI_DT_UINT:
+                  value = pValue->GetValueAsUInt32();
+                  break;
+               case DCI_DT_INT64:
+                  value = pValue->GetValueAsInt64();
+                  break;
+               case DCI_DT_UINT64:
+                  value = pValue->GetValueAsUInt64();
+                  break;
+               case DCI_DT_FLOAT:
+                  value = pValue->GetValueAsReal();
+                  break;
+               case DCI_DT_STRING:
+                  value = pValue->GetValueAsCString();
+                  break;
+               default:
+                  break;
+            }
+         }
+      }
+      else
+      {
+printf("SCRIPT ERROR: %s\n", m_pScript->GetErrorText());
+      }
+   }
 }
 
 
@@ -1110,8 +1187,7 @@ void DCItem::UpdateFromTemplate(DCItem *pItem)
    _tcscpy(m_szName, pItem->m_szName);
    _tcscpy(m_szDescription, pItem->m_szDescription);
    _tcscpy(m_szInstance, pItem->m_szInstance);
-   safe_free(m_pszFormula);
-   m_pszFormula = _tcsdup(pItem->m_pszFormula);
+   NewFormula(pItem->m_pszFormula);
    m_iAdvSchedule = pItem->m_iAdvSchedule;
 
    // Copy schedules
@@ -1148,3 +1224,32 @@ void DCItem::UpdateFromTemplate(DCItem *pItem)
    
    Unlock();
 }
+
+
+//
+// Set new formula
+//
+
+void DCItem::NewFormula(TCHAR *pszFormula)
+{
+   safe_free(m_pszFormula);
+   delete m_pScript;
+   if (pszFormula != NULL)
+   {
+      m_pszFormula = _tcsdup(pszFormula);
+      StrStrip(m_pszFormula);
+      if (m_pszFormula[0] != 0)
+      {
+         m_pScript = (NXSL_Program *)NXSLCompile(m_pszFormula, NULL, 0);
+      }
+      else
+      {
+         m_pScript = NULL;
+      }
+   }
+   else
+   {
+      m_pszFormula = NULL;
+      m_pScript = NULL;
+   }
+}
index c78fba7..586f37f 100644 (file)
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib libnetxms.lib libnxcscp.lib libnxsrv.lib libnxsnmp.lib iphlpapi.lib libeay32.lib minidump.lib version.lib psapi.lib /nologo /dll /machine:I386 /libpath:"..\..\libnetxms\Release" /libpath:"..\..\libnxcscp\Release" /libpath:"..\..\libnxsnmp\Release" /libpath:"..\libnxsrv\Release"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib libnetxms.lib libnxcscp.lib libnxsrv.lib libnxsnmp.lib iphlpapi.lib libeay32.lib minidump.lib version.lib psapi.lib libnxsl.lib /nologo /dll /machine:I386 /libpath:"..\..\libnetxms\Release" /libpath:"..\..\libnxcscp\Release" /libpath:"..\..\libnxsnmp\Release" /libpath:"..\libnxsrv\Release" /libpath:"..\..\libnxsl\Release"
 # Begin Special Build Tool
 SOURCE="$(InputPath)"
 PostBuild_Desc=Copy files
@@ -84,7 +84,7 @@ BSC32=bscmake.exe
 # ADD BSC32 /nologo
 LINK32=link.exe
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib libnetxms.lib libnxcscp.lib libnxsrv.lib libnxsnmp.lib iphlpapi.lib libeay32.lib minidump.lib version.lib psapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libnetxms\Debug" /libpath:"..\..\libnxcscp\Debug" /libpath:"..\..\libnxsnmp\Debug" /libpath:"..\libnxsrv\Debug"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ws2_32.lib libnetxms.lib libnxcscp.lib libnxsrv.lib libnxsnmp.lib iphlpapi.lib libeay32.lib minidump.lib version.lib psapi.lib libnxsl.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\libnetxms\Debug" /libpath:"..\..\libnxcscp\Debug" /libpath:"..\..\libnxsnmp\Debug" /libpath:"..\libnxsrv\Debug" /libpath:"..\..\libnxsl\Debug"
 # Begin Special Build Tool
 SOURCE="$(InputPath)"
 PostBuild_Desc=Copy files
@@ -254,6 +254,10 @@ SOURCE=.\rootobj.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\script.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\session.cpp
 # End Source File
 # Begin Source File
@@ -382,6 +386,10 @@ SOURCE=..\include\nms_pkg.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\include\nms_script.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\..\include\nms_threads.h
 # End Source File
 # Begin Source File
@@ -434,6 +442,14 @@ SOURCE=..\..\..\include\nxqueue.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\..\..\include\nxsl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\include\nxsl_classes.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\..\..\include\nxsnmp.h
 # End Source File
 # Begin Source File
index a49da3a..d2c3f9a 100644 (file)
@@ -78,6 +78,7 @@
 #include <nxqueue.h>
 #include <nxsnmp.h>
 #include <nxmodule.h>
+#include <nxsl.h>
 
 
 //
@@ -104,6 +105,7 @@ typedef __console_ctx * CONSOLE_CTX;
 #include "nms_locks.h"
 #include "nms_pkg.h"
 #include "nms_topo.h"
+#include "nms_script.h"
 
 
 //
index f2bddfe..add92ed 100644 (file)
@@ -163,6 +163,7 @@ private:
    Threshold **m_ppThresholdList;
    Template *m_pNode;             // Pointer to node or template object this item related to
    char *m_pszFormula;        // Transformation formula
+   NXSL_Program *m_pScript;   // Compiled transformation script
    MUTEX m_hMutex;
    DWORD m_dwCacheSize;       // Number of items in cache
    ItemValue **m_ppValueCache;
@@ -180,6 +181,8 @@ private:
    void CheckThresholds(ItemValue &value);
    void ClearCache(void);
 
+   void NewFormula(TCHAR *pszFormula);
+
 public:
    DCItem();
    DCItem(const DCItem *pItem);