예제 #1
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));
}
예제 #2
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);
}