NXSL arrays - syntax fully implemented, some work on execution
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Jun 2008 22:21:16 +0000 (22:21 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 4 Jun 2008 22:21:16 +0000 (22:21 +0000)
13 files changed:
.gitattributes
include/nxsl.h
include/nxsl_classes.h
src/client/console/nxmc/rc/nxmc.ico [new file with mode: 0644]
src/libnxsl/Makefile.am
src/libnxsl/array.cpp [new file with mode: 0644]
src/libnxsl/libnxsl.dsp
src/libnxsl/libnxsl.h
src/libnxsl/parser.l
src/libnxsl/parser.y
src/libnxsl/program.cpp
src/libnxsl/value.cpp
src/nxcptest/nxcptest.cpp

index a4c10cf..d5a345c 100644 (file)
@@ -84,6 +84,7 @@ src/client/console/nxmc/rc/icons/normal/unknown.png -text
 src/client/console/nxmc/rc/icons/small/config.png -text
 src/client/console/nxmc/rc/icons/small/taskbar.png -text
 src/client/console/nxmc/rc/login.png -text
+src/client/console/nxmc/rc/nxmc.ico -text
 src/client/console/nxmc/rc/processing.png -text
 src/console/PocketPC/res/Cmdbar.bmp -text
 src/console/PocketPC/res/SeverityCritical.ico -text
@@ -257,6 +258,7 @@ src/libnetxms/wcstoull.c -text
 src/libnetxms/xml.cpp -text
 src/libnxcl/libnxcl.dsw -text
 src/libnxmap/libnxmap.dsw -text
+src/libnxsl/array.cpp -text
 src/libnxsl/libnxsl.dsw -text
 src/libnxsl/parser.l -text
 src/libnxsl/parser.y -text
index 89b9b75..0ceb8c1 100644 (file)
@@ -67,6 +67,7 @@
 #define NXSL_ERR_NOT_INTEGER                                   19
 #define NXSL_ERR_INVALID_OBJECT_OPERATION 20
 #define NXSL_ERR_BAD_CLASS                21
+#define NXSL_ERR_VARIABLE_ALREADY_EXIST   22
 
 
 //
index caa7a3b..b9490df 100644 (file)
 
 #define NXSL_DT_NULL       0
 #define NXSL_DT_OBJECT     1
-#define NXSL_DT_STRING     2
-#define NXSL_DT_REAL       3
-#define NXSL_DT_INT32      4
-#define NXSL_DT_INT64      5
-#define NXSL_DT_UINT32     6
-#define NXSL_DT_UINT64     7
+#define NXSL_DT_ARRAY      2
+#define NXSL_DT_STRING     3
+#define NXSL_DT_REAL       4
+#define NXSL_DT_INT32      5
+#define NXSL_DT_INT64      6
+#define NXSL_DT_UINT32     7
+#define NXSL_DT_UINT64     8
 
 
 //
@@ -119,6 +120,30 @@ public:
 
 
 //
+// Array
+//
+
+class LIBNXSL_EXPORTABLE NXSL_Array
+{
+private:
+       int m_refCount;
+       NXSL_Value **m_data;
+
+public:
+       NXSL_Array();
+       NXSL_Array(NXSL_Array *src);
+       ~NXSL_Array();
+
+       void IncRefCount() { m_refCount++; }
+       void DecRefCount() { m_refCount--; }
+       BOOL IsUnused() { return m_refCount < 1; }
+
+       void Set(int index, NXSL_Value *value);
+       NXSL_Value *Get(int index);
+};
+
+
+//
 // Variable or constant value
 //
 
@@ -137,6 +162,7 @@ protected:
       QWORD uInt64;
       double dReal;
       NXSL_Object *pObject;
+               NXSL_Array *pArray;
    } m_value;
 
    void UpdateNumber(void);
@@ -153,6 +179,7 @@ public:
    NXSL_Value(void);
    NXSL_Value(const NXSL_Value *);
    NXSL_Value(NXSL_Object *pObject);
+   NXSL_Value(NXSL_Array *pArray);
    NXSL_Value(LONG nValue);
    NXSL_Value(INT64 nValue);
    NXSL_Value(DWORD uValue);
@@ -169,6 +196,7 @@ public:
 
    BOOL IsNull(void) { return (m_nDataType == NXSL_DT_NULL); }
    BOOL IsObject(void) { return (m_nDataType == NXSL_DT_OBJECT); }
