Esempio n. 1
0
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();
}
Esempio n. 2
0
void execOrderReturn (long returnVal) {

	//-----------------------------
	// Assignment to function id...
	StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
	long delta = level - CurRoutineIdPtr->level - 1;
	while (delta-- > 0)
		headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;

	if (CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_STATE) {
		//----------------------------------
		// Return in a state function, so...
		if (debugger)
			debugger->traceDataStore(CurRoutineIdPtr, CurRoutineIdPtr->typePtr, (StackItemPtr)headerPtr, CurRoutineIdPtr->typePtr);
	
		ExitWithReturn = true;
		ExitFromTacOrder = true;

		if (returnVal == 0) {
			//----------------------------------------------------------
			// Use the "eject" code only if called for a failed Order...
			codeSegmentPtr = (char*)ExitStateCodeSegment;
			getCodeToken();
		}
		
		}
	else {
		//-------------------------------------------------------------------------
		// All Order functions (TacticalOrder/GeneralOrder/ActionOrder) must return
		// an integer error code, so we assume the return type is IntegerTypePtr...
		StackItemPtr targetPtr = (StackItemPtr)headerPtr;
		targetPtr->integer = returnVal;

		//----------------------------------------------------------------------
		// Preserve the return value, in case we need it for the calling user...
		memcpy(&returnValue, targetPtr, sizeof(StackItem));

		if (debugger)
			debugger->traceDataStore(CurRoutineIdPtr, CurRoutineIdPtr->typePtr, (StackItemPtr)headerPtr, CurRoutineIdPtr->typePtr);
	
		ExitWithReturn = true;
		ExitFromTacOrder = true;

		if (returnVal == 0) {
			//----------------------------------------------------------
			// Use the "eject" code only if called for a failed Order...
			codeSegmentPtr = (char*)ExitOrderCodeSegment;
			getCodeToken();
		}
	}
}
Esempio n. 3
0
void execAssignmentStatement(SymTableNodePtr idPtr)
{
	StackItemPtr targetPtr;
	TypePtr targetTypePtr;
	TypePtr expressionTypePtr;
	//--------------------------
	// Assignment to variable...
	targetTypePtr = execVariable(idPtr, USE_TARGET);
	targetPtr = (StackItemPtr)tos->address;
	//------------------------------
	// Pop off the target address...
	pop();
	//------------------------
	// Pop the size, if nec...
	//if (targetTypePtr->form == FRM_ARRAY)
	//	pop();
	//---------------------------------------------------------------
	// Routine execExpression() leaves the expression value on top of
	// stack...
	getCodeToken();
	expressionTypePtr = execExpression();
	//--------------------------
	// Now, do the assignment...
	if((targetTypePtr == RealTypePtr) && (expressionTypePtr == IntegerTypePtr))
	{
		//-------------------------
		// integer assigned to real
		targetPtr->real = (float)(tos->integer);
	}
	else if(targetTypePtr->form == FRM_ARRAY)
	{
		//-------------------------
		// Copy the array/record...
		PSTR dest = (PSTR)targetPtr;
		PSTR src = tos->address;
		int32_t size = targetTypePtr->size;
		memcpy(dest, src, size);
	}
	else if((targetTypePtr == IntegerTypePtr) || (targetTypePtr->form == FRM_ENUM))
	{
		//------------------------------------------------------
		// Range check assignment to integer or enum subrange...
		targetPtr->integer = tos->integer;
	}
	else if(targetTypePtr == CharTypePtr)
		targetPtr->byte = tos->byte;
	else
	{
		//-----------------------
		// Assign real to real...
		targetPtr->real = tos->real;
	}
	//-----------------------------
	// Grab the expression value...
	pop();
	if(debugger)
		debugger->traceDataStore(idPtr, idPtr->typePtr, targetPtr, targetTypePtr);
}
Esempio n. 4
0
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);
		}
	}
}
Esempio n. 5
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);
}
Esempio n. 6
0
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);
	}
}
Esempio n. 7
0
void routineEntry(SymTableNodePtr routineIdPtr)
{
	if(debugger)
		debugger->traceRoutineEntry(routineIdPtr);
	memset(&returnValue, 0, sizeof(StackItem));
	//------------------------------
	// Switch to new code segment...
	codeSegmentPtr = routineIdPtr->defn.info.routine.codeSegment;
	//----------------------------------------------
	// Allocate local variables onto system stack...
	for(SymTableNodePtr varIdPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.locals);
			varIdPtr != nullptr;
			varIdPtr = varIdPtr->next)
		if(varIdPtr->defn.info.data.varType == VAR_TYPE_NORMAL)
			allocLocal((TypePtr)(varIdPtr->typePtr));
}
Esempio n. 8
0
TypePtr execConstant(SymTableNodePtr idPtr)
{
	TypePtr typePtr = idPtr->typePtr;
	if ((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM))
		pushInteger(idPtr->defn.info.constant.value.integer);
	else if (typePtr == RealTypePtr)
		pushReal(idPtr->defn.info.constant.value.real);
	else if (typePtr == CharTypePtr)
		pushInteger(idPtr->defn.info.constant.value.character);
	else if (typePtr->form == FRM_ARRAY)
		pushAddress(idPtr->defn.info.constant.value.stringPtr);
	if (debugger)
		debugger->traceDataFetch(idPtr, typePtr, tos);
	getCodeToken();
	return (typePtr);
}
Esempio n. 9
0
void routineExit(SymTableNodePtr routineIdPtr)
{
	if(debugger)
		debugger->traceRoutineExit(routineIdPtr);
	//-----------------------------------------
	// De-alloc parameters & local variables...
	SymTableNodePtr idPtr;
	for(idPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.params);
			idPtr != nullptr;
			idPtr = idPtr->next)
		freeLocal(idPtr);
	for(idPtr = (SymTableNodePtr)(routineIdPtr->defn.info.routine.locals);
			idPtr != nullptr;
			idPtr = idPtr->next)
		if(idPtr->defn.info.data.varType == VAR_TYPE_NORMAL)
			freeLocal(idPtr);
	StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
	codeSegmentPtr = headerPtr->returnAddress.address;
	if(routineIdPtr->typePtr == nullptr)
		tos = stackFrameBasePtr - 1;
	else
		tos = stackFrameBasePtr;
	stackFrameBasePtr = (StackItemPtr)headerPtr->dynamicLink.address;
}
Esempio n. 10
0
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();
}
Esempio n. 11
0
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));
}
Esempio n. 12
0
int32_t ABLModule::execute(ABLParamPtr moduleParamList, SymTableNodePtr functionIdPtr)
{
    CurModule = this;
    if(debugger)
        debugger->setModule(this);
    //--------------------------
    // Execute the ABL module...
    SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr;
    if(moduleIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM)
        CurFSM = this;
    else
        CurFSM = nullptr;
    NumStateTransitions = 0;
    //--------------------------------------------
    // Point to this module's static data space...
    StaticDataPtr = staticData;
    OrderCompletionFlags = orderCallFlags;
    //---------------------------------
    // Init some important variables...
    CurModuleIdPtr = nullptr;
    CurRoutineIdPtr = nullptr;
    FileNumber = -1;
    errorCount = 0;
    execStatementCount = 0;
    NumExecutions++;
    NewStateSet = false;
    //------------------
    // 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(nullptr);
    //----------------
    // Dynamic Link...
    pushAddress(nullptr);
    //------------------
    // Return Address...
    pushAddress(nullptr);
    //initDebugger();
    //----------
    // Run it...
    if(moduleParamList)
    {
        //------------------------------------------------------------------------------
        // NOTE: Currently, parameter passing of arrays is not functioning. This MUST be
        // done...
        int32_t curParam = 0;
        for(SymTableNodePtr formalIdPtr = (SymTableNodePtr)(moduleIdPtr->defn.info.routine.params);
                formalIdPtr != nullptr;
                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...
                    int32_t size = formalTypePtr->size;
                    PSTR dest = (PSTR)ABLStackMallocCallback((size_t)size);
                    if(!dest)
                    {
                        char err[255];
                        sprintf(err, "ABL: Unable to AblStackHeap->malloc array parameter [Module %d]", id);
                        ABL_Fatal(0, err);
                    }
                    PSTR src = tos->address;
                    PSTR 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;
    ::executeChild(moduleIdPtr, functionIdPtr);
    memcpy(&returnVal, &returnValue, sizeof(StackItem));
    //-----------
    // Summary...
    return(execStatementCount);
}
Esempio n. 13
0
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);
}
Esempio n. 14
0
void execStdReturn (void) {

	memset(&returnValue, 0, sizeof(StackItem));
	if (CurRoutineIdPtr->typePtr) {
		//-----------------------------
		// Assignment to function id...
		StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
		long delta = level - CurRoutineIdPtr->level - 1;
		while (delta-- > 0)
			headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;

		StackItemPtr targetPtr = (StackItemPtr)headerPtr;
		TypePtr targetTypePtr = (TypePtr)(CurRoutineIdPtr->typePtr);
		getCodeToken();

		//---------------------------------------------------------------
		// Routine execExpression() leaves the expression value on top of
		// stack...
		getCodeToken();
		TypePtr expressionTypePtr = execExpression();

		//--------------------------
		// Now, do the assignment...
		if ((targetTypePtr == RealTypePtr) && (expressionTypePtr == IntegerTypePtr)) {
			//-------------------------
			// integer assigned to real
			targetPtr->real = (float)(tos->integer);
			}
		else if (targetTypePtr->form == FRM_ARRAY) {
			//-------------------------
			// Copy the array/record...
			char* dest = (char*)targetPtr;
			char* src = tos->address;
			long size = targetTypePtr->size;
			memcpy(dest, src, size);
			}
		else if ((targetTypePtr == IntegerTypePtr) || (targetTypePtr->form == FRM_ENUM)) {
			//------------------------------------------------------
			// Range check assignment to integer or enum subrange...
			targetPtr->integer = tos->integer;
			}
		else {
			//-----------------------
			// Assign real to real...
			targetPtr->real = tos->real;
		}

		//-----------------------------
		// Grab the expression value...
		pop();

		//----------------------------------------------------------------------
		// Preserve the return value, in case we need it for the calling user...
		memcpy(&returnValue, targetPtr, sizeof(StackItem));
		
		if (debugger)
			debugger->traceDataStore(CurRoutineIdPtr, CurRoutineIdPtr->typePtr, targetPtr, targetTypePtr);
	}

	//-----------------------
	// Grab the semi-colon...
	getCodeToken();

	if (CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_ORDER)
		codeSegmentPtr = (char*)ExitOrderCodeSegment;
	else if (CurRoutineIdPtr->defn.info.routine.flags & ROUTINE_FLAG_STATE)
		codeSegmentPtr = (char*)ExitStateCodeSegment;
	else
		codeSegmentPtr = (char*)ExitRoutineCodeSegment;
	ExitWithReturn = true;

	getCodeToken();
}