Example #1
0
int32_t Debugger::sprintSimpleValue(PSTR dest, SymTableNodePtr symbol)
{
	//--------------------------------------------------------------------
	// This code is adapted from execVariable(). If that function changes,
	// this better too!
	TypePtr	typePtr = (TypePtr)(symbol->typePtr);
	if(symbol->defn.key == DFN_CONST)
	{
		if(typePtr == IntegerTypePtr)
			sprintf(dest, "%d", symbol->defn.info.constant.value.integer);
		else if(typePtr == CharTypePtr)
			sprintf(dest, "%c", symbol->defn.info.constant.value.character);
		else
			sprintf(dest, "%.4f", symbol->defn.info.constant.value.real);
	}
	else
	{
		//--------------------------------------------------------------------
		// 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;
		switch(symbol->defn.info.data.varType)
		{
			case VAR_TYPE_NORMAL:
			{
				StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
				int32_t delta = level - symbol->level;
				while(delta-- > 0)
					headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;
				dataPtr = (StackItemPtr)headerPtr + symbol->defn.info.data.offset;
			}
			break;
			case VAR_TYPE_ETERNAL:
				dataPtr = (StackItemPtr)stack + symbol->defn.info.data.offset;
				break;
			case VAR_TYPE_STATIC:
				dataPtr = (StackItemPtr)StaticDataPtr + symbol->defn.info.data.offset;
				break;
		}
		//---------------------------------------------------------------
		// If it's a scalar or enumeration reference parameter, that item
		// points to the actual item...
		if((symbol->defn.key == DFN_REFPARAM) && (typePtr->form != FRM_ARRAY)/* && (typePtr->form != FRM_RECORD)*/)
			dataPtr = (StackItemPtr)dataPtr->address;
		if((typePtr->form != FRM_ARRAY) /*&& (typePtr->form != FRM_RECORD)*/)
		{
			ABL_Assert(dataPtr != nullptr, 0, " Debugger.sprintSimpleValue(): dataPtr is nullptr ");
			if((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM))
				sprintf(dest, "%d", *((int32_t*)dataPtr));
			else if(typePtr == CharTypePtr)
				sprintf(dest, "\"%c\"", *((PSTR)dataPtr));
			else
				sprintf(dest, "%.4f", *((float*)dataPtr));
		}
		else
			sprintf(dest, "ARRAY");
	}
	return(ABL_NO_ERR);
}
Example #2
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();
}
Example #3
0
int32_t Debugger::sprintArrayValue(PSTR dest, SymTableNodePtr symbol, PSTR subscriptString)
{
	//--------------------------------------------------------------------
	// This code is adapted from execVariable(). If that function changes,
	// this better too!
	//--------------------------------------------------------------------
	// 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...
	if(symbol->defn.key == DFN_CONST)
		sprintf(dest, "\"%s\"", symbol->defn.info.constant.value.stringPtr);
	else
	{
		StackItemPtr dataPtr = nullptr;
		switch(symbol->defn.info.data.varType)
		{
			case VAR_TYPE_NORMAL:
			{
				StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr;
				int32_t delta = level - symbol->level;
				while(delta-- > 0)
					headerPtr = (StackFrameHeaderPtr)headerPtr->staticLink.address;
				dataPtr = (StackItemPtr)headerPtr + symbol->defn.info.data.offset;
			}
			break;
			case VAR_TYPE_ETERNAL:
				dataPtr = (StackItemPtr)stack + symbol->defn.info.data.offset;
				break;
			case VAR_TYPE_STATIC:
				dataPtr = (StackItemPtr)StaticDataPtr + symbol->defn.info.data.offset;
				break;
		}
		TypePtr	typePtr = (TypePtr)(symbol->typePtr);
		ABL_Assert(dataPtr != nullptr, 0, " Debugger.sprintArrayValue(): dataPtr is nullptr ");
		Address elementAddress = (Address)dataPtr->address;
		if(subscriptString)
		{
			PSTR cp = subscriptString;
			//-----------------------------
			// Get past the open bracket...
			cp++;
			PSTR token = strtok(&subscriptString[1], ",]");
			while(token)
			{
				//----------------
				// Read integer...
				int32_t index = atoi(token);
				//-------------------------
				// Range check the index...
				if((index < 0) || (index >= typePtr->info.array.elementCount))
					return(1);
				elementAddress += (index * typePtr->info.array.elementTypePtr->size);
				typePtr = typePtr->info.array.elementTypePtr;
				token = strtok(nullptr, ",]");
			}
		}
		if((typePtr->form != FRM_ARRAY))
		{
			if((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM))
				sprintf(dest, "%d", *((int32_t*)elementAddress));
			else if(typePtr == CharTypePtr)
				sprintf(dest, "\"%c\"", *((PSTR)elementAddress));
			else
				sprintf(dest, "%.4f", *((float*)elementAddress));
		}
		else if(typePtr->info.array.elementTypePtr == CharTypePtr)
			sprintf(dest, "\"%s\"", (PSTR)elementAddress);
		else
			sprintf(dest, "Could you be more specific?");
	}
	return(ABL_NO_ERR);
}
Example #4
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);
}