+   BOOL IsArray(void) { return (m_nDataType == NXSL_DT_ARRAY); }
    BOOL IsString(void) { return (m_nDataType >= NXSL_DT_STRING); }
    BOOL IsNumeric(void) { return (m_nDataType > NXSL_DT_STRING); }
    BOOL IsReal(void) { return (m_nDataType == NXSL_DT_REAL); }
@@ -185,6 +213,7 @@ public:
    QWORD GetValueAsUInt64(void);
    double GetValueAsReal(void);
    NXSL_Object *GetValueAsObject(void) { return (m_nDataType == NXSL_DT_OBJECT) ? m_value.pObject : NULL; }
+   NXSL_Array *GetValueAsArray(void) { return (m_nDataType == NXSL_DT_ARRAY) ? m_value.pArray : NULL; }
 
    void Concatenate(char *pszString, DWORD dwLen);
    
@@ -400,6 +429,7 @@ protected:
    NXSL_Value *MatchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp, BOOL bIgnoreCase);
 
    NXSL_Variable *FindOrCreateVariable(TCHAR *pszName);
+       NXSL_Variable *CreateVariable(TCHAR *pszName);
 
    DWORD GetFunctionAddress(char *pszName);
    void RelocateCode(DWORD dwStartOffset, DWORD dwLen, DWORD dwShift);
diff --git a/src/client/console/nxmc/rc/nxmc.ico b/src/client/console/nxmc/rc/nxmc.ico
new file mode 100644 (file)
index 0000000..3c68a8e
Binary files /dev/null and b/src/client/console/nxmc/rc/nxmc.ico differ
index c5d1be1..1992293 100644 (file)
@@ -1,7 +1,7 @@
 INCLUDES=-I@top_srcdir@/include
 
 lib_LTLIBRARIES = libnxsl.la
-libnxsl_la_SOURCES = lex.yy.cpp parser.tab.cpp class.cpp compiler.cpp \
+libnxsl_la_SOURCES = lex.yy.cpp parser.tab.cpp array.cpp class.cpp compiler.cpp \
                     env.cpp functions.cpp instruction.cpp lexer.cpp \
                     library.cpp main.cpp program.cpp stack.cpp value.cpp \
                     variable.cpp
diff --git a/src/libnxsl/array.cpp b/src/libnxsl/array.cpp
new file mode 100644 (file)
index 0000000..aa669d2
--- /dev/null
@@ -0,0 +1,48 @@
+/* \r
+** NetXMS - Network Management System\r
+** NetXMS Scripting Language Interpreter\r
+** Copyright (C) 2005, 2006, 2007, 2008 Victor Kirhenshtein\r
+**\r
+** This program is free software; you can redistribute it and/or modify\r
+** it under the terms of the GNU General Public License as published by\r
+** the Free Software Foundation; either version 2 of the License, or\r
+** (at your option) any later version.\r
+**\r
+** This program is distributed in the hope that it will be useful,\r
+** but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+** GNU General Public License for more details.\r
+**\r
+** You should have received a copy of the GNU General Public License\r
+** along with this program; if not, write to the Free Software\r
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+**\r
+** File: array.cpp\r
+**\r
+**/\r
+\r
+#include "libnxsl.h"\r
+\r
+\r
+//\r
+// Array constructors\r
+//\r
+\r
+NXSL_Array::NXSL_Array()\r
+{\r
+       m_refCount = 0;\r
+}\r
+\r
+NXSL_Array::NXSL_Array(NXSL_Array *src)\r
+{\r
+       m_refCount = 0;\r
+}\r
+\r
+\r
+//\r
+// Array destructor\r
+//\r
+\r
+NXSL_Array::~NXSL_Array()\r
+{\r
+}\r
index a31e6c3..c726ce6 100644 (file)
@@ -174,6 +174,10 @@ PostBuild_Cmds=copy Debug64\libnxsl.dll ..\..\bin64
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
 # Begin Source File
 
+SOURCE=.\array.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\class.cpp
 # End Source File
 # Begin Source File
index 8fc852d..0ef77ff 100644 (file)
@@ -101,8 +101,10 @@ typedef void *yyscan_t;
 #define OPCODE_ILIKE          44
 #define OPCODE_MATCH          45
 #define OPCODE_IMATCH         46
-#define OPCODE_CASE                            47
-#define OPCODE_ARRAY                           48
+#define OPCODE_CASE           47
+#define OPCODE_ARRAY          48
+#define OPCODE_GET_ELEMENT    49
+#define OPCODE_SET_ELEMENT    50
 
 
 //
index f789e88..dec7cac 100644 (file)
@@ -48,6 +48,7 @@ static void LexerError(const char *pszMsg, yyscan_t scanner);
 <INITIAL>"match"       return T_MATCH;
 <INITIAL>"NULL"                return T_NULL;
 <INITIAL>"print"       return T_PRINT;
