NXSL: arrays implemented
[public/netxms.git] / src / libnxsl / program.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Scripting Language Interpreter
4 ** Copyright (C) 2005, 2006, 2007 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: program.cpp
21 **
22 **/
23
24 #include "libnxsl.h"
25 #ifdef _WIN32
26 #include <netxms-regex.h>
27 #else
28 #include <regex.h>
29 #endif
30
31
32 //
33 // Constants
34 //
35
36 #define MAX_ERROR_NUMBER 24
37 #define CONTROL_STACK_LIMIT 32768
38
39
40 //
41 // Command mnemonics
42 //
43
44 static const char *m_szCommandMnemonic[] =
45 {
46 "NOP", "RET", "JMP", "CALL", "CALL",
47 "PUSH", "PUSH", "EXIT", "POP", "SET",
48 "ADD", "SUB", "MUL", "DIV", "REM",
49 "EQ", "NE", "LT", "LE", "GT", "GE",
50 "BITAND", "BITOR", "BITXOR",
51 "AND", "OR", "LSHIFT", "RSHIFT",
52 "NRET", "JZ", "PRINT", "CONCAT",
53 "BIND", "INC", "DEC", "NEG", "NOT",
54 "BITNOT", "CAST", "REF", "INCP", "DECP",
55 "JNZ", "LIKE", "ILIKE", "MATCH",
56 "IMATCH", "CASE", "ARRAY", "EGET", "ESET"
57 };
58
59
60 //
61 // Error texts
62 //
63
64 static const TCHAR *m_szErrorMessage[MAX_ERROR_NUMBER] =
65 {
66 _T("Data stack underflow"),
67 _T("Control stack underflow"),
68 _T("Condition value is not a number"),
69 _T("Bad arithmetic conversion"),
70 _T("Invalid operation with NULL value"),
71 _T("Internal error"),
72 _T("main() function not presented"),
73 _T("Control stack overflow"),
74 _T("Divide by zero"),
75 _T("Invalid operation with real numbers"),
76 _T("Function not found"),
77 _T("Invalid number of function's arguments"),
78 _T("Cannot do automatic type cast"),
79 _T("Left argument of -> must be a reference to object"),
80 _T("Unknown object's attribute"),
81 _T("Requested module not found or cannot be loaded"),
82 _T("Argument is not of string type and cannot be converted to string"),
83 _T("Invalid regular expression"),
84 _T("Function or operation argument is not a whole number"),
85 _T("Invalid operation on object"),
86 _T("Bad (or incompatible) object class"),
87 _T("Variable already exist"),
88 _T("Array index is not an integer"),
89 _T("Attempt to use array element access operation on non-array")
90 };
91
92
93 //
94 // Determine operation data type
95 //
96
97 static int SelectResultType(int nType1, int nType2, int nOp)
98 {
99 int nType;
100
101 if (nOp == OPCODE_DIV)
102 {
103 nType = NXSL_DT_REAL;
104 }
105 else
106 {
107 if ((nType1 == NXSL_DT_REAL) || (nType2 == NXSL_DT_REAL))
108 {
109 if ((nOp == OPCODE_REM) || (nOp == OPCODE_LSHIFT) ||
110 (nOp == OPCODE_RSHIFT) || (nOp == OPCODE_BIT_AND) ||
111 (nOp == OPCODE_BIT_OR) || (nOp == OPCODE_BIT_XOR))
112 {
113 nType = NXSL_DT_NULL; // Error
114 }
115 else
116 {
117 nType = NXSL_DT_REAL;
118 }
119 }
120 else
121 {
122 if (((nType1 >= NXSL_DT_UINT32) && (nType2 < NXSL_DT_UINT32)) ||
123 ((nType1 < NXSL_DT_UINT32) && (nType2 >= NXSL_DT_UINT32)))
124 {
125 // One operand signed, other unsigned, convert both to signed
126 if (nType1 >= NXSL_DT_UINT32)
127 nType1 -= 2;
128 else if (nType2 >= NXSL_DT_UINT32)
129 nType2 -= 2;
130 }
131 nType = max(nType1, nType2);
132 }
133 }
134 return nType;
135 }
136
137
138 //
139 // Constructor
140 //
141
142 NXSL_Program::NXSL_Program(void)
143 {
144 m_ppInstructionSet = NULL;
145 m_dwCodeSize = 0;
146 m_dwCurrPos = INVALID_ADDRESS;
147 m_pDataStack = NULL;
148 m_pCodeStack = NULL;
149 m_nErrorCode = 0;
150 m_pszErrorText = NULL;
151 m_pConstants = new NXSL_VariableSystem;
152 m_pGlobals = new NXSL_VariableSystem;
153 m_pLocals = NULL;
154 m_dwNumFunctions = 0;
155 m_pFunctionList = NULL;
156 m_dwSubLevel = 0; // Level of current subroutine
157 m_pEnv = NULL;
158 m_pRetValue = NULL;
159 m_dwNumModules = 0;
160 m_pModuleList = NULL;
161 m_dwNumPreloads = 0;
162 m_ppszPreloadList = NULL;
163 }
164
165
166 //
167 // Destructor
168 //
169
170 NXSL_Program::~NXSL_Program(void)
171 {
172 DWORD i;
173
174 for(i = 0; i < m_dwCodeSize; i++)
175 delete m_ppInstructionSet[i];
176 safe_free(m_ppInstructionSet);
177
178 delete m_pDataStack;
179 delete m_pCodeStack;
180
181 delete m_pConstants;
182 delete m_pGlobals;
183 delete m_pLocals;
184
185 delete m_pEnv;
186 delete m_pRetValue;
187
188 safe_free(m_pFunctionList);
189 safe_free(m_pModuleList);
190
191 for(i = 0; i < m_dwNumPreloads; i++)
192 safe_free(m_ppszPreloadList[i]);
193 safe_free(m_ppszPreloadList);
194
195 safe_free(m_pszErrorText);
196 }
197
198
199 //
200 // Add new instruction to set
201 //
202
203 void NXSL_Program::AddInstruction(NXSL_Instruction *pInstruction)
204 {
205 m_ppInstructionSet = (NXSL_Instruction **)realloc(m_ppInstructionSet,
206 sizeof(NXSL_Instruction *) * (m_dwCodeSize + 1));
207 m_ppInstructionSet[m_dwCodeSize++] = pInstruction;
208 }
209
210
211 //
212 // Resolve last jump with INVALID_ADDRESS to current address
213 //
214
215 void NXSL_Program::ResolveLastJump(int nOpCode)
216 {
217 DWORD i;
218
219 for(i = m_dwCodeSize; i > 0;)
220 {
221 i--;
222 if ((m_ppInstructionSet[i]->m_nOpCode == nOpCode) &&
223 (m_ppInstructionSet[i]->m_operand.m_dwAddr == INVALID_ADDRESS))
224 {
225 m_ppInstructionSet[i]->m_operand.m_dwAddr = m_dwCodeSize;
226 break;
227 }
228 }
229 }
230
231
232 //
233 // Create jump at given address replacing another instruction (usually NOP)
234 //
235
236 void NXSL_Program::CreateJumpAt(DWORD dwOpAddr, DWORD dwJumpAddr)
237 {
238 int nLine;
239
240 if (dwOpAddr >= m_dwCodeSize)
241 return;
242
243 nLine = m_ppInstructionSet[dwOpAddr]->m_nSourceLine;
244 delete m_ppInstructionSet[dwOpAddr];
245 m_ppInstructionSet[dwOpAddr] = new NXSL_Instruction(nLine, OPCODE_JMP, dwJumpAddr);
246 }
247
248
249 //
250 // Add new function to defined functions list
251 // Will use first free address if dwAddr == INVALID_ADDRESS
252 //
253
254 BOOL NXSL_Program::AddFunction(const char *pszName, DWORD dwAddr, char *pszError)
255 {
256 DWORD i;
257
258 // Check for duplicate function names
259 for(i = 0; i < m_dwNumFunctions; i++)
260 if (!strcmp(m_pFunctionList[i].m_szName, pszName))
261 {
262 sprintf(pszError, "Duplicate function name: \"%s\"", pszName);
263 return FALSE;
264 }
265 m_dwNumFunctions++;
266 m_pFunctionList = (NXSL_Function *)realloc(m_pFunctionList, sizeof(NXSL_Function) * m_dwNumFunctions);
267 nx_strncpy(m_pFunctionList[i].m_szName, pszName, MAX_FUNCTION_NAME);
268 m_pFunctionList[i].m_dwAddr = (dwAddr == INVALID_ADDRESS) ? m_dwCodeSize : dwAddr;
269 return TRUE;
270 }
271
272
273 //
274 // Add preload information
275 //
276
277 void NXSL_Program::AddPreload(char *pszName)
278 {
279 m_ppszPreloadList = (char **)realloc(m_ppszPreloadList, sizeof(char *) * (m_dwNumPreloads + 1));
280 m_ppszPreloadList[m_dwNumPreloads] = pszName;
281 m_dwNumPreloads++;
282 }
283
284
285 //
286 // resolve local functions
287 //
288
289 void NXSL_Program::ResolveFunctions(void)
290 {
291 DWORD i, j;
292
293 for(i = 0; i < m_dwCodeSize; i++)
294 {
295 if (m_ppInstructionSet[i]->m_nOpCode == OPCODE_CALL_EXTERNAL)
296 {
297 for(j = 0; j < m_dwNumFunctions; j++)
298 {
299 if (!strcmp(m_pFunctionList[j].m_szName,
300 m_ppInstructionSet[i]->m_operand.m_pszString))
301 {
302 free(m_ppInstructionSet[i]->m_operand.m_pszString);
303 m_ppInstructionSet[i]->m_operand.m_dwAddr = m_pFunctionList[j].m_dwAddr;
304 m_ppInstructionSet[i]->m_nOpCode = OPCODE_CALL;
305 break;
306 }
307 }
308 }
309 }
310 }
311
312
313 //
314 // Dump program to file (as text)
315 //
316
317 void NXSL_Program::Dump(FILE *pFile)
318 {
319 DWORD i;
320
321 for(i = 0; i < m_dwCodeSize; i++)
322 {
323 fprintf(pFile, "%04X %-6s ", i,
324 m_szCommandMnemonic[m_ppInstructionSet[i]->m_nOpCode]);
325 switch(m_ppInstructionSet[i]->m_nOpCode)
326 {
327 case OPCODE_CALL_EXTERNAL:
328 fprintf(pFile, "%s, %d\n", m_ppInstructionSet[i]->m_operand.m_pszString,
329 m_ppInstructionSet[i]->m_nStackItems);
330 break;
331 case OPCODE_CALL:
332 fprintf(pFile, "%04X, %d\n", m_ppInstructionSet[i]->m_operand.m_dwAddr,
333 m_ppInstructionSet[i]->m_nStackItems);
334 break;
335 case OPCODE_JMP:
336 case OPCODE_JZ:
337 case OPCODE_JNZ:
338 fprintf(pFile, "%04X\n", m_ppInstructionSet[i]->m_operand.m_dwAddr);
339 break;
340 case OPCODE_PUSH_VARIABLE:
341 case OPCODE_SET:
342 case OPCODE_BIND:
343 case OPCODE_ARRAY:
344 case OPCODE_INC:
345 case OPCODE_DEC:
346 case OPCODE_INCP:
347 case OPCODE_DECP:
348 case OPCODE_REFERENCE:
349 fprintf(pFile, "%s\n", m_ppInstructionSet[i]->m_operand.m_pszString);
350 break;
351 case OPCODE_PUSH_CONSTANT:
352 case OPCODE_CASE:
353 if (m_ppInstructionSet[i]->m_operand.m_pConstant->IsNull())
354 fprintf(pFile, "<null>\n");
355 else
356 fprintf(pFile, "\"%s\"\n",
357 m_ppInstructionSet[i]->m_operand.m_pConstant->GetValueAsCString());
358 break;
359 case OPCODE_POP:
360 fprintf(pFile, "%d\n", m_ppInstructionSet[i]->m_nStackItems);
361 break;
362 case OPCODE_CAST:
363 fprintf(pFile, "[%s]\n", g_szTypeNames[m_ppInstructionSet[i]->m_nStackItems]);
364 break;
365 default:
366 fprintf(pFile, "\n");
367 break;
368 }
369 }
370 }
371
372
373 //
374 // Report error
375 //
376
377 void NXSL_Program::Error(int nError)
378 {
379 TCHAR szBuffer[1024];
380
381 safe_free(m_pszErrorText);
382 _sntprintf(szBuffer, 1024, _T("Error %d in line %d: %s"), nError,
383 (m_dwCurrPos == INVALID_ADDRESS) ? 0 : m_ppInstructionSet[m_dwCurrPos]->m_nSourceLine,
384 ((nError > 0) && (nError <= MAX_ERROR_NUMBER)) ? m_szErrorMessage[nError - 1] : _T("Unknown error code"));
385 m_pszErrorText = _tcsdup(szBuffer);
386 m_dwCurrPos = INVALID_ADDRESS;
387 }
388
389
390 //
391 // Run program
392 // Returns 0 on success and -1 on error
393 //
394
395 int NXSL_Program::Run(NXSL_Environment *pEnv, DWORD argc, NXSL_Value **argv,
396 NXSL_VariableSystem *pUserLocals, NXSL_VariableSystem **ppGlobals)
397 {
398 DWORD i, dwOrigCodeSize, dwOrigNumFn;
399 NXSL_VariableSystem *pSavedGlobals;
400 NXSL_Value *pValue;
401 char szBuffer[32];
402
403 // Save original code size and number of functions
404 dwOrigCodeSize = m_dwCodeSize;
405 dwOrigNumFn = m_dwNumFunctions;
406
407 // Delete previous return value
408 delete m_pRetValue;
409 m_pRetValue = NULL;
410
411 // Use provided environment or create default
412 if (pEnv != NULL)
413 m_pEnv = pEnv;
414 else
415 m_pEnv = new NXSL_Environment;
416
417 // Create stacks
418 m_pDataStack = new NXSL_Stack;
419 m_pCodeStack = new NXSL_Stack;
420
421 // Create local variable system for main() and bind arguments
422 m_pLocals = (pUserLocals == NULL) ? new NXSL_VariableSystem : pUserLocals;
423 for(i = 0; i < argc; i++)
424 {
425 sprintf(szBuffer, "$%d", i + 1);
426 m_pLocals->Create(szBuffer, argv[i]);
427 }
428
429 // Preserve original global variables
430 pSavedGlobals = new NXSL_VariableSystem(m_pGlobals);
431
432 // Preload modules
433 for(i = 0; i < m_dwNumPreloads; i++)
434 {
435 if (!pEnv->UseModule(this, m_ppszPreloadList[i]))
436 {
437 Error(NXSL_ERR_MODULE_NOT_FOUND);
438 break;
439 }
440 }
441
442 // Locate main() and run
443 if (i == m_dwNumPreloads)
444 {
445 for(i = 0; i < m_dwNumFunctions; i++)
446 if (!strcmp(m_pFunctionList[i].m_szName, "main"))
447 break;
448 if (i < m_dwNumFunctions)
449 {
450 m_dwCurrPos = m_pFunctionList[i].m_dwAddr;
451 while(m_dwCurrPos < m_dwCodeSize)
452 Execute();
453 if (m_dwCurrPos != INVALID_ADDRESS)
454 m_pRetValue = (NXSL_Value *)m_pDataStack->Pop();
455 }
456 else
457 {
458 Error(NXSL_ERR_NO_MAIN);
459 }
460 }
461
462 // Restore global variables
463 if (ppGlobals == NULL)
464 delete m_pGlobals;
465 else
466 *ppGlobals = m_pGlobals;
467 m_pGlobals = pSavedGlobals;
468
469 // Cleanup
470 while((pValue = (NXSL_Value *)m_pDataStack->Pop()) != NULL)
471 delete pValue;
472 while(m_dwSubLevel > 0)
473 {
474 m_dwSubLevel--;
475 delete (NXSL_VariableSystem *)m_pCodeStack->Pop();
476 m_pCodeStack->Pop();
477 }
478 delete_and_null(m_pEnv);
479 delete_and_null(m_pLocals);
480 delete_and_null(m_pDataStack);
481 delete_and_null(m_pCodeStack);
482 safe_free(m_pModuleList);
483 m_pModuleList = NULL;
484 m_dwNumModules = 0;
485
486 // Restore original code size and number of functions
487 for(i = dwOrigCodeSize; i < m_dwCodeSize; i++)
488 delete m_ppInstructionSet[i];
489 m_dwCodeSize = dwOrigCodeSize;
490 m_dwNumFunctions = dwOrigNumFn;
491
492 return (m_dwCurrPos == INVALID_ADDRESS) ? -1 : 0;
493 }
494
495
496 //
497 // Set global variale
498 //
499
500 void NXSL_Program::SetGlobalVariable(const TCHAR *pszName, NXSL_Value *pValue)
501 {
502 NXSL_Variable *pVar;
503
504 pVar = m_pGlobals->Find(pszName);
505 if (pVar == NULL)
506 pVar = m_pGlobals->Create(pszName, pValue);
507 else
508 pVar->Set(pValue);
509 }
510
511
512 //
513 // Find variable or create if does not exist
514 //
515
516 NXSL_Variable *NXSL_Program::FindOrCreateVariable(TCHAR *pszName)
517 {
518 NXSL_Variable *pVar;
519
520 pVar = m_pConstants->Find(pszName);
521 if (pVar == NULL)
522 {
523 pVar = m_pGlobals->Find(pszName);
524 if (pVar == NULL)
525 {
526 pVar = m_pLocals->Find(pszName);
527 if (pVar == NULL)
528 {
529 pVar = m_pLocals->Create(pszName);
530 }
531 }
532 }
533 return pVar;
534 }
535
536
537 //
538 // Create variable if it does not exist, otherwise return NULL
539 //
540
541 NXSL_Variable *NXSL_Program::CreateVariable(TCHAR *pszName)
542 {
543 NXSL_Variable *pVar = NULL;
544
545 if (m_pConstants->Find(pszName) == NULL)
546 {
547 if (m_pGlobals->Find(pszName) == NULL)
548 {
549 if (m_pLocals->Find(pszName) == NULL)
550 {
551 pVar = m_pLocals->Create(pszName);
552 }
553 }
554 }
555 return pVar;
556 }
557
558
559 //
560 // Execute single instruction
561 //
562
563 void NXSL_Program::Execute(void)
564 {
565 NXSL_Instruction *cp;
566 NXSL_Value *pValue;
567 NXSL_Variable *pVar;
568 NXSL_ExtFunction *pFunc;
569 DWORD dwNext = m_dwCurrPos + 1;
570 char szBuffer[256];
571 int i, nRet;
572
573 cp = m_ppInstructionSet[m_dwCurrPos];
574 switch(cp->m_nOpCode)
575 {
576 case OPCODE_PUSH_CONSTANT:
577 m_pDataStack->Push(new NXSL_Value(cp->m_operand.m_pConstant));
578 break;
579 case OPCODE_PUSH_VARIABLE:
580 pVar = FindOrCreateVariable(cp->m_operand.m_pszString);
581 m_pDataStack->Push(new NXSL_Value(pVar->Value()));
582 break;
583 case OPCODE_SET:
584 pVar = FindOrCreateVariable(cp->m_operand.m_pszString);
585 pValue = (NXSL_Value *)m_pDataStack->Peek();
586 if (pValue != NULL)
587 {
588 if (pValue->IsArray())
589 {
590 pVar->Set(new NXSL_Value(new NXSL_Array(pValue->GetValueAsArray())));
591 }
592 else
593 {
594 pVar->Set(new NXSL_Value(pValue));
595 }
596 }
597 else
598 {
599 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
600 }
601 break;
602 case OPCODE_ARRAY:
603 pVar = CreateVariable(cp->m_operand.m_pszString);
604 if (pVar != NULL)
605 {
606 pVar->Set(new NXSL_Value(new NXSL_Array));
607 }
608 else
609 {
610 Error(NXSL_ERR_VARIABLE_ALREADY_EXIST);
611 }
612 break;
613 case OPCODE_SET_ELEMENT: // Set array element; stack should contain: array index value (top)
614 pValue = (NXSL_Value *)m_pDataStack->Pop();
615 if (pValue != NULL)
616 {
617 NXSL_Value *array, *index;
618
619 index = (NXSL_Value *)m_pDataStack->Pop();
620 array = (NXSL_Value *)m_pDataStack->Pop();
621 if ((index != NULL) && (array != NULL))
622 {
623 if (!index->IsInteger())
624 {
625 Error(NXSL_ERR_INDEX_NOT_INTEGER);
626 delete pValue;
627 }
628 else if (!array->IsArray())
629 {
630 Error(NXSL_ERR_NOT_ARRAY);
631 delete pValue;
632 }
633 else
634 {
635 array->GetValueAsArray()->Set(index->GetValueAsInt32(), pValue);
636 }
637 }
638 else
639 {
640 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
641 delete pValue;
642 }
643 delete index;
644 delete array;
645 }
646 else
647 {
648 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
649 }
650 break;
651 case OPCODE_GET_ELEMENT: // Get array element; stack should contain: array index (top)
652 pValue = (NXSL_Value *)m_pDataStack->Pop();
653 if (pValue != NULL)
654 {
655 NXSL_Value *array;
656
657 array = (NXSL_Value *)m_pDataStack->Pop();
658 if (array != NULL)
659 {
660 if (array->IsArray())
661 {
662 if (pValue->IsInteger())
663 {
664 NXSL_Value *element;
665
666 element = array->GetValueAsArray()->Get(pValue->GetValueAsInt32());
667 m_pDataStack->Push((element != NULL) ? new NXSL_Value(element) : new NXSL_Value);
668 }
669 else
670 {
671 Error(NXSL_ERR_INDEX_NOT_INTEGER);
672 }
673 }
674 else
675 {
676 Error(NXSL_ERR_NOT_ARRAY);
677 }
678 delete array;
679 }
680 else
681 {
682 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
683 }
684 delete pValue;
685 }
686 else
687 {
688 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
689 }
690 break;
691 case OPCODE_CAST:
692 pValue = (NXSL_Value *)m_pDataStack->Peek();
693 if (pValue != NULL)
694 {
695 if (!pValue->Convert(cp->m_nStackItems))
696 {
697 Error(NXSL_ERR_TYPE_CAST);
698 }
699 }
700 else
701 {
702 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
703 }
704 break;
705 case OPCODE_POP:
706 for(i = 0; i < cp->m_nStackItems; i++)
707 delete (NXSL_Value *)m_pDataStack->Pop();
708 break;
709 case OPCODE_JMP:
710 dwNext = cp->m_operand.m_dwAddr;
711 break;
712 case OPCODE_JZ:
713 case OPCODE_JNZ:
714 pValue = (NXSL_Value *)m_pDataStack->Pop();
715 if (pValue != NULL)
716 {
717 if (pValue->IsNumeric())
718 {
719 if (cp->m_nOpCode == OPCODE_JZ ? pValue->IsZero() : pValue->IsNonZero())
720 dwNext = cp->m_operand.m_dwAddr;
721 }
722 else
723 {
724 Error(3);
725 }
726 delete pValue;
727 }
728 else
729 {
730 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
731 }
732 break;
733 case OPCODE_CALL:
734 dwNext = cp->m_operand.m_dwAddr;
735 CallFunction(cp->m_nStackItems);
736 break;
737 case OPCODE_CALL_EXTERNAL:
738 pFunc = m_pEnv->FindFunction(cp->m_operand.m_pszString);
739 if (pFunc != NULL)
740 {
741 if ((cp->m_nStackItems == pFunc->m_iNumArgs) ||
742 (pFunc->m_iNumArgs == -1))
743 {
744 if (m_pDataStack->Size() >= cp->m_nStackItems)
745 {
746 nRet = pFunc->m_pfHandler(cp->m_nStackItems,
747 (NXSL_Value **)m_pDataStack->PeekList(cp->m_nStackItems),
748 &pValue);
749 if (nRet == 0)
750 {
751 for(i = 0; i < cp->m_nStackItems; i++)
752 m_pDataStack->Pop();
753 m_pDataStack->Push(pValue);
754 }
755 else
756 {
757 // Execution error inside function
758 Error(nRet);
759 }
760 }
761 else
762 {
763 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
764 }
765 }
766 else
767 {
768 Error(NXSL_ERR_INVALID_ARGUMENT_COUNT);
769 }
770 }
771 else
772 {
773 DWORD dwAddr;
774
775 dwAddr = GetFunctionAddress(cp->m_operand.m_pszString);
776 if (dwAddr != INVALID_ADDRESS)
777 {
778 dwNext = dwAddr;
779 CallFunction(cp->m_nStackItems);
780 }
781 else
782 {
783 Error(NXSL_ERR_NO_FUNCTION);
784 }
785 }
786 break;
787 case OPCODE_RET_NULL:
788 m_pDataStack->Push(new NXSL_Value);
789 case OPCODE_RETURN:
790 if (m_dwSubLevel > 0)
791 {
792 m_dwSubLevel--;
793 delete m_pLocals;
794 m_pLocals = (NXSL_VariableSystem *)m_pCodeStack->Pop();
795 dwNext = CAST_FROM_POINTER(m_pCodeStack->Pop(), DWORD);
796 }
797 else
798 {
799 // Return from main(), terminate program
800 dwNext = m_dwCodeSize;
801 }
802 break;
803 case OPCODE_BIND:
804 sprintf(szBuffer, "$%d", m_nBindPos++);
805 pVar = m_pLocals->Find(szBuffer);
806 pValue = (pVar != NULL) ? new NXSL_Value(pVar->Value()) : new NXSL_Value;
807 pVar = m_pLocals->Find(cp->m_operand.m_pszString);
808 if (pVar == NULL)
809 m_pLocals->Create(cp->m_operand.m_pszString, pValue);
810 else
811 pVar->Set(pValue);
812 break;
813 case OPCODE_PRINT:
814 pValue = (NXSL_Value *)m_pDataStack->Pop();
815 if (pValue != NULL)
816 {
817 char *pszText;
818 DWORD dwLen;
819
820 if (m_pEnv->GetStdOut() != NULL)
821 {
822 pszText = pValue->GetValueAsString(&dwLen);
823 if (pszText != NULL)
824 fwrite(pszText, dwLen, 1, m_pEnv->GetStdOut());
825 else
826 fputs("(null)", m_pEnv->GetStdOut());
827 }
828 delete pValue;
829 }
830 else
831 {
832 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
833 }
834 break;
835 case OPCODE_EXIT:
836 pValue = (NXSL_Value *)m_pDataStack->Pop();
837 if (pValue != NULL)
838 {
839 dwNext = m_dwCodeSize;
840 delete pValue;
841 }
842 else
843 {
844 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
845 }
846 break;
847 case OPCODE_ADD:
848 case OPCODE_SUB:
849 case OPCODE_MUL:
850 case OPCODE_DIV:
851 case OPCODE_REM:
852 case OPCODE_CONCAT:
853 case OPCODE_LIKE:
854 case OPCODE_ILIKE:
855 case OPCODE_MATCH:
856 case OPCODE_IMATCH:
857 case OPCODE_EQ:
858 case OPCODE_NE:
859 case OPCODE_LT:
860 case OPCODE_LE:
861 case OPCODE_GT:
862 case OPCODE_GE:
863 case OPCODE_AND:
864 case OPCODE_OR:
865 case OPCODE_BIT_AND:
866 case OPCODE_BIT_OR:
867 case OPCODE_BIT_XOR:
868 case OPCODE_LSHIFT:
869 case OPCODE_RSHIFT:
870 case OPCODE_CASE:
871 DoBinaryOperation(cp->m_nOpCode);
872 break;
873 case OPCODE_NEG:
874 case OPCODE_NOT:
875 case OPCODE_BIT_NOT:
876 DoUnaryOperation(cp->m_nOpCode);
877 break;
878 case OPCODE_INC: // Post increment/decrement
879 case OPCODE_DEC:
880 pVar = FindOrCreateVariable(cp->m_operand.m_pszString);
881 pValue = pVar->Value();
882 if (pValue->IsNumeric())
883 {
884 m_pDataStack->Push(new NXSL_Value(pValue));
885 if (cp->m_nOpCode == OPCODE_INC)
886 pValue->Increment();
887 else
888 pValue->Decrement();
889 }
890 else
891 {
892 Error(NXSL_ERR_NOT_NUMBER);
893 }
894 break;
895 case OPCODE_INCP: // Pre increment/decrement
896 case OPCODE_DECP:
897 pVar = FindOrCreateVariable(cp->m_operand.m_pszString);
898 pValue = pVar->Value();
899 if (pValue->IsNumeric())
900 {
901 if (cp->m_nOpCode == OPCODE_INC)
902 pValue->Increment();
903 else
904 pValue->Decrement();
905 m_pDataStack->Push(new NXSL_Value(pValue));
906 }
907 else
908 {
909 Error(NXSL_ERR_NOT_NUMBER);
910 }
911 break;
912 case OPCODE_REFERENCE:
913 pValue = (NXSL_Value *)m_pDataStack->Pop();
914 if (pValue != NULL)
915 {
916 if (pValue->DataType() == NXSL_DT_OBJECT)
917 {
918 NXSL_Object *pObj;
919 NXSL_Value *pAttr;
920
921 pObj = pValue->GetValueAsObject();
922 if (pObj != NULL)
923 {
924 pAttr = pObj->Class()->GetAttr(pObj, cp->m_operand.m_pszString);
925 if (pAttr != NULL)
926 {
927 m_pDataStack->Push(pAttr);
928 }
929 else
930 {
931 Error(NXSL_ERR_NO_SUCH_ATTRIBUTE);
932 }
933 }
934 else
935 {
936 Error(NXSL_ERR_INTERNAL);
937 }
938 }
939 else
940 {
941 Error(NXSL_ERR_NOT_OBJECT);
942 }
943 delete pValue;
944 }
945 else
946 {
947 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
948 }
949 break;
950 default:
951 break;
952 }
953
954 if (m_dwCurrPos != INVALID_ADDRESS)
955 m_dwCurrPos = dwNext;
956 }
957
958
959 //
960 // Perform binary operation on two operands from stack and push result to stack
961 //
962
963 void NXSL_Program::DoBinaryOperation(int nOpCode)
964 {
965 NXSL_Value *pVal1, *pVal2, *pRes = NULL;
966 char *pszText1, *pszText2;
967 DWORD dwLen1, dwLen2;
968 int nType;
969 LONG nResult;
970
971 if (nOpCode == OPCODE_CASE)
972 {
973 pVal1 = m_ppInstructionSet[m_dwCurrPos]->m_operand.m_pConstant;
974 pVal2 = (NXSL_Value *)m_pDataStack->Peek();
975 }
976 else
977 {
978 pVal2 = (NXSL_Value *)m_pDataStack->Pop();
979 pVal1 = (NXSL_Value *)m_pDataStack->Pop();
980 }
981
982 if ((pVal1 != NULL) && (pVal2 != NULL))
983 {
984 if ((!pVal1->IsNull() && !pVal2->IsNull()) ||
985 (nOpCode == OPCODE_EQ) || (nOpCode == OPCODE_NE) || (nOpCode == OPCODE_CASE))
986 {
987 if (pVal1->IsNumeric() && pVal2->IsNumeric() &&
988 (nOpCode != OPCODE_CONCAT) && (nOpCode != OPCODE_LIKE))
989 {
990 nType = SelectResultType(pVal1->DataType(), pVal2->DataType(), nOpCode);
991 if (nType != NXSL_DT_NULL)
992 {
993 if ((pVal1->Convert(nType)) && (pVal2->Convert(nType)))
994 {
995 switch(nOpCode)
996 {
997 case OPCODE_ADD:
998 pRes = pVal1;
999 pRes->Add(pVal2);
1000 delete pVal2;
1001 break;
1002 case OPCODE_SUB:
1003 pRes = pVal1;
1004 pRes->Sub(pVal2);
1005 delete pVal2;
1006 break;
1007 case OPCODE_MUL:
1008 pRes = pVal1;
1009 pRes->Mul(pVal2);
1010 delete pVal2;
1011 break;
1012 case OPCODE_DIV:
1013 pRes = pVal1;
1014 pRes->Div(pVal2);
1015 delete pVal2;
1016 break;
1017 case OPCODE_REM:
1018 pRes = pVal1;
1019 pRes->Rem(pVal2);
1020 delete pVal2;
1021 break;
1022 case OPCODE_EQ:
1023 case OPCODE_NE:
1024 nResult = pVal1->EQ(pVal2);
1025 delete pVal1;
1026 delete pVal2;
1027 pRes = new NXSL_Value((nOpCode == OPCODE_EQ) ? nResult : !nResult);
1028 break;
1029 case OPCODE_LT:
1030 nResult = pVal1->LT(pVal2);
1031 delete pVal1;
1032 delete pVal2;
1033 pRes = new NXSL_Value(nResult);
1034 break;
1035 case OPCODE_LE:
1036 nResult = pVal1->LE(pVal2);
1037 delete pVal1;
1038 delete pVal2;
1039 pRes = new NXSL_Value(nResult);
1040 break;
1041 case OPCODE_GT:
1042 nResult = pVal1->GT(pVal2);
1043 delete pVal1;
1044 delete pVal2;
1045 pRes = new NXSL_Value(nResult);
1046 break;
1047 case OPCODE_GE:
1048 nResult = pVal1->GE(pVal2);
1049 delete pVal1;
1050 delete pVal2;
1051 pRes = new NXSL_Value(nResult);
1052 break;
1053 case OPCODE_LSHIFT:
1054 pRes = pVal1;
1055 pRes->LShift(pVal2->GetValueAsInt32());
1056 delete pVal2;
1057 break;
1058 case OPCODE_RSHIFT:
1059 pRes = pVal1;
1060 pRes->RShift(pVal2->GetValueAsInt32());
1061 delete pVal2;
1062 break;
1063 case OPCODE_BIT_AND:
1064 pRes = pVal1;
1065 pRes->BitAnd(pVal2);
1066 delete pVal2;
1067 break;
1068 case OPCODE_BIT_OR:
1069 pRes = pVal1;
1070 pRes->BitOr(pVal2);
1071 delete pVal2;
1072 break;
1073 case OPCODE_BIT_XOR:
1074 pRes = pVal1;
1075 pRes->BitXor(pVal2);
1076 delete pVal2;
1077 break;
1078 case OPCODE_AND:
1079 nResult = (pVal1->IsNonZero() && pVal2->IsNonZero());
1080 delete pVal1;
1081 delete pVal2;
1082 pRes = new NXSL_Value(nResult);
1083 break;
1084 case OPCODE_OR:
1085 nResult = (pVal1->IsNonZero() || pVal2->IsNonZero());
1086 delete pVal1;
1087 delete pVal2;
1088 pRes = new NXSL_Value(nResult);
1089 break;
1090 case OPCODE_CASE:
1091 pRes = new NXSL_Value((LONG)pVal1->EQ(pVal2));
1092 break;
1093 default:
1094 Error(NXSL_ERR_INTERNAL);
1095 break;
1096 }
1097 }
1098 else
1099 {
1100 Error(NXSL_ERR_TYPE_CAST);
1101 }
1102 }
1103 else
1104 {
1105 Error(NXSL_ERR_REAL_VALUE);
1106 }
1107 }
1108 else
1109 {
1110 switch(nOpCode)
1111 {
1112 case OPCODE_EQ:
1113 case OPCODE_NE:
1114 case OPCODE_CASE:
1115 if (pVal1->IsNull() && pVal2->IsNull())
1116 {
1117 nResult = 1;
1118 }
1119 else if (pVal1->IsNull() || pVal2->IsNull())
1120 {
1121 nResult = 0;
1122 }
1123 else
1124 {
1125 pszText1 = pVal1->GetValueAsString(&dwLen1);
1126 pszText2 = pVal2->GetValueAsString(&dwLen2);
1127 if (dwLen1 == dwLen2)
1128 nResult = !memcmp(pszText1, pszText2, dwLen1);
1129 else
1130 nResult = 0;
1131 }
1132 if (nOpCode != OPCODE_CASE)
1133 {
1134 delete pVal1;
1135 delete pVal2;
1136 }
1137 pRes = new NXSL_Value((nOpCode == OPCODE_NE) ? !nResult : nResult);
1138 break;
1139 case OPCODE_CONCAT:
1140 if (pVal1->IsNull() || pVal2->IsNull())
1141 {
1142 Error(NXSL_ERR_NULL_VALUE);
1143 }
1144 else if (pVal1->IsObject() || pVal2->IsObject())
1145 {
1146 Error(NXSL_ERR_INVALID_OBJECT_OPERATION);
1147 }
1148 else
1149 {
1150 pRes = pVal1;
1151 pszText2 = pVal2->GetValueAsString(&dwLen2);
1152 pRes->Concatenate(pszText2, dwLen2);
1153 delete pVal2;
1154 }
1155 break;
1156 case OPCODE_LIKE:
1157 case OPCODE_ILIKE:
1158 if (pVal1->IsString() && pVal2->IsString())
1159 {
1160 pRes = new NXSL_Value((LONG)MatchString(pVal2->GetValueAsCString(),
1161 pVal1->GetValueAsCString(),
1162 nOpCode == OPCODE_LIKE));
1163 delete pVal1;
1164 delete pVal2;
1165 }
1166 else
1167 {
1168 Error(NXSL_ERR_NOT_STRING);
1169 }
1170 break;
1171 case OPCODE_MATCH:
1172 case OPCODE_IMATCH:
1173 if (pVal1->IsString() && pVal2->IsString())
1174 {
1175 pRes = MatchRegexp(pVal1, pVal2, nOpCode == OPCODE_IMATCH);
1176 delete pVal1;
1177 delete pVal2;
1178 }
1179 else
1180 {
1181 Error(NXSL_ERR_NOT_STRING);
1182 }
1183 break;
1184 case OPCODE_ADD:
1185 case OPCODE_SUB:
1186 case OPCODE_MUL:
1187 case OPCODE_DIV:
1188 case OPCODE_REM:
1189 case OPCODE_LT:
1190 case OPCODE_LE:
1191 case OPCODE_GT:
1192 case OPCODE_GE:
1193 case OPCODE_AND:
1194 case OPCODE_OR:
1195 case OPCODE_BIT_AND:
1196 case OPCODE_BIT_OR:
1197 case OPCODE_BIT_XOR:
1198 case OPCODE_LSHIFT:
1199 case OPCODE_RSHIFT:
1200 Error(NXSL_ERR_NOT_NUMBER);
1201 break;
1202 default:
1203 Error(NXSL_ERR_INTERNAL);
1204 break;
1205 }
1206 }
1207 }
1208 else
1209 {
1210 Error(NXSL_ERR_NULL_VALUE);
1211 }
1212 }
1213 else
1214 {
1215 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
1216 }
1217
1218 if (pRes != NULL)
1219 m_pDataStack->Push(pRes);
1220 }
1221
1222
1223 //
1224 // Perform unary operation on operand from the stack and push result back to stack
1225 //
1226
1227 void NXSL_Program::DoUnaryOperation(int nOpCode)
1228 {
1229 NXSL_Value *pVal;
1230
1231 pVal = (NXSL_Value *)m_pDataStack->Peek();
1232 if (pVal != NULL)
1233 {
1234 if (pVal->IsNumeric())
1235 {
1236 switch(nOpCode)
1237 {
1238 case OPCODE_NEG:
1239 pVal->Negate();
1240 break;
1241 case OPCODE_NOT:
1242 if (!pVal->IsReal())
1243 {
1244 pVal->Set((LONG)pVal->IsZero());
1245 }
1246 else
1247 {
1248 Error(NXSL_ERR_REAL_VALUE);
1249 }
1250 break;
1251 case OPCODE_BIT_NOT:
1252 if (!pVal->IsReal())
1253 {
1254 pVal->BitNot();
1255 }
1256 else
1257 {
1258 Error(NXSL_ERR_REAL_VALUE);
1259 }
1260 break;
1261 default:
1262 Error(NXSL_ERR_INTERNAL);
1263 break;
1264 }
1265 }
1266 else
1267 {
1268 Error(NXSL_ERR_NOT_NUMBER);
1269 }
1270 }
1271 else
1272 {
1273 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
1274 }
1275 }
1276
1277
1278 //
1279 // Relocate code block
1280 //
1281
1282 void NXSL_Program::RelocateCode(DWORD dwStart, DWORD dwLen, DWORD dwShift)
1283 {
1284 DWORD i, dwLast;
1285
1286 dwLast = min(dwStart + dwLen, m_dwCodeSize);
1287 for(i = dwStart; i < dwLast; i++)
1288 if ((m_ppInstructionSet[i]->m_nOpCode == OPCODE_JMP) ||
1289 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JZ) ||
1290 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JNZ) ||
1291 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_CALL))
1292 {
1293 m_ppInstructionSet[i]->m_operand.m_dwAddr += dwShift;
1294 }
1295 }
1296
1297
1298 //
1299 // Use external module
1300 //
1301
1302 void NXSL_Program::UseModule(NXSL_Program *pModule, const char *pszName)
1303 {
1304 DWORD i, j, dwStart;
1305
1306 // Check if module already loaded
1307 for(i = 0; i < m_dwNumModules; i++)
1308 if (!stricmp(pszName, m_pModuleList[i].m_szName))
1309 return; // Already loaded
1310
1311 // Add code from module
1312 dwStart = m_dwCodeSize;
1313 m_dwCodeSize += pModule->m_dwCodeSize;
1314 m_ppInstructionSet = (NXSL_Instruction **)realloc(m_ppInstructionSet,
1315 sizeof(NXSL_Instruction *) * m_dwCodeSize);
1316 for(i = dwStart, j = 0; i < m_dwCodeSize; i++, j++)
1317 m_ppInstructionSet[i] = new NXSL_Instruction(pModule->m_ppInstructionSet[j]);
1318 RelocateCode(dwStart, pModule->m_dwCodeSize, dwStart);
1319
1320 // Add function names from module
1321 m_pFunctionList = (NXSL_Function *)realloc(m_pFunctionList,
1322 sizeof(NXSL_Function) * (m_dwNumFunctions + pModule->m_dwNumFunctions));
1323 memcpy(&m_pFunctionList[m_dwNumFunctions], pModule->m_pFunctionList,
1324 sizeof(NXSL_Function) * pModule->m_dwNumFunctions);
1325 for(i = m_dwNumFunctions, j = 0; j < pModule->m_dwNumFunctions; i++, j++)
1326 m_pFunctionList[i].m_dwAddr += dwStart;
1327
1328 // Register module as loaded
1329 m_pModuleList = (NXSL_Module *)malloc(sizeof(NXSL_Module) * (m_dwNumModules + 1));
1330 strncpy(m_pModuleList[m_dwNumModules].m_szName, pszName, MAX_PATH);
1331 m_pModuleList[m_dwNumModules].m_dwCodeStart = dwStart;
1332 m_pModuleList[m_dwNumModules].m_dwCodeSize = pModule->m_dwCodeSize;
1333 m_pModuleList[m_dwNumModules].m_dwFunctionStart = m_dwNumFunctions;
1334 m_pModuleList[m_dwNumModules].m_dwNumFunctions = pModule->m_dwNumFunctions;
1335 m_dwNumModules++;
1336
1337 m_dwNumFunctions += pModule->m_dwNumFunctions;
1338 }
1339
1340
1341 //
1342 // Call function at given address
1343 //
1344
1345 void NXSL_Program::CallFunction(int nArgCount)
1346 {
1347 int i;
1348 NXSL_Value *pValue;
1349 char szBuffer[32];
1350
1351 if (m_dwSubLevel < CONTROL_STACK_LIMIT)
1352 {
1353 m_dwSubLevel++;
1354 m_pCodeStack->Push((void *)(m_dwCurrPos + 1));
1355 m_pCodeStack->Push(m_pLocals);
1356 m_pLocals = new NXSL_VariableSystem;
1357 m_nBindPos = 1;
1358
1359 // Bind arguments
1360 for(i = nArgCount; i > 0; i--)
1361 {
1362 pValue = (NXSL_Value *)m_pDataStack->Pop();
1363 if (pValue != NULL)
1364 {
1365 sprintf(szBuffer, "$%d", i);
1366 m_pLocals->Create(szBuffer, pValue);
1367 }
1368 else
1369 {
1370 Error(NXSL_ERR_DATA_STACK_UNDERFLOW);
1371 break;
1372 }
1373 }
1374 }
1375 else
1376 {
1377 Error(NXSL_ERR_CONTROL_STACK_OVERFLOW);
1378 }
1379 }
1380
1381
1382 //
1383 // Find function address by name
1384 //
1385
1386 DWORD NXSL_Program::GetFunctionAddress(char *pszName)
1387 {
1388 DWORD i;
1389
1390 for(i = 0; i < m_dwNumFunctions; i++)
1391 if (!strcmp(m_pFunctionList[i].m_szName, pszName))
1392 return m_pFunctionList[i].m_dwAddr;
1393 return INVALID_ADDRESS;
1394 }
1395
1396
1397 //
1398 // Match regular expression
1399 //
1400
1401 NXSL_Value *NXSL_Program::MatchRegexp(NXSL_Value *pValue, NXSL_Value *pRegexp,
1402 BOOL bIgnoreCase)
1403 {
1404 regex_t preg;
1405 regmatch_t fields[256];
1406 NXSL_Value *pResult;
1407 NXSL_Variable *pVar;
1408 TCHAR szName[16];
1409 int i;
1410
1411 if (regcomp(&preg, pRegexp->GetValueAsCString(),
1412 bIgnoreCase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED) == 0)
1413 {
1414 if (regexec(&preg, pValue->GetValueAsCString(), 256, fields, 0) == 0)
1415 {
1416 pResult = new NXSL_Value((LONG)1);
1417 for(i = 1; (i < 256) && (fields[i].rm_so != -1); i++)
1418 {
1419 _stprintf(szName, _T("$%d"), i);
1420 pVar = m_pLocals->Find(szName);
1421 if (pVar == NULL)
1422 m_pLocals->Create(szName, new NXSL_Value(pValue->GetValueAsCString() + fields[i].rm_so, fields[i].rm_eo - fields[i].rm_so));
1423 else
1424 pVar->Set(new NXSL_Value(pValue->GetValueAsCString() + fields[i].rm_so, fields[i].rm_eo - fields[i].rm_so));
1425 }
1426 }
1427 else
1428 {
1429 pResult = new NXSL_Value((LONG)0);
1430 }
1431 regfree(&preg);
1432 }
1433 else
1434 {
1435 Error(NXSL_ERR_REGEXP_ERROR);
1436 pResult = NULL;
1437 }
1438 return pResult;
1439 }
1440
1441
1442 //
1443 // Get final jump destination from a jump chain
1444 //
1445
1446 DWORD NXSL_Program::FinalJumpDestination(DWORD dwAddr)
1447 {
1448 return (m_ppInstructionSet[dwAddr]->m_nOpCode == OPCODE_JMP) ? FinalJumpDestination(m_ppInstructionSet[dwAddr]->m_operand.m_dwAddr) : dwAddr;
1449 }
1450
1451
1452 //
1453 // Optimize compiled program
1454 //
1455
1456 void NXSL_Program::Optimize(void)
1457 {
1458 DWORD i, j;
1459
1460 // Convert jump chains to single jump
1461 for(i = 0; i < m_dwCodeSize; i++)
1462 {
1463 if ((m_ppInstructionSet[i]->m_nOpCode == OPCODE_JMP) ||
1464 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JZ) ||
1465 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JNZ))
1466 {
1467 m_ppInstructionSet[i]->m_operand.m_dwAddr = FinalJumpDestination(m_ppInstructionSet[i]->m_operand.m_dwAddr);
1468 }
1469 }
1470
1471 // Remove jumps to next instruction
1472 for(i = 0; i < m_dwCodeSize; i++)
1473 {
1474 if (((m_ppInstructionSet[i]->m_nOpCode == OPCODE_JMP) ||
1475 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JZ) ||
1476 (m_ppInstructionSet[i]->m_nOpCode == OPCODE_JNZ)) &&
1477 (m_ppInstructionSet[i]->m_operand.m_dwAddr == i + 1))
1478 {
1479 delete m_ppInstructionSet[i];
1480 m_dwCodeSize--;
1481 memmove(&m_ppInstructionSet[i], &m_ppInstructionSet[i + 1], sizeof(NXSL_Instruction *) * (m_dwCodeSize - i));
1482
1483 // Change jump destination addresses
1484 for(j = 0; j < m_dwCodeSize; j++)
1485 {
1486 if (((m_ppInstructionSet[j]->m_nOpCode == OPCODE_JMP) ||
1487 (m_ppInstructionSet[j]->m_nOpCode == OPCODE_JZ) ||
1488 (m_ppInstructionSet[j]->m_nOpCode == OPCODE_JNZ) ||
1489 (m_ppInstructionSet[j]->m_nOpCode == OPCODE_CALL)) &&
1490 (m_ppInstructionSet[j]->m_operand.m_dwAddr > i))
1491 {
1492 m_ppInstructionSet[j]->m_operand.m_dwAddr--;
1493 }
1494 }
1495
1496 i--;
1497 }
1498 }
1499 }