Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
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.
2026-06-24 21:28:16 -05:00

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
}
//***************************************************************************
}