+<INITIAL>"println"     return T_PRINTLN;\r
 <INITIAL>"real"                return T_TYPE_REAL;
 <INITIAL>"return"      return T_RETURN;
 <INITIAL>"string"      return T_TYPE_STRING;
@@ -114,6 +115,8 @@ static void LexerError(const char *pszMsg, yyscan_t scanner);
 <INITIAL>"<"   return '<';
 <INITIAL>">"   return '>';
 <INITIAL>"?"   return '?';
+<INITIAL>"["   return '[';\r
+<INITIAL>"]"   return ']';\r
 
 <INITIAL>"/*"  { yyextra->m_nCommentLevel = 1; BEGIN COMMENT; }
 <INITIAL>\"    { yyextra->m_nStrSize = 0; BEGIN STR; }
index af65271..6d33d80 100644 (file)
@@ -48,6 +48,7 @@ int yylex(YYSTYPE *lvalp, yyscan_t scanner);
 %token T_IF
 %token T_NULL
 %token T_PRINT
+%token T_PRINTLN\r
 %token T_RETURN
 %token T_SUB
 %token T_SWITCH
@@ -84,7 +85,7 @@ int yylex(YYSTYPE *lvalp, yyscan_t scanner);
 %left '+' '-'
 %left '*' '/' '%'
 %right T_INC T_DEC '!' '~' NEGATE
-%left T_POST_INC T_POST_DEC T_REF
+%left T_POST_INC T_POST_DEC T_REF '[' ']'
 
 %type <pConstant> Constant
 %type <valStr> AnyIdentifier
@@ -206,6 +207,14 @@ Expression:
 {
        pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_SET, $1));
 }
+|      Expression '[' Expression ']' '=' Expression\r
+{\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_SET_ELEMENT));\r
+}\r
+|      Expression '[' Expression ']'\r
+{\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_GET_ELEMENT));\r
+}\r
 |      Expression T_REF T_IDENTIFIER
 {
        pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_REFERENCE, $3));
@@ -395,7 +404,8 @@ BuiltinType:
 ;
 
 BuiltinStatement:
-       SimpleStatement ';'
+       SimpleStatement ';'\r
+|      PrintlnStatement
 |      IfStatement
 |      DoStatement
 |      WhileStatement
@@ -453,7 +463,21 @@ SimpleStatementKeyword:
 |      T_PRINT
 {
        $$ = new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_PRINT);
-}
+}\r
+;\r
+\r
+PrintlnStatement:
+       T_PRINTLN Expression ';'\r
+{\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_PUSH_CONSTANT, new NXSL_Value(_T("\n"))));\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_CONCAT));\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_PRINT));\r
+}\r
+|      T_PRINTLN ';'\r
+{\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_PUSH_CONSTANT, new NXSL_Value(_T("\n"))));\r
+       pScript->AddInstruction(new NXSL_Instruction(pLexer->GetCurrLine(), OPCODE_PRINT));\r
+}\r
 ;
 
 IfStatement:
index be02c64..20a121e 100644 (file)
@@ -33,7 +33,7 @@
 // Constants
 //
 
-#define MAX_ERROR_NUMBER         21
+#define MAX_ERROR_NUMBER         22
 #define CONTROL_STACK_LIMIT      32768
 
 
@@ -53,7 +53,7 @@ static const char *m_szCommandMnemonic[] =
    "BIND", "INC", "DEC", "NEG", "NOT",
    "BITNOT", "CAST", "REF", "INCP", "DECP",
    "JNZ", "LIKE", "ILIKE", "MATCH",
-   "IMATCH", "CASE", "ARRAY"
+   "IMATCH", "CASE", "ARRAY", "EGET", "ESET"
 };
 
 
@@ -83,7 +83,8 @@ static const TCHAR *m_szErrorMessage[MAX_ERROR_NUMBER] =
        _T("Invalid regular expression"),
        _T("Function or operation argument is not a whole number"),
        _T("Invalid operation on object"),
-       _T("Bad (or incompatible) object class")
+       _T("Bad (or incompatible) object class"),
+       _T("Variable already exist")
 };
 
 
@@ -532,6 +533,28 @@ NXSL_Variable *NXSL_Program::FindOrCreateVariable(TCHAR *pszName)
 
 
 //
