Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1446 lines
40 KiB
C++
1446 lines
40 KiB
C++
//***************************************************************************
|
|
//
|
|
// ABLENV.CPP
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "MW4Headers.hpp"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifndef ABLGEN_H
|
|
#include "ablgen.h"
|
|
#endif
|
|
|
|
#ifndef ABLERR_H
|
|
#include "ablerr.h"
|
|
#endif
|
|
|
|
#ifndef ABLSCAN_H
|
|
#include "ablscan.h"
|
|
#endif
|
|
|
|
#ifndef ABLEXEC_H
|
|
#include "ablexec.h"
|
|
#endif
|
|
|
|
#ifndef ABLENV_H
|
|
#include "ablenv.h"
|
|
#endif
|
|
|
|
#ifndef ABLDBUG_H
|
|
#include "abldbug.h"
|
|
#endif
|
|
|
|
#ifndef ABLHEAP_H
|
|
#include "ablheap.h"
|
|
#endif
|
|
|
|
#ifndef ABLFILE_H
|
|
#include "ablfile.h"
|
|
#endif
|
|
|
|
#include "ai.hpp"
|
|
#include "mwobject.hpp"
|
|
|
|
#include <gameos\gameos.hpp>
|
|
//***************************************************************************
|
|
namespace ABL
|
|
{
|
|
MechWarrior4::AI *CurWarrior;
|
|
|
|
StackItem returnValue;
|
|
bool eofFlag = false;
|
|
bool ExitWithReturn = false;
|
|
bool ExitFromTacOrder = false;
|
|
|
|
//-------------------
|
|
// EXTERNAL variables
|
|
extern UserHeapPtr AblStackHeap;
|
|
|
|
extern long lineNumber;
|
|
extern long errorCount;
|
|
extern long execStatementCount;
|
|
|
|
extern TokenCodeType curToken;
|
|
extern char wordString[];
|
|
extern SymTableNodePtr symTableDisplay[];
|
|
extern long level;
|
|
extern bool blockFlag;
|
|
extern BlockType blockType;
|
|
extern bool printFlag;
|
|
extern SymTableNodePtr CurModuleIdPtr;
|
|
extern SymTableNodePtr CurRoutineIdPtr;
|
|
extern long CurModuleHandle;
|
|
extern bool CallModuleInit;
|
|
extern long FileNumber;
|
|
|
|
extern Type DummyType;
|
|
extern char* codeBuffer;
|
|
extern char* codeBufferPtr;
|
|
extern StackItem* stack;
|
|
//extern StackItem* eternalStack;
|
|
extern StackItemPtr tos;
|
|
extern StackItemPtr stackFrameBasePtr;
|
|
extern long eternalOffset;
|
|
|
|
extern TokenCodeType statementStartList[];
|
|
extern TokenCodeType statementEndList[];
|
|
extern TokenCodeType declarationStartList[];
|
|
|
|
extern char tokenString[MAXLEN_TOKENSTRING];
|
|
|
|
extern CharCodeType charTable[256];
|
|
extern FILE* sourceFile;
|
|
|
|
extern char sourceBuffer[MAXLEN_SOURCELINE];
|
|
extern long bufferOffset;
|
|
extern char* bufferp;
|
|
extern char* tokenp;
|
|
|
|
extern long digitCount;
|
|
extern bool countError;
|
|
|
|
extern bool eofFlag;
|
|
extern long pageNumber;
|
|
|
|
extern UserHeapPtr systemHeap;
|
|
extern UserHeapPtr AblSymTableHeap;
|
|
extern UserHeapPtr AblStackHeap;
|
|
extern UserHeapPtr AblCodeHeap;
|
|
|
|
extern SymTableNodePtr SymTableDisplay[MAX_NESTING_LEVEL];
|
|
extern TypePtr IntegerTypePtr;
|
|
extern TypePtr RealTypePtr;
|
|
extern TypePtr BooleanTypePtr;
|
|
|
|
extern StackItemPtr StaticDataPtr;
|
|
extern StackItem returnValue;
|
|
|
|
extern DebuggerPtr debugger;
|
|
extern long* EternalVariablesSizes;
|
|
|
|
//-----------------------
|
|
// CLASS static variables
|
|
long NumModules = 0;
|
|
|
|
//-----------------
|
|
// GLOBAL variables
|
|
ModuleEntryPtr ModuleRegistry = NULL;
|
|
ABLModulePtr* ModuleInstanceRegistry = NULL;
|
|
long MaxModules = 0;
|
|
long NumModulesRegistered = 0;
|
|
long NumModuleInstances = 0;
|
|
long MaxWatchesPerModule = 20;
|
|
long MaxBreakPointsPerModule = 20;
|
|
ABLModulePtr CurModule = NULL;
|
|
ABLModulePtr CurLibrary = NULL;
|
|
ABLModulePtr* LibraryInstanceRegistry = NULL;
|
|
long MaxLibraries = 0;
|
|
extern long numLibrariesLoaded;
|
|
|
|
extern long NumExecutions;
|
|
long CallStackLevel = 0;
|
|
|
|
#define MAX_PROFILE_LINELEN 128
|
|
#define MAX_PROFILE_LINES 256
|
|
|
|
long NumProfileLogLines = 0;
|
|
long TotalProfileLogLines = 0;
|
|
char ProfileLogBuffer[MAX_PROFILE_LINES][MAX_PROFILE_LINELEN];
|
|
bool ProfileLog = true;
|
|
double ProfileLogFunctionTimeLimit = 0.005f;
|
|
|
|
// UserFile *UserFile::files[MAX_USER_FILES];
|
|
|
|
//***************************************************************************
|
|
// PROFILING LOG routines
|
|
//***************************************************************************
|
|
|
|
void DumpProfileLog (void)
|
|
{
|
|
//----------------
|
|
// Dump to file...
|
|
if (ProfileLog)
|
|
{
|
|
#if defined(LAB_ONLY)
|
|
for (long i = 0; i < NumProfileLogLines; i++)
|
|
{
|
|
SPEWALWAYS (("afarrier",ProfileLogBuffer[i]));
|
|
}
|
|
#endif
|
|
NumProfileLogLines = 0;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABL_CloseProfileLog (void)
|
|
{
|
|
if (ProfileLog)
|
|
{
|
|
DumpProfileLog();
|
|
#if defined(LAB_ONLY)
|
|
char s[512];
|
|
sprintf(s, "\nABL:: Num Total Lines = %d\n", TotalProfileLogLines);
|
|
SPEWALWAYS (("afarrier",s));
|
|
#endif
|
|
ProfileLog = false;
|
|
NumProfileLogLines = 0;
|
|
TotalProfileLogLines = 0;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABL_OpenProfileLog (void)
|
|
{
|
|
if (ProfileLog)
|
|
ABL_CloseProfileLog();
|
|
|
|
NumProfileLogLines = 0;
|
|
ProfileLog = true;
|
|
#if 0
|
|
if (!ProfileLog)
|
|
ABL_Fatal(0, " unable to malloc ABL ProfileLog ");
|
|
if (ProfileLog->create("abl.log") != NO_ERR)
|
|
ABL_Fatal(0, " unable to create ABL ProfileLog ");
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABL_AddToProfileLog (char* profileString)
|
|
{
|
|
if (NumProfileLogLines == MAX_PROFILE_LINES)
|
|
DumpProfileLog();
|
|
|
|
strncpy(ProfileLogBuffer[NumProfileLogLines], profileString, MAX_PROFILE_LINELEN - 1);
|
|
ProfileLogBuffer[NumProfileLogLines][MAX_PROFILE_LINELEN] = NULL;
|
|
NumProfileLogLines++;
|
|
TotalProfileLogLines++;
|
|
}
|
|
#if 0
|
|
//***************************************************************************
|
|
// USER FILE routines
|
|
//***************************************************************************
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void UserFile::dump (void)
|
|
{
|
|
|
|
//----------------
|
|
// Dump to file...
|
|
for (long i = 0; i < numLines; i++)
|
|
filePtr->writeString(lines[i]);
|
|
numLines = 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void UserFile::close (void)
|
|
{
|
|
|
|
if (filePtr && inUse)
|
|
{
|
|
dump();
|
|
char s[512];
|
|
sprintf(s, "\nNum Total Lines = %d\n", totalLines);
|
|
filePtr->writeString(s);
|
|
filePtr->close();
|
|
inUse = false;
|
|
numLines = 0;
|
|
totalLines = 0;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long UserFile::open (MemoryStream *str)
|
|
{
|
|
stream = str;
|
|
numLines = 0;
|
|
totalLines = 0;
|
|
|
|
inUse = true;
|
|
return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void UserFile::write (char* s)
|
|
{
|
|
|
|
static char buffer[MAX_USER_FILE_LINELEN];
|
|
|
|
if (numLines == MAX_USER_FILE_LINES)
|
|
dump();
|
|
|
|
if (strlen(s) > (MAX_USER_FILE_LINELEN - 1))
|
|
s[MAX_USER_FILE_LINELEN - 1] = NULL;
|
|
|
|
sprintf(buffer, "%s\n", s);
|
|
strncpy(lines[numLines], buffer, MAX_USER_FILE_LINELEN - 1);
|
|
numLines++;
|
|
totalLines++;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
UserFile* UserFile::getNewFile (void)
|
|
{
|
|
|
|
long fileHandle = -1;
|
|
for (long i = 0; i < MAX_USER_FILES; i++)
|
|
if (!files[i]->inUse)
|
|
{
|
|
fileHandle = i;
|
|
break;
|
|
}
|
|
return(files[i]);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void UserFile::setup (void)
|
|
{
|
|
|
|
for (long i = 0; i < MAX_USER_FILES; i++)
|
|
{
|
|
files[i] = (UserFile*)gos_Malloc(sizeof(UserFile));
|
|
files[i]->init();
|
|
files[i]->handle = i;
|
|
files[i]->inUse = false;
|
|
files[i]->filePtr = new File;
|
|
if (!files[i]->filePtr)
|
|
ABL_Fatal(0, " ABL: Unable to malloc UserFiles ");
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void UserFile::cleanup (void)
|
|
{
|
|
|
|
for (long i = 0; i < MAX_USER_FILES; i++)
|
|
{
|
|
if (files[i] && files[i]->inUse)
|
|
{
|
|
files[i]->close();
|
|
files[i]->filePtr->close();
|
|
delete files[i]->filePtr;
|
|
files[i]->filePtr = NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
//***************************************************************************
|
|
// MODULE REGISTRY routines
|
|
//***************************************************************************
|
|
|
|
void initModuleRegistry (long maxModules)
|
|
{
|
|
|
|
//---------------------------------------------------------------------
|
|
// First, set the max number of modules that may be loaded into the ABL
|
|
// environment at a time...
|
|
MaxModules = maxModules;
|
|
|
|
//------------------------------
|
|
// Create the module registry...
|
|
ModuleRegistry = (ModuleEntryPtr)AblStackHeap->Malloc(sizeof(ModuleEntry) * MaxModules);
|
|
if (!ModuleRegistry)
|
|
ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc Module Registry ");
|
|
memset(ModuleRegistry, 0, sizeof(ModuleEntry) * MaxModules);
|
|
|
|
//-------------------------------------------------
|
|
// Create the active (ABLModule) module registry...
|
|
ModuleInstanceRegistry = (ABLModulePtr*)AblStackHeap->Malloc(sizeof(ABLModulePtr) * MaxModules);
|
|
if (!ModuleInstanceRegistry)
|
|
ABL_Fatal(0, " ABL: Unable to malloc AblStackHeap->Module Instance Registry ");
|
|
memset(ModuleInstanceRegistry, 0, sizeof(ABLModulePtr) * MaxModules);
|
|
}
|
|
|
|
//***************************************************************************
|
|
|
|
void destroyModuleRegistry (void)
|
|
{
|
|
|
|
if (!AblStackHeap)
|
|
return;
|
|
|
|
//-----------------------------------------------------------
|
|
// First, go through the registry, free'n each module and its
|
|
// associated data...
|
|
for (long i = 0; i < NumModulesRegistered; i++)
|
|
{
|
|
//destroyModule(ModuleRegistry[i].moduleIdPtr);
|
|
AblStackHeap->Free(ModuleRegistry[i].fileName);
|
|
ModuleRegistry[i].fileName = NULL;
|
|
ModuleRegistry[i].moduleIdPtr = NULL;
|
|
for (long j = 0; j < ModuleRegistry[i].numSourceFiles; j++)
|
|
{
|
|
AblStackHeap->Free(ModuleRegistry[i].sourceFiles[j]);
|
|
ModuleRegistry[i].sourceFiles[j] = NULL;
|
|
}
|
|
}
|
|
|
|
AblStackHeap->Free(ModuleRegistry);
|
|
ModuleRegistry = NULL;
|
|
|
|
AblStackHeap->Free(ModuleInstanceRegistry);
|
|
ModuleInstanceRegistry = NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// LIBRARY REGISTRY routines
|
|
//***************************************************************************
|
|
|
|
void initLibraryRegistry (long maxLibraries)
|
|
{
|
|
|
|
//-----------------------------------------------------------------------
|
|
// First, set the max number of libraries that may be loaded into the ABL
|
|
// environment at a time...
|
|
MaxLibraries = maxLibraries;
|
|
|
|
//--------------------------------------------------
|
|
// Create the active (ABLModule) library registry...
|
|
LibraryInstanceRegistry = (ABLModulePtr*)AblStackHeap->Malloc(sizeof(ABLModulePtr) * MaxLibraries);
|
|
if (!LibraryInstanceRegistry)
|
|
ABL_Fatal(0, " ABL: Unable to malloc AblStackHeap->Library Instance Registry ");
|
|
memset(LibraryInstanceRegistry, 0, sizeof(ABLModulePtr) * MaxLibraries);
|
|
}
|
|
|
|
//***************************************************************************
|
|
|
|
void destroyLibraryRegistry (void)
|
|
{
|
|
|
|
if (!AblStackHeap)
|
|
return;
|
|
|
|
//-----------------------------------------------------------------
|
|
// Kinda need to do the same thing here as in the normal Registry.
|
|
// Or leak o RAMA!!!!!!!
|
|
// The actual data held by the pointer is removed in destroyModuleRegistry.
|
|
// However, the classes holding the actual ABLModulePtr are then responsible
|
|
// for deleting the ABLModulePtr. Libraries have no owner class which, I'm guessing,
|
|
// this class was supposed to do. This class now does that!!!!
|
|
// -fs 1/25/98
|
|
for (long i=0;i<numLibrariesLoaded;i++)
|
|
{
|
|
delete LibraryInstanceRegistry[i];
|
|
LibraryInstanceRegistry[i] = NULL;
|
|
}
|
|
|
|
AblStackHeap->Free(LibraryInstanceRegistry);
|
|
LibraryInstanceRegistry = NULL;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// ABLMODULE class
|
|
//***************************************************************************
|
|
#if 0
|
|
void* ABLModule::operator new (size_t mySize)
|
|
{
|
|
|
|
void* result = NULL;
|
|
|
|
result = gos_Malloc(mySize);
|
|
|
|
return(result);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::operator delete (void* us)
|
|
{
|
|
|
|
gos_Free(us);
|
|
}
|
|
#endif
|
|
//---------------------------------------------------------------------------
|
|
|
|
ABLModule::reset (void)
|
|
{
|
|
long numStatics = ModuleRegistry[handle].numStaticVars;
|
|
if (numStatics)
|
|
{
|
|
long* sizeList = ModuleRegistry[handle].sizeStaticVars;
|
|
for (long i = 0; i < numStatics; i++)
|
|
if (sizeList[i] > 0)
|
|
{
|
|
memset (staticData[i].address,0,sizeList[i]);
|
|
}
|
|
else
|
|
staticData[i].integer = 0;
|
|
}
|
|
|
|
SwitchStates("startstate");
|
|
}
|
|
|
|
long ABLModule::init (long moduleHandle)
|
|
{
|
|
|
|
init ();
|
|
id = NumModules++;
|
|
handle = moduleHandle;
|
|
staticData = NULL;
|
|
long numStatics = ModuleRegistry[handle].numStaticVars;
|
|
if (numStatics)
|
|
{
|
|
staticData = (StackItemPtr)AblStackHeap->Malloc(sizeof(StackItem) * numStatics);
|
|
if (!staticData)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc staticData [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
long* sizeList = ModuleRegistry[handle].sizeStaticVars;
|
|
for (long i = 0; i < numStatics; i++)
|
|
if (sizeList[i] > 0)
|
|
{
|
|
staticData[i].address = (char*)AblStackHeap->Malloc(sizeList[i]);
|
|
if (!staticData)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc staticData address [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
}
|
|
else
|
|
staticData[i].integer = 0;
|
|
}
|
|
ModuleRegistry[handle].numInstances++;
|
|
initCalled = false;
|
|
|
|
SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr;
|
|
if (moduleIdPtr->defn.key == DFN_FSM)
|
|
{
|
|
moduleIdPtr->defn.info.routine.state = NULL;
|
|
curState = searchSymTable("startstate", moduleIdPtr->defn.info.routine.localSymTable);
|
|
if (curState == NULL)
|
|
ABL_Fatal (0,"Could not find start state");
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// This Active Module is now on the instance registry...
|
|
ModuleInstanceRegistry[NumModuleInstances++] = this;
|
|
|
|
if (debugger)
|
|
{
|
|
watchManager = new WatchManager;
|
|
if (!watchManager)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc WatchManager ");
|
|
long result = watchManager->init(MaxWatchesPerModule);
|
|
if (result != NO_ERR)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc WatchManager ");
|
|
breakPointManager = new BreakPointManager;
|
|
if (!breakPointManager)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc BreakPointManager ");
|
|
result = breakPointManager->init(MaxBreakPointsPerModule);
|
|
if (result != NO_ERR)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc BreakPointManager ");
|
|
}
|
|
|
|
//--------------------
|
|
// Can this ever fail?
|
|
return(NO_ERR);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::write (MemoryStream *stream)
|
|
{
|
|
|
|
*stream << name;
|
|
*stream << handle;
|
|
if (curState)
|
|
{
|
|
*stream << true;
|
|
*stream << strlen (curState->name);
|
|
stream->WriteLine (curState->name);
|
|
}
|
|
else
|
|
*stream << false;
|
|
|
|
long numStatics = ModuleRegistry[handle].numStaticVars;
|
|
long* sizeList = ModuleRegistry[handle].sizeStaticVars;
|
|
for (long i = 0; i < numStatics; i++)
|
|
{
|
|
if (sizeList[i] > 0)
|
|
stream->WriteBytes ((MemoryPtr)staticData[i].address, sizeList[i]);
|
|
else
|
|
stream->WriteBytes ((MemoryPtr)&staticData[i], sizeof(StackItem));
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::read (MemoryStream *stream)
|
|
{
|
|
|
|
//----------------------------------------------------------------------------
|
|
// If this is called on a newly init'd module, then it will do all appropriate
|
|
// memory alloc, etc. If it's being called on a module that's already been
|
|
// setup (via a call to init(moduleHandle)), then it simply loads the
|
|
// module's data...
|
|
char *state = NULL;
|
|
char tname[MAX_ABLMODULE_NAME];
|
|
stream->ReadLine (tname,MAX_ABLMODULE_NAME);
|
|
Verify (!strcmp (name,tname));
|
|
bool fresh = (id == -1);
|
|
Verify (!fresh);
|
|
if (fresh)
|
|
{
|
|
id = NumModules++;
|
|
*stream >> handle;
|
|
// handle = moduleFile->readLong();
|
|
staticData = NULL;
|
|
}
|
|
else
|
|
{
|
|
#pragma warning (disable : 4189)
|
|
long ignore;
|
|
*stream >> ignore;
|
|
// long ignore = moduleFile->readLong();
|
|
}
|
|
|
|
bool flag;
|
|
*stream >> flag;
|
|
if (flag)
|
|
{
|
|
int len;
|
|
*stream >> len;
|
|
state = new char[len+1];
|
|
stream->ReadBytes (state,len+1);
|
|
}
|
|
|
|
long numStatics = ModuleRegistry[handle].numStaticVars;
|
|
if (numStatics)
|
|
{
|
|
if (fresh)
|
|
{
|
|
staticData = (StackItemPtr)AblStackHeap->Malloc(sizeof(StackItem) * numStatics);
|
|
if (!staticData)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc staticData [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
}
|
|
long* sizeList = ModuleRegistry[handle].sizeStaticVars;
|
|
for (long i = 0; i < numStatics; i++)
|
|
if (sizeList[i] > 0)
|
|
{
|
|
if (fresh)
|
|
{
|
|
staticData[i].address = (char*)AblStackHeap->Malloc(sizeList[i]);
|
|
if (!staticData)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc staticData address [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
}
|
|
stream->ReadBytes ((MemoryPtr)staticData[i].address, sizeList[i]);
|
|
}
|
|
else
|
|
{
|
|
staticData[i].integer = 0;
|
|
stream->ReadBytes ((MemoryPtr)&staticData[i], sizeof(StackItem));
|
|
}
|
|
}
|
|
if (fresh)
|
|
{
|
|
ModuleRegistry[handle].numInstances++;
|
|
initCalled = false;
|
|
|
|
//------------------------------------------------------
|
|
// This Active Module is now on the instance registry...
|
|
ModuleInstanceRegistry[NumModuleInstances++] = this;
|
|
|
|
if (debugger)
|
|
{
|
|
watchManager = new WatchManager;
|
|
if (!watchManager)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc WatchManager ");
|
|
long result = watchManager->init(MaxWatchesPerModule);
|
|
if (result != NO_ERR)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc WatchManager ");
|
|
breakPointManager = new BreakPointManager;
|
|
if (!breakPointManager)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc BreakPointManager ");
|
|
result = breakPointManager->init(MaxBreakPointsPerModule);
|
|
if (result != NO_ERR)
|
|
ABL_Fatal(0, " Unable to AblStackHeap->malloc BreakPointManager ");
|
|
}
|
|
}
|
|
|
|
SwitchStates (state);
|
|
delete[] state;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::setName (char* _name)
|
|
{
|
|
|
|
strncpy(name, _name, MAX_ABLMODULE_NAME);
|
|
name[MAX_ABLMODULE_NAME] = NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
void ABLModule::SwitchStates (const char *name)
|
|
{
|
|
SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr;
|
|
Verify (moduleIdPtr->defn.key == DFN_FSM);
|
|
curState = searchSymTable(name, moduleIdPtr->defn.info.routine.localSymTable);
|
|
if (curState == NULL)
|
|
ABL_Fatal (0,"Could not find current state");
|
|
}
|
|
|
|
long ABLModule::execute (ABLParamPtr paramList)
|
|
{
|
|
|
|
CurModule = this;
|
|
if (debugger)
|
|
debugger->setModule(this);
|
|
|
|
//--------------------------
|
|
// Execute the ABL module...
|
|
SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr;
|
|
|
|
//--------------------------------------------
|
|
// Point to this module's static data space...
|
|
StaticDataPtr = staticData;
|
|
|
|
//---------------------------------
|
|
// Init some important variables...
|
|
CurModuleIdPtr = NULL;
|
|
CurRoutineIdPtr = NULL;
|
|
FileNumber = -1;
|
|
errorCount = 0;
|
|
execStatementCount = 0;
|
|
NumExecutions++;
|
|
|
|
//------------------
|
|
// Init the stack...
|
|
stackFrameBasePtr = tos = (stack + eternalOffset);
|
|
|
|
//---------------------------------------
|
|
// Initialize the module's stack frame...
|
|
level = 1;
|
|
CallStackLevel = 0;
|
|
stackFrameBasePtr = tos + 1;
|
|
|
|
//-------------------------
|
|
// Function return value...
|
|
pushInteger(0);
|
|
//---------------
|
|
// Static Link...
|
|
pushAddress(NULL);
|
|
//----------------
|
|
// Dynamic Link...
|
|
pushAddress(NULL);
|
|
//------------------
|
|
// Return Address...
|
|
pushAddress(NULL);
|
|
|
|
//initDebugger();
|
|
|
|
//----------
|
|
// Run it...
|
|
|
|
if (paramList)
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
// NOTE: Currently, parameter passing of arrays is not functioning. This MUST be
|
|
// done...
|
|
long curParam = 0;
|
|
for (SymTableNodePtr formalIdPtr = (SymTableNodePtr)(moduleIdPtr->defn.info.routine.params);
|
|
formalIdPtr != NULL;
|
|
formalIdPtr = formalIdPtr->next)
|
|
{
|
|
|
|
TypePtr formalTypePtr = (TypePtr)(formalIdPtr->typePtr);
|
|
|
|
if (formalIdPtr->defn.key == DFN_VALPARAM)
|
|
{
|
|
|
|
if (formalTypePtr == RealTypePtr)
|
|
{
|
|
if (paramList[curParam].type == ABL_PARAM_INTEGER)
|
|
{
|
|
//---------------------------------------------
|
|
// Real formal parameter, but integer actual...
|
|
pushReal((float)(paramList[curParam].integer));
|
|
}
|
|
else if (paramList[curParam].type == ABL_PARAM_REAL)
|
|
pushReal(paramList[curParam].real);
|
|
}
|
|
else if (formalTypePtr == IntegerTypePtr)
|
|
{
|
|
if (paramList[curParam].type== ABL_PARAM_INTEGER)
|
|
pushInteger(paramList[curParam].integer);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
// Formal parameter is an array or record, so make a copy...
|
|
if ((formalTypePtr->form == FRM_ARRAY)/* || (formalTypePtr->form == FRM_RECORD)*/)
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
// The following is a little inefficient, but is kept this way to keep it clear.
|
|
// Once it's verified to work, optimize...
|
|
long size = formalTypePtr->size;
|
|
char* dest = (char*)AblStackHeap->Malloc((size_t)size);
|
|
if (!dest)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc array parameter [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
char* src = tos->address;
|
|
char* savePtr = dest;
|
|
memcpy(dest, src, size);
|
|
tos->address = savePtr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------
|
|
// pass by reference parameter...
|
|
if (formalTypePtr == RealTypePtr)
|
|
pushAddress((Address)&(paramList[curParam].real));
|
|
else if (formalTypePtr == IntegerTypePtr)
|
|
pushAddress((Address)&(paramList[curParam].integer));
|
|
else
|
|
return(0);
|
|
//SymTableNodePtr idPtr = getCodeSymTableNodePtr();
|
|
//execVariable(idPtr, USE_REFPARAM);
|
|
}
|
|
curParam++;
|
|
}
|
|
}
|
|
|
|
CurModuleHandle = handle;
|
|
|
|
CallModuleInit = !initCalled;
|
|
initCalled = true;
|
|
|
|
Verify (moduleIdPtr->defn.info.routine.state == NULL);
|
|
moduleIdPtr->defn.info.routine.state = curState;
|
|
ABL::execute(moduleIdPtr);
|
|
curState = moduleIdPtr->defn.info.routine.state;
|
|
moduleIdPtr->defn.info.routine.state = NULL;
|
|
|
|
memcpy(&returnVal, &returnValue, sizeof(StackItem));
|
|
|
|
//-----------
|
|
// Summary...
|
|
return(execStatementCount);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::execute (ABLParamPtr moduleParamList, SymTableNodePtr functionIdPtr)
|
|
{
|
|
|
|
CurModule = this;
|
|
if (debugger)
|
|
debugger->setModule(this);
|
|
|
|
//--------------------------
|
|
// Execute the ABL module...
|
|
SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr;
|
|
|
|
//--------------------------------------------
|
|
// Point to this module's static data space...
|
|
StaticDataPtr = staticData;
|
|
|
|
//---------------------------------
|
|
// Init some important variables...
|
|
CurModuleIdPtr = NULL;
|
|
CurRoutineIdPtr = NULL;
|
|
FileNumber = -1;
|
|
errorCount = 0;
|
|
execStatementCount = 0;
|
|
NumExecutions++;
|
|
|
|
//------------------
|
|
// Init the stack...
|
|
stackFrameBasePtr = tos = (stack + eternalOffset);
|
|
|
|
//---------------------------------------
|
|
// Initialize the module's stack frame...
|
|
level = 1;
|
|
CallStackLevel = 0;
|
|
stackFrameBasePtr = tos + 1;
|
|
|
|
//-------------------------
|
|
// Function return value...
|
|
pushInteger(0);
|
|
//---------------
|
|
// Static Link...
|
|
pushAddress(NULL);
|
|
//----------------
|
|
// Dynamic Link...
|
|
pushAddress(NULL);
|
|
//------------------
|
|
// Return Address...
|
|
pushAddress(NULL);
|
|
|
|
//initDebugger();
|
|
|
|
//----------
|
|
// Run it...
|
|
|
|
if (moduleParamList)
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
// NOTE: Currently, parameter passing of arrays is not functioning. This MUST be
|
|
// done...
|
|
long curParam = 0;
|
|
for (SymTableNodePtr formalIdPtr = (SymTableNodePtr)(moduleIdPtr->defn.info.routine.params);
|
|
formalIdPtr != NULL;
|
|
formalIdPtr = formalIdPtr->next)
|
|
{
|
|
|
|
TypePtr formalTypePtr = (TypePtr)(formalIdPtr->typePtr);
|
|
|
|
if (formalIdPtr->defn.key == DFN_VALPARAM)
|
|
{
|
|
|
|
if (formalTypePtr == RealTypePtr)
|
|
{
|
|
if (moduleParamList[curParam].type == ABL_PARAM_INTEGER)
|
|
{
|
|
//---------------------------------------------
|
|
// Real formal parameter, but integer actual...
|
|
pushReal((float)(moduleParamList[curParam].integer));
|
|
}
|
|
else if (moduleParamList[curParam].type == ABL_PARAM_REAL)
|
|
pushReal(moduleParamList[curParam].real);
|
|
}
|
|
else if (formalTypePtr == IntegerTypePtr)
|
|
{
|
|
if (moduleParamList[curParam].type== ABL_PARAM_INTEGER)
|
|
pushInteger(moduleParamList[curParam].integer);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
//----------------------------------------------------------
|
|
// Formal parameter is an array or record, so make a copy...
|
|
if ((formalTypePtr->form == FRM_ARRAY)/* || (formalTypePtr->form == FRM_RECORD)*/)
|
|
{
|
|
//------------------------------------------------------------------------------
|
|
// The following is a little inefficient, but is kept this way to keep it clear.
|
|
// Once it's verified to work, optimize...
|
|
long size = formalTypePtr->size;
|
|
char* dest = (char*)AblStackHeap->Malloc((size_t)size);
|
|
if (!dest)
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABL: Unable to AblStackHeap->malloc array parameter [Module %d]", id);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
char* src = tos->address;
|
|
char* savePtr = dest;
|
|
memcpy(dest, src, size);
|
|
tos->address = savePtr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//-------------------------------
|
|
// pass by reference parameter...
|
|
if (formalTypePtr == RealTypePtr)
|
|
pushAddress((Address)&(moduleParamList[curParam].real));
|
|
else if (formalTypePtr == IntegerTypePtr)
|
|
pushAddress((Address)&(moduleParamList[curParam].integer));
|
|
else
|
|
return(0);
|
|
}
|
|
curParam++;
|
|
}
|
|
}
|
|
|
|
CurModuleHandle = handle;
|
|
|
|
CallModuleInit = !initCalled;
|
|
initCalled = true;
|
|
|
|
ABL::executeChild(moduleIdPtr, functionIdPtr);
|
|
|
|
memcpy(&returnVal, &returnValue, sizeof(StackItem));
|
|
|
|
//-----------
|
|
// Summary...
|
|
return(execStatementCount);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
SymTableNodePtr ABLModule::findSymbol (char* symbolName, SymTableNodePtr curFunction, bool searchLibraries)
|
|
{
|
|
|
|
if (curFunction)
|
|
{
|
|
SymTableNodePtr symbol = searchSymTable(strlwr(symbolName), curFunction->defn.info.routine.localSymTable);
|
|
if (symbol)
|
|
return(symbol);
|
|
}
|
|
|
|
SymTableNodePtr symbol = searchSymTable(strlwr(symbolName), ModuleRegistry[handle].moduleIdPtr->defn.info.routine.localSymTable);
|
|
|
|
if (!symbol && searchLibraries)
|
|
{
|
|
for (long i = 0; i < ModuleRegistry[handle].numLibrariesUsed; i++)
|
|
{
|
|
symbol = searchSymTable(strlwr(symbolName), ModuleRegistry[ModuleRegistry[handle].librariesUsed[i]->handle].moduleIdPtr->defn.info.routine.localSymTable);
|
|
if (symbol)
|
|
break;
|
|
}
|
|
}
|
|
if (!symbol)
|
|
{
|
|
symbol = searchSymTableDisplay(strlwr(symbolName));
|
|
}
|
|
|
|
return(symbol);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
SymTableNodePtr ABLModule::findFunction (char* functionName, bool searchLibraries)
|
|
{
|
|
|
|
SymTableNodePtr symbol = searchSymTable(functionName, ModuleRegistry[handle].moduleIdPtr->defn.info.routine.localSymTable);
|
|
|
|
if (!symbol && searchLibraries)
|
|
{
|
|
for (long i = 0; i < ModuleRegistry[handle].numLibrariesUsed; i++)
|
|
{
|
|
symbol = searchSymTable(strlwr(functionName), ModuleRegistry[ModuleRegistry[handle].librariesUsed[i]->handle].moduleIdPtr->defn.info.routine.localSymTable);
|
|
if (symbol)
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(symbol);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::setStaticInteger (char* name, long value)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(1);
|
|
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr);
|
|
if (baseTypePtr != IntegerTypePtr)
|
|
return(2);
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(3);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
*((long*)dataPtr) = value;
|
|
return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::getStaticInteger (char* name)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(0xFFFFFFFF);
|
|
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr);
|
|
if (baseTypePtr != IntegerTypePtr)
|
|
return(0xFFFFFFFF);
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(0xFFFFFFFF);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
return(*((long*)dataPtr));
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::setStaticReal (char* name, float value)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(1);
|
|
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr);
|
|
if (baseTypePtr != RealTypePtr)
|
|
return(2);
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(3);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
*((float*)dataPtr) = value;
|
|
return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
float ABLModule::getStaticReal (char* name)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(-999999.0);
|
|
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr);
|
|
if (baseTypePtr != RealTypePtr)
|
|
return(-999999.0);
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(-999999.0);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
return(*((float*)dataPtr));
|
|
// return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::setStaticIntegerArray (char* name, long numValues, long* values)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(1);
|
|
|
|
// NOTE: This function is not dummy-proof. Essentially, this routine copies
|
|
// the values data into the array's data space WITHOUT checking to make sure
|
|
// the array really is an array (single or mult-dimensional) of reals. User
|
|
// beware!
|
|
/*
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr->info.array.elementTypePtr);
|
|
if (baseTypePtr != IntegerTypePtr)
|
|
return(2);
|
|
*/
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(3);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
memcpy(dataPtr->address, values, 4 * numValues);
|
|
|
|
return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::getStaticIntegerArray (char* name, long numValues, long* values)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(0);
|
|
|
|
// NOTE: This function is not dummy-proof. Essentially, this routine copies
|
|
// the values data into the array's data space WITHOUT checking to make sure
|
|
// the array really is an array (single or mult-dimensional) of reals. User
|
|
// beware!
|
|
/*
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr->info.array.elementTypePtr);
|
|
if (baseTypePtr != IntegerTypePtr)
|
|
return(2);
|
|
*/
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(0);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
memcpy(values, dataPtr->address, 4 * numValues);
|
|
return(1);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::setStaticRealArray (char* name, long numValues, float* values)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(1);
|
|
|
|
// NOTE: This function is not dummy-proof. Essentially, this routine copies
|
|
// the values data into the array's data space WITHOUT checking to make sure
|
|
// the array really is an array (single or mult-dimensional) of reals. User
|
|
// beware!
|
|
/*
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr->info.array.elementTypePtr);
|
|
if (baseTypePtr != RealTypePtr)
|
|
return(2);
|
|
*/
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(3);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
memcpy(dataPtr->address, values, 4 * numValues);
|
|
|
|
return(0);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
long ABLModule::getStaticRealArray (char* name, long numValues, float* values)
|
|
{
|
|
|
|
SymTableNodePtr symbol = findSymbol(name);
|
|
if (!symbol)
|
|
return(0);
|
|
|
|
// NOTE: This function is not dummy-proof. Essentially, this routine copies
|
|
// the values data into the array's data space WITHOUT checking to make sure
|
|
// the array really is an array (single or mult-dimensional) of reals. User
|
|
// beware!
|
|
/*
|
|
TypePtr baseTypePtr = baseType(symbol->typePtr->info.array.elementTypePtr);
|
|
if (baseTypePtr != RealTypePtr)
|
|
return(2);
|
|
*/
|
|
|
|
if (symbol->defn.info.data.varType != VAR_TYPE_STATIC)
|
|
return(0);
|
|
|
|
StackItemPtr dataPtr = staticData + symbol->defn.info.data.offset;
|
|
memcpy(values, dataPtr->address, 4 * numValues);
|
|
|
|
return(1);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
char* ABLModule::getSourceFile (long fileNumber)
|
|
{
|
|
|
|
return(ModuleRegistry[handle].sourceFiles[fileNumber]);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
char* ABLModule::getSourceDirectory (long fileNumber, char* directory)
|
|
{
|
|
|
|
char* fileName = ModuleRegistry[handle].sourceFiles[fileNumber];
|
|
long curChar = strlen(fileName);
|
|
while ((curChar > -1) && (fileName[curChar] != '\\'))
|
|
curChar--;
|
|
if (curChar == -1)
|
|
return(NULL);
|
|
strcpy(directory, fileName);
|
|
directory[curChar + 1] = NULL;
|
|
return(directory);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void buildRoutineList (SymTableNodePtr curSymbol, ModuleInfo* moduleInfo)
|
|
{
|
|
|
|
if (curSymbol)
|
|
{
|
|
buildRoutineList(curSymbol->left, moduleInfo);
|
|
if (curSymbol->defn.key == DFN_FUNCTION)
|
|
{
|
|
if (moduleInfo->numRoutines < 1024)
|
|
{
|
|
strcpy(moduleInfo->routineInfo[moduleInfo->numRoutines].name, curSymbol->name);
|
|
moduleInfo->routineInfo[moduleInfo->numRoutines].codeSegmentSize = curSymbol->defn.info.routine.codeSegmentSize;
|
|
moduleInfo->numRoutines++;
|
|
}
|
|
}
|
|
buildRoutineList(curSymbol->right, moduleInfo);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::getInfo (ModuleInfo* moduleInfo)
|
|
{
|
|
|
|
strcpy(moduleInfo->name, name);
|
|
strcpy(moduleInfo->fileName, ModuleRegistry[handle].fileName);
|
|
|
|
moduleInfo->numRoutines = 0;
|
|
buildRoutineList(ModuleRegistry[handle].moduleIdPtr->defn.info.routine.localSymTable, moduleInfo);
|
|
for (long i = 0; i < moduleInfo->numRoutines; i++)
|
|
moduleInfo->totalCodeSegmentSize += moduleInfo->routineInfo[i].codeSegmentSize;
|
|
|
|
moduleInfo->numStaticVars = ModuleRegistry[handle].numStaticVars;
|
|
moduleInfo->totalSizeStaticVars = ModuleRegistry[handle].totalSizeStaticVars;
|
|
|
|
if (ModuleRegistry[handle].sizeStaticVars)
|
|
{
|
|
long largest = 0;
|
|
for (i = 0; i < moduleInfo->numStaticVars; i++)
|
|
{
|
|
if (ModuleRegistry[handle].sizeStaticVars[i] > ModuleRegistry[handle].sizeStaticVars[largest])
|
|
largest = i;
|
|
}
|
|
moduleInfo->largestStaticVar.size = ModuleRegistry[handle].sizeStaticVars[largest];
|
|
moduleInfo->largestStaticVar.name[0] = NULL;
|
|
}
|
|
else
|
|
{
|
|
moduleInfo->largestStaticVar.size = 0;
|
|
moduleInfo->largestStaticVar.name[0] = NULL;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLModule::destroy (void)
|
|
{
|
|
|
|
if ((id > -1) && ModuleInstanceRegistry)
|
|
{
|
|
//-----------------------------------------------
|
|
// It's on the active registry, so pull it off...
|
|
for (long i = 0; i < NumModuleInstances; i++)
|
|
if (ModuleInstanceRegistry[i] == this)
|
|
{
|
|
ModuleInstanceRegistry[i] = ModuleInstanceRegistry[NumModuleInstances-1];
|
|
ModuleInstanceRegistry[--NumModuleInstances] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (watchManager)
|
|
{
|
|
delete watchManager;
|
|
watchManager = NULL;
|
|
}
|
|
|
|
if (breakPointManager)
|
|
{
|
|
delete breakPointManager;
|
|
breakPointManager = NULL;
|
|
}
|
|
|
|
if (staticData)
|
|
{
|
|
AblStackHeap->Free(staticData);
|
|
staticData = NULL;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
// MISC routines
|
|
//***************************************************************************
|
|
|
|
|
|
void ABLi_saveEnvironment (MemoryStream *stream)
|
|
{
|
|
|
|
*stream << numLibrariesLoaded;
|
|
*stream << NumModulesRegistered;
|
|
*stream << NumModules;
|
|
// ablFile->writeLong(numLibrariesLoaded);
|
|
// ablFile->writeLong(NumModulesRegistered);
|
|
// ablFile->writeLong(NumModules);
|
|
for (long i = 0; i < NumModulesRegistered; i++)
|
|
*stream << ModuleRegistry[i].fileName;
|
|
// ablFile->writeString(ModuleRegistry[i].fileName);
|
|
*stream << 999;
|
|
// ablFile->writeLong(999);
|
|
for (i = 0; i < eternalOffset; i++)
|
|
{
|
|
StackItemPtr dataPtr = (StackItemPtr)stack + i;
|
|
if (EternalVariablesSizes[i] > 0)
|
|
stream->WriteBytes ((MemoryPtr)dataPtr->address, EternalVariablesSizes[i]);
|
|
// ablFile->write((MemoryPtr)dataPtr->address, EternalVariablesSizes[i]);
|
|
else
|
|
stream->WriteBytes ((MemoryPtr)dataPtr, sizeof(StackItem));
|
|
// ablFile->write((MemoryPtr)dataPtr, sizeof(StackItem));
|
|
}
|
|
//blurt, each ai will do this
|
|
#if 0
|
|
for (i = 0; i < NumModules; i++)
|
|
ModuleInstanceRegistry[i]->write(ablFile);
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
void ABLi_loadEnvironment (MemoryStream *stream)
|
|
{
|
|
|
|
// long numLibs = ablFile->readLong();
|
|
// long numModsRegistered = ablFile->readLong();
|
|
// long numMods = ablFile->readLong();
|
|
long numLibs;
|
|
long numModsRegistered;
|
|
long numMods;
|
|
*stream >> numLibs;
|
|
*stream >> numModsRegistered;
|
|
*stream >> numMods;
|
|
|
|
for (long i = 0; i < numLibs; i++)
|
|
{
|
|
unsigned char fileName[1024];
|
|
if (!stream->ReadLine ((char *) &(fileName[0]),1024))
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABLi_loadEnvironment: Unable to read filename [Module %d]", i);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < (numModsRegistered - numLibs); i++)
|
|
{
|
|
unsigned char fileName[1024];
|
|
if (!stream->ReadLine ((char *) &(fileName[0]),1024))
|
|
{
|
|
char err[255];
|
|
sprintf(err, "ABLi_loadEnvironment: Unable to read filename [Module %d]", i);
|
|
ABL_Fatal(0, err);
|
|
}
|
|
}
|
|
#pragma warning (disable : 4189)
|
|
long mark;
|
|
*stream >> mark;
|
|
for (i = 0; i < eternalOffset; i++)
|
|
{
|
|
StackItemPtr dataPtr = (StackItemPtr)stack + i;
|
|
if (EternalVariablesSizes[i] > 0)
|
|
stream->ReadBytes ((MemoryPtr)dataPtr->address, EternalVariablesSizes[i]);
|
|
else
|
|
stream->ReadBytes ((MemoryPtr)dataPtr, sizeof(StackItem));
|
|
}
|
|
#if 0 // each ai will do this themselves
|
|
for (i = 0; i < numMods; i++)
|
|
{
|
|
ABLModulePtr module = NULL;
|
|
module = ModuleInstanceRegistry[i];
|
|
module->read(ablFile);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//***************************************************************************
|
|
|
|
|
|
}
|