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 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 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); } } }
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 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); } } }
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); }