+// Create variable if it does not exist, otherwise return NULL
+//
+
+NXSL_Variable *NXSL_Program::CreateVariable(TCHAR *pszName)
+{
+   NXSL_Variable *pVar = NULL;
+
+   if (m_pConstants->Find(pszName) == NULL)
+   {
+      if (m_pGlobals->Find(pszName) == NULL)
+      {
+         if (m_pLocals->Find(pszName) == NULL)
+         {
+            pVar = m_pLocals->Create(pszName);
+         }
+      }
+   }
+   return pVar;
+}
+
+
+//
 // Execute single instruction
 //
 
@@ -560,13 +583,31 @@ void NXSL_Program::Execute(void)
          pValue = (NXSL_Value *)m_pDataStack->Peek();
          if (pValue != NULL)
          {
-            pVar->Set(new NXSL_Value(pValue));
+                               if (pValue->IsArray())
+                               {
+                                       pVar->Set(new NXSL_Value(new NXSL_Array(pValue->GetValueAsArray())));
+                               }
+                               else
+                               {
+                                       pVar->Set(new NXSL_Value(pValue));
+                               }
          }
          else
          {
             Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
          }
          break;
+               case OPCODE_ARRAY:
+         pVar = CreateVariable(cp->m_operand.m_pszString);
+                       if (pVar != NULL)
+                       {
+                               pVar->Set(new NXSL_Value(new NXSL_Array));
+                       }
+                       else
+                       {
+                               Error(NXSL_ERR_VARIABLE_ALREADY_EXIST);
+                       }
+                       break;
       case OPCODE_CAST:
          pValue = (NXSL_Value *)m_pDataStack->Peek();
          if (pValue != NULL)
index f0bea49..db24deb 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** NetXMS Scripting Language Interpreter
-** Copyright (C) 2005, 2006 Victor Kirhenshtein
+** Copyright (C) 2005, 2006, 2007, 2008 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
@@ -103,6 +103,11 @@ NXSL_Value::NXSL_Value(const NXSL_Value *pValue)
       {
          m_value.pObject = new NXSL_Object(pValue->m_value.pObject);
       }
+      else if (m_nDataType == NXSL_DT_ARRAY)
+      {
+         m_value.pArray = pValue->m_value.pArray;
+                       m_value.pArray->IncRefCount();
+      }
       else
       {
          memcpy(&m_value, &pValue->m_value, sizeof(m_value));
@@ -133,6 +138,15 @@ NXSL_Value::NXSL_Value(NXSL_Object *pObject)
    m_bStringIsValid = FALSE;
 }
 
+NXSL_Value::NXSL_Value(NXSL_Array *pArray)
+{
+   m_nDataType = NXSL_DT_ARRAY;
+   m_value.pArray = pArray;
+       pArray->IncRefCount();
+   m_pszValStr = NULL;
+   m_bStringIsValid = FALSE;
+}
+
 NXSL_Value::NXSL_Value(LONG nValue)
 {
    m_nDataType = NXSL_DT_INT32;
@@ -209,7 +223,15 @@ NXSL_Value::~NXSL_Value()
 {
    safe_free(m_pszValStr);
    if (m_nDataType == NXSL_DT_OBJECT)
-      delete m_value.pObject;
+   {
+               delete m_value.pObject;
+       }
+   else if (m_nDataType == NXSL_DT_ARRAY)
+       {
+               m_value.pArray->DecRefCount();
+               if (m_value.pArray->IsUnused())
+                       delete m_value.pArray;
+       }
 }
 
 
@@ -365,7 +387,7 @@ BOOL NXSL_Value::Convert(int nDataType)
 
 char *NXSL_Value::GetValueAsCString(void)
 {
-   if (IsNull() || IsObject())
+   if (IsNull() || IsObject() || IsArray())
       return NULL;
 
    if (!m_bStringIsValid)
@@ -380,7 +402,7 @@ char *NXSL_Value::GetValueAsCString(void)
 
 char *NXSL_Value::GetValueAsString(DWORD *pdwLen)
 {
-   if (IsNull() || IsObject())
+   if (IsNull() || IsObject() || IsArray())
        {
                *pdwLen = 0;
       return NULL;
index f1c72f2..8767780 100644 (file)
@@ -172,7 +172,7 @@ static void Exchange(SOCKET hSocket)
                msg = new CSCPMessage(xml);\r
                rawMsg = msg->CreateMessage();\r
                delete msg;\r
-               if (SendEx(hSocket, rawMsg, ntohl(rawMsg->dwSize), 0) != ntohl(rawMsg->dwSize))\r
+               if ((DWORD)SendEx(hSocket, rawMsg, ntohl(rawMsg->dwSize), 0) != ntohl(rawMsg->dwSize))\r
                {\r
                        printf("Error sending message\n");\r
                        free(rawMsg);\r