void execStdGetModule (void) { //---------------------------------------------------------- // Return the handle of the current module being executed... char* curBuffer = ABLi_popCharPtr(); char* fsmBuffer = ABLi_popCharPtr(); strcpy(curBuffer, CurModule->getFileName()); strcpy(fsmBuffer, CurFSM ? CurFSM->getFileName() : "none"); ABLi_pushInteger(CurModuleHandle); }
void execStdPrint (void) { //--------------------------- // Grab the opening LPAREN... getCodeToken(); //---------------------------- // Get parameter expression... getCodeToken(); TypePtr paramTypePtr = execExpression(); char buffer[20]; char* s = buffer; if (paramTypePtr == IntegerTypePtr) sprintf(buffer, "%d", tos->integer); else if (paramTypePtr == BooleanTypePtr) sprintf(buffer, "%s", tos->integer ? "true" : "false"); else if (paramTypePtr == CharTypePtr) sprintf(buffer, "%c", tos->byte); else if (paramTypePtr == RealTypePtr) sprintf(buffer, "%.4f", tos->real); else if ((paramTypePtr->form == FRM_ARRAY) && (paramTypePtr->info.array.elementTypePtr == CharTypePtr)) s = (char*)tos->address; pop(); if (debugger) { char message[512]; sprintf(message, "PRINT: \"%s\"", s); debugger->print(message); sprintf(message, " MODULE %s", CurModule->getName()); debugger->print(message); sprintf(message, " FILE %s", CurModule->getSourceFile(FileNumber)); debugger->print(message); sprintf(message, " LINE %d", execLineNumber); debugger->print(message); } /* else if (TACMAP) { aChatWindow* chatWin = TACMAP->getChatWindow(); if (chatWin) chatWin->processChatString(0, s, -1); else { #ifdef _DEBUG OutputDebugString(s); #endif } } */ else { #ifdef _DEBUG ABLDebugPrintCallback(s); #endif } //----------------------- // Grab closing RPAREN... getCodeToken(); }
void execStdSetState (void) { unsigned long stateHandle = ABLi_popInteger(); if (stateHandle > 0) { SymTableNodePtr stateFunction = ModuleRegistry[CurFSM->getHandle()].stateHandles[stateHandle].state; CurFSM->setPrevState(CurFSM->getState()); CurFSM->setState(stateFunction); sprintf(SetStateDebugStr, "%s:%s, line %d", CurFSM->getFileName(), stateFunction->name, execLineNumber); NewStateSet = true; } }
void execStdGetStateHandle (void) { char* name = ABLi_popCharPtr(); long stateHandle = CurFSM->findStateHandle(_strlwr(name)); ABLi_pushInteger(stateHandle); }
void execStdResetOrders (void) { long scope = ABLi_popInteger(); if (scope == 0) CurModule->resetOrderCallFlags(); else if (scope == 1) { long startIndex = CurRoutineIdPtr->defn.info.routine.orderCallIndex; long endIndex = startIndex + CurRoutineIdPtr->defn.info.routine.numOrderCalls; for (long i = startIndex; i < endIndex; i++) { unsigned char orderDWord = (unsigned char)(i / 32); unsigned char orderBitMask = (unsigned char)(i % 32); CurModule->clearOrderCallFlag(orderDWord, orderBitMask); } } }
void execTransBackStatement(void) { SymTableNodePtr prevState = CurModule->getPrevState(); if(!prevState) runtimeError(ABL_ERR_RUNTIME_NULL_PREVSTATE); transState(prevState); getCodeToken(); }
void execStdAssert (void) { //---------------------------------------------------------------------- // // ASSERT function: // // If the debugger is active, this immediately jumps into debug mode // if expression is FALSE. Otherwise, the assert statement is ignored // unless the #debug directive has been issued in the module. If // so, a fatal occurs and exits the game (displaying the // string passed in). // // PARAMS: boolean expression // // integer assert code to display // // char[] message // // RETURN: none // //---------------------------------------------------------------------- long expression = ABLi_popInteger(); long code = ABLi_popInteger(); char* s = ABLi_popCharPtr(); if (!expression) { char message[512]; if (debugger) { sprintf(message, "ASSERT: [%d] \"%s\"", code, s); debugger->print(message); sprintf(message, " MODULE (%d) %s", CurModule->getId(), CurModule->getName()); debugger->print(message); sprintf(message, " FILE %s", CurModule->getSourceFile(FileNumber)); debugger->print(message); sprintf(message, " LINE %d", execLineNumber); debugger->print(message); debugger->debugMode(); } else { sprintf(message, "ABL ASSERT: [%d] %s", code, s); ABL_Fatal(0, message); } } }
TypePtr execStandardRoutineCall (SymTableNodePtr routineIdPtr, bool skipOrder) { long key = routineIdPtr->defn.info.routine.key; switch (key) { case RTN_RETURN: execStdReturn(); return(NULL); case RTN_PRINT: execStdPrint(); return(NULL); case RTN_CONCAT: return(execStdConcat()); default: { if (key >= NumStandardFunctions) { char err[255]; sprintf(err, " ABL: Undefined ABL RoutineKey in %s:%d", CurModule->getName(), execLineNumber); ABL_Fatal(0, err); } if (FunctionInfoTable[key].numParams > 0) getCodeToken(); SkipOrder = skipOrder; if (FunctionCallbackTable[key]) (*FunctionCallbackTable[key])(); else { char err[255]; sprintf(err, " ABL: Undefined ABL RoutineKey %d in %s:%d", key, CurModule->getName(), execLineNumber); ABL_Fatal(key,err); } getCodeToken(); switch (FunctionInfoTable[key].returnType) { case RETURN_TYPE_NONE: return(NULL); case RETURN_TYPE_INTEGER: return(IntegerTypePtr); case RETURN_TYPE_REAL: return(RealTypePtr); case RETURN_TYPE_BOOLEAN: return(BooleanTypePtr); } } } return(NULL); }
void execStdGetFunctionHandle (void) { char* name = ABLi_popCharPtr(); SymTableNodePtr function = CurModule->findFunction(name, false); if (function) ABLi_pushInteger((unsigned long)function); else ABLi_pushInteger(0); }
void runtimeError (long errCode) { char message[512]; if (debugger) { sprintf(message, "RUNTIME ERROR: [%d] %s", errCode, runtimeErrorMessages[errCode]); debugger->print(message); sprintf(message, "MODULE %s", CurModule->getName()); debugger->print(message); if (FileNumber > -1) sprintf(message, "FILE %s", CurModule->getSourceFile(FileNumber)); else sprintf(message, "FILE %s: unavailable"); debugger->print(message); sprintf(message, "LINE %d", execLineNumber); debugger->print(message); debugger->debugMode(); } sprintf(message, "ABL RUNTIME ERROR %s [line %d] - (type %d) %s\n", (FileNumber > -1) ? CurModule->getSourceFile(FileNumber) : "unavailable", execLineNumber, errCode, runtimeErrorMessages[errCode]); ABL_Fatal(-ABL_ERR_RUNTIME_ABORT, message); }
void execStdFatal (void) { //---------------------------------------------------------------------- // // FATAL function: // // If the debugger is active, this immediately jumps into debug mode. // Otherwise, it causes a fatal and exits the game (displaying the // string passed in). // // PARAMS: integer fatal code to display // // char[] message // // RETURN: none // //---------------------------------------------------------------------- long code = ABLi_popInteger(); char* s = ABLi_popCharPtr(); char message[512]; if (debugger) { sprintf(message, "FATAL: [%d] \"%s\"", code, s); debugger->print(message); sprintf(message, " MODULE (%d) %s", CurModule->getId(), CurModule->getName()); debugger->print(message); sprintf(message, " FILE %s", CurModule->getSourceFile(FileNumber)); debugger->print(message); sprintf(message, " LINE %d", execLineNumber); debugger->print(message); debugger->debugMode(); } else { sprintf(message, "ABL FATAL: [%d] %s", code, s); ABL_Fatal(0, s); } }
void execute(SymTableNodePtr routineIdPtr) { SymTableNodePtr thisRoutineIdPtr = CurRoutineIdPtr; CurRoutineIdPtr = routineIdPtr; routineEntry(routineIdPtr); //---------------------------------------------------- // Now, search this module for the function we want... if(CallModuleInit) { CallModuleInit = false; SymTableNodePtr initFunctionIdPtr = searchSymTable("init", ModuleRegistry[CurModule->getHandle()].moduleIdPtr->defn.info.routine.localSymTable); if(initFunctionIdPtr) { execRoutineCall(initFunctionIdPtr, false); //------------------------------------------------------------------------- // Since we're calling the function directly, we need to compensate for the // codeSegmentPtr being incremented by 1 in the normal execRoutineCall... codeSegmentPtr--; } } if(routineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM) { NewStateSet = true; static char stateList[60][256]; strcpy(SetStateDebugStr, "--"); while(NewStateSet) { NumStateTransitions++; sprintf(stateList[NumStateTransitions], "%s (%s)", CurModule->getState()->name, SetStateDebugStr); if(NumStateTransitions == 50) { UserFile* userFile = UserFile::getNewFile(); char errStr[512]; if(userFile) { int32_t err = userFile->open("endless.log"); if(!err) { //char s[1024]; //sprintf(s, "Current Date: %s\n", GetTime()); //userFile->write(s); userFile->write(ModuleRegistry[CurModule->getHandle()].fileName); for(size_t i = 1; i < 51; i++) userFile->write(stateList[i]); userFile->write(" "); if(ABLEndlessStateCallback) (*ABLEndlessStateCallback)(userFile); userFile->close(); } } sprintf(errStr, " ABL endless state loop in %s [%s:%s] ", ModuleRegistry[CurModule->getHandle()].fileName, CurModule->getState()->name, CurModule->getPrevState()->name); #if 0 ABL_Fatal(NumStateTransitions, errStr); #else NewStateSet = false; #endif } else { NewStateSet = false; SymTableNodePtr curState = CurModule->getState(); if(!curState) ABL_Fatal(0, " ABL.execute: nullptr state in FSM "); execRoutineCall(curState, false); codeSegmentPtr--; } //--------------------------------------------- // In case we exited with a return statement... ExitWithReturn = false; ExitFromTacOrder = false; } } else { getCodeToken(); execStatement(); //--------------------------------------------- // In case we exited with a return statement... ExitWithReturn = false; ExitFromTacOrder = false; } routineExit(routineIdPtr); CurRoutineIdPtr = thisRoutineIdPtr; }
void execStatement(void) { if(codeToken == TKN_STATEMENT_MARKER) { execLineNumber = getCodeStatementMarker(); execStatementCount++; statementStartPtr = codeSegmentPtr; if(debugger) debugger->traceStatementExecution(); getCodeToken(); } switch(codeToken) { case TKN_IDENTIFIER: { SymTableNodePtr idPtr = getCodeSymTableNodePtr(); ABL_Assert(idPtr != nullptr, 0, " oops "); if(idPtr->defn.key == DFN_FUNCTION) { bool skipOrder = false; uint8_t orderDWord = 0; uint8_t orderBitMask = 0; if((idPtr->defn.info.routine.flags & ROUTINE_FLAG_ORDER) && CurModule->getOrderCallFlags()) { orderDWord = getCodeByte(); orderBitMask = getCodeByte(); skipOrder = !CurModule->isLibrary() && CurModule->getOrderCallFlag(orderDWord, orderBitMask); } TypePtr returnType = execRoutineCall(idPtr, skipOrder); if(idPtr->defn.info.routine.flags & ROUTINE_FLAG_ORDER) { if(AutoReturnFromOrders) { //----------------------------------------------------------------- // We called an Order function, and we're in an Orders/State block, // so do we continue the flow of orders or stop here? int32_t returnVal = tos->integer; pop(); if(returnVal == 0) execOrderReturn(returnVal); else if(CurModule->getOrderCallFlags()) { CurModule->setOrderCallFlag(orderDWord, orderBitMask); } } } else if(returnType) { //------------------------------------------ // In case this routine returns a value, pop // the return value off the stack... pop(); } } else execAssignmentStatement(idPtr); } break; case TKN_CODE: { bool wasAutoReturnFromOrders = AutoReturnFromOrders; AutoReturnFromOrders = ((CurRoutineIdPtr->defn.info.routine.flags & (ROUTINE_FLAG_ORDER + ROUTINE_FLAG_STATE)) != 0); getCodeToken(); TokenCodeType endToken = TKN_END_FUNCTION; if(CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_ORDER) endToken = TKN_END_ORDER; else if(CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_STATE) endToken = TKN_END_STATE; TokenCodeType endTokenFinal = TKN_END_MODULE; if(CurLibrary) endTokenFinal = TKN_END_LIBRARY; else if(CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM) endTokenFinal = TKN_END_FSM; while((codeToken != endToken) && (codeToken != endTokenFinal) && !NewStateSet) execStatement(); if(NewStateSet) return; getCodeToken(); AutoReturnFromOrders = wasAutoReturnFromOrders; } break; case TKN_FOR: execForStatement(); break; case TKN_IF: execIfStatement(); break; case TKN_REPEAT: execRepeatStatement(); break; case TKN_WHILE: execWhileStatement(); break; case TKN_SWITCH: execSwitchStatement(); break; case TKN_TRANS: execTransStatement(); break; case TKN_TRANS_BACK: execTransBackStatement(); break; case TKN_SEMICOLON: case TKN_ELSE: case TKN_UNTIL: break; default: //runtimeError(ABL_ERR_RUNTIME_UNIMPLEMENTED_FEATURE); NODEFAULT; } while(codeToken == TKN_SEMICOLON) getCodeToken(); }
void execActualParams(SymTableNodePtr routineIdPtr) { //-------------------------- // Execute the parameters... for(SymTableNodePtr formalIdPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.params); formalIdPtr != nullptr; formalIdPtr = formalIdPtr->next) { TypePtr formalTypePtr = (TypePtr)(formalIdPtr->typePtr); getCodeToken(); if(formalIdPtr->defn.key == DFN_VALPARAM) { //------------------- // pass by value parameter... TypePtr actualTypePtr = execExpression(); if((formalTypePtr == RealTypePtr) && (actualTypePtr == IntegerTypePtr)) { //--------------------------------------------- // Real formal parameter, but integer actual... tos->real = (float)(tos->integer); } //---------------------------------------------------------- // 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... int32_t size = formalTypePtr->size; PSTR src = tos->address; PSTR dest = (PSTR)ABLStackMallocCallback((size_t)size); if(!dest) { char err[255]; sprintf(err, " ABL: Unable to AblStackHeap->malloc actual array param in module %s)", CurModule->getName()); ABL_Fatal(0, err); } PSTR savePtr = dest; memcpy(dest, src, size); tos->address = savePtr; } } else { //------------------------------- // pass by reference parameter... SymTableNodePtr idPtr = getCodeSymTableNodePtr(); execVariable(idPtr, USE_REFPARAM); } } }
TypePtr execDeclaredRoutineCall(SymTableNodePtr routineIdPtr, bool skipOrder) { if(skipOrder) { StackItemPtr curStackFrameBase = tos; //---------------------------------------- // Push parameter values onto the stack... getCodeToken(); if(codeToken == TKN_LPAREN) { execActualParams(routineIdPtr); getCodeToken(); } getCodeToken(); tos = curStackFrameBase; pushInteger(1); return((TypePtr)(routineIdPtr->typePtr)); } int32_t oldLevel = level; // level of caller int32_t newLevel = routineIdPtr->level + 1; // level of callee CallStackLevel++; //------------------------------------------- // First, set up the stack frame of callee... StackItemPtr newStackFrameBasePtr = tos + 1; bool isLibraryCall = (routineIdPtr->library && (routineIdPtr->library != CurRoutineIdPtr->library)); if(isLibraryCall) pushStackFrameHeader(-1, -1); else pushStackFrameHeader(oldLevel, newLevel); //---------------------------------------- // Push parameter values onto the stack... getCodeToken(); if(codeToken == TKN_LPAREN) { execActualParams(routineIdPtr); getCodeToken(); } //------------------------------------------------- // Set the return address in the new stack frame... level = newLevel; stackFrameBasePtr = newStackFrameBasePtr; StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr; headerPtr->returnAddress.address = codeSegmentPtr - 1; //--------------------------------------------------------- // If we're calling a library function, we need to set some // module-specific info... ABLModulePtr PrevModule = nullptr; if(isLibraryCall) { PrevModule = CurModule; CurModule = routineIdPtr->library; CurModuleHandle = CurModule->getHandle(); if(debugger) debugger->setModule(CurModule); StaticDataPtr = CurModule->getStaticData(); CallModuleInit = !CurModule->getInitCalled(); CurModule->setInitCalled(true); // routineEntry(ModuleRegistry[CurModule->getHandle()].moduleIdPtr); } if(ProfileLog) { int32_t functionStartTime = ABLGetTimeCallback(); execute(routineIdPtr); int32_t functionExecTime = ABLGetTimeCallback() - functionStartTime; if(functionExecTime > ProfileLogFunctionTimeLimit) { char s[512]; sprintf_s(s, _countof(s), "[%08d] ", NumExecutions); for(size_t i = 0; i < CallStackLevel; i++) strcat(s, " "); char s1[512]; sprintf_s(s1, _countof(s1), "%s (%d)\n", routineIdPtr->name, functionExecTime); strcat(s, s1); ABL_AddToProfileLog(s); } } else execute(routineIdPtr); //---------------------------------------------------------------- // If we're calling a library function, reset some module-specific // info... if(isLibraryCall) { // routineExit(ModuleRegistry[CurModule->getHandle()].moduleIdPtr); CurModule = PrevModule; CurModuleHandle = CurModule->getHandle(); if(debugger) debugger->setModule(CurModule); StaticDataPtr = CurModule->getStaticData(); } //------------------------------------------------------- // Return from the callee, and grab the first token after // the return... level = oldLevel; getCodeToken(); CallStackLevel--; return((TypePtr)(routineIdPtr->typePtr)); }
int32_t ABLModule::init(int32_t moduleHandle) { if(moduleHandle == -1) { //---------- // Clean up! return(-1); } id = NumModules++; handle = moduleHandle; staticData = nullptr; int32_t numStatics = ModuleRegistry[handle].numStaticVars; if(numStatics) { staticData = (StackItemPtr)ABLStackMallocCallback(sizeof(StackItem) * numStatics); if(!staticData) { char err[255]; sprintf(err, "ABL: Unable to AblStackHeap->malloc staticData [Module %d]", id); ABL_Fatal(0, err); } int32_t* sizeList = ModuleRegistry[handle].sizeStaticVars; for(size_t i = 0; i < numStatics; i++) if(sizeList[i] > 0) { staticData[i].address = (PSTR)ABLStackMallocCallback(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; } if(ModuleRegistry[handle].numOrderCalls) { int32_t numLongs = 1 + ModuleRegistry[handle].numOrderCalls / 32; orderCallFlags = (uint32_t*)ABLStackMallocCallback(sizeof(uint32_t) * numLongs); if(!orderCallFlags) { char err[255]; sprintf(err, "ABL: Unable to AblStackHeap->malloc orderCallFlags [Module %d]", id); ABL_Fatal(0, err); } for(size_t i = 0; i < numLongs; i++) orderCallFlags[i] = 0; } 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 "); int32_t result = watchManager->init(MaxWatchesPerModule); if(result != ABL_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 != ABL_NO_ERR) ABL_Fatal(0, " Unable to AblStackHeap->malloc BreakPointManager "); } if(ModuleRegistry[handle].moduleIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM) { //-------------------------------- // Always starts in START state... SymTableNodePtr startState = searchSymTable("start", ModuleRegistry[handle].moduleIdPtr->defn.info.routine.localSymTable); if(!startState) { char err[255]; sprintf(err, "ABL: FSM has no Start state [%s]", CurModule->getName()); ABL_Fatal(0, err); } prevState = nullptr; state = startState; } //-------------------- // Can this ever fail? return(ABL_NO_ERR); }
void ABLi_loadEnvironment(ABLFile* ablFile, bool malloc) { int32_t numLibs = ablFile->readLong(); int32_t numModsRegistered = ablFile->readLong(); int32_t numMods = ablFile->readLong(); int32_t i; for(i = 0; i < numLibs; i++) { uint8_t fileName[1024]; int32_t result = ablFile->readString(fileName); if(!result) { char err[255]; sprintf(err, "ABLi_loadEnvironment: Unable to read filename [Module %d]", i); ABL_Fatal(0, err); } if(malloc) { int32_t numErrors, numLinesProcessed; ABLModulePtr library = ABLi_loadLibrary((PSTR)fileName, &numErrors, &numLinesProcessed, nullptr, false, false); if(!library) { char err[255]; sprintf(err, "ABLi_loadEnvironment: Unable to load library [Module %d]", i); ABL_Fatal(0, err); } } } for(i = 0; i < (numModsRegistered - numLibs); i++) { uint8_t fileName[1024]; int32_t result = ablFile->readString(fileName); if(!result) { char err[255]; sprintf(err, "ABLi_loadEnvironment: Unable to read filename [Module %d]", i); ABL_Fatal(0, err); } int32_t numErrors, numLinesProcessed; if(malloc) { int32_t handle = ABLi_preProcess((PSTR)fileName, &numErrors, &numLinesProcessed); if(handle < 0) { char err[255]; sprintf(err, "ABLi_loadEnvironment: Unable to preprocess [Module %d]", i); ABL_Fatal(0, err); } } } //int32_t mark = ablFile->readLong(); for(i = 0; i < eternalOffset; i++) { StackItemPtr dataPtr = (StackItemPtr)stack + i; if(EternalVariablesSizes[i] > 0) ablFile->read((puint8_t)dataPtr->address, EternalVariablesSizes[i]); else ablFile->read((puint8_t)dataPtr, sizeof(StackItem)); } for(i = 0; i < numLibs; i++) { ABLModulePtr library = LibraryInstanceRegistry[i]; library->read(ablFile); } for(i = 0; i < (numMods - numLibs); i++) { ABLModulePtr module = nullptr; if(malloc) module = new ABLModule; else module = ModuleInstanceRegistry[numLibs + i]; module->read(ablFile); } }
TypePtr execVariable(SymTableNodePtr idPtr, UseType use) { TypePtr typePtr = (TypePtr)(idPtr->typePtr); // First, point to the variable's stack item. If the variable's scope // level is less than the current scope level, follow the static links // to the proper stack frame base... StackItemPtr dataPtr = nullptr; StackItem tempStackItem; switch (idPtr->defn.info.data.varType) { case VAR_TYPE_NORMAL: { StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr; int32_t delta = level - idPtr->level; while (delta-- > 0) headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address; dataPtr = (StackItemPtr)headerPtr + idPtr->defn.info.data.offset; } break; case VAR_TYPE_ETERNAL: dataPtr = (StackItemPtr)stack + idPtr->defn.info.data.offset; break; case VAR_TYPE_STATIC: //--------------------------------------------------------- // If we're referencing a library's static variable, we may // need to shift to its static data space temporarily... if (idPtr->library && (idPtr->library != CurModule)) StaticDataPtr = idPtr->library->getStaticData(); dataPtr = (StackItemPtr)StaticDataPtr + idPtr->defn.info.data.offset; if (idPtr->library && (idPtr->library != CurModule)) StaticDataPtr = CurModule->getStaticData(); break; case VAR_TYPE_REGISTERED: tempStackItem.address = (PSTR)idPtr->defn.info.data.registeredData; dataPtr = &tempStackItem; break; } //--------------------------------------------------------------- // If it's a scalar or enumeration reference parameter, that item // points to the actual item... if (idPtr->defn.key == DFN_REFPARAM) if (typePtr->form != FRM_ARRAY) /* && (typePtr->form != FRM_RECORD)*/ dataPtr = (StackItemPtr)dataPtr->address; ABL_Assert(dataPtr != nullptr, 0, " ABL.execVariable(): dataPtr is nullptr "); //----------------------------------------------------- // Now, push the address of the variable's data area... if ((typePtr->form == FRM_ARRAY) /*|| (typePtr->form == FRM_RECORD)*/) { // pushInteger(typePtr->size); pushAddress((Address)dataPtr->address); } else if (idPtr->defn.info.data.varType == VAR_TYPE_REGISTERED) pushAddress((Address)dataPtr->address); else pushAddress((Address)dataPtr); //----------------------------------------------------------------------------------- // If there is a subscript (or field identifier, if records are being used // in ABL) then modify the address to point to the proper element of the // array (or record)... getCodeToken(); while ((codeToken == TKN_LBRACKET) /*|| (codeTOken == TKN_PERIOD)*/) { // if (codeToken == TKN_LBRACKET) typePtr = execSubscripts(typePtr); // else if (codeToken == TKN_PERIOD) // typePtr = execField(typePtr); } //------------------------------------------------------------ // Leave the modified address on the top of the stack if: // a) it's an assignment target; // b) it reresents a parameter passed by reference; // c) it's the address of an array or record; // Otherwise, replace the address with the value it points to. if ((use != USE_TARGET) && (use != USE_REFPARAM) && (typePtr->form != FRM_ARRAY)) { if ((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM)) { tos->integer = *((int32_t*)tos->address); } else if (typePtr == CharTypePtr) tos->byte = *((PSTR)tos->address); else tos->real = *((float*)tos->address); } if (debugger) { if ((use != USE_TARGET) && (use != USE_REFPARAM)) { if (typePtr->form == FRM_ARRAY) debugger->traceDataFetch(idPtr, typePtr, (StackItemPtr)tos->address); else debugger->traceDataFetch(idPtr, typePtr, tos); } } return (typePtr); }
void execStdGetCurrentStateHandle (void) { long stateHandle = CurFSM->getStateHandle(); ABLi_pushInteger(stateHandle); }