//*************************************************************************** // // ABLENV.CPP // //*************************************************************************** #include "MW4Headers.hpp" #include #include #include #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 //*************************************************************************** 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;iFree(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 } //*************************************************************************** }