opl16gen.cpp

来自「在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己」· C++ 代码 · 共 2,125 行 · 第 1/5 页

CPP
2,125
字号
						break;
					}	
				CleanupStack::PopAndDestroy();
				break;
				}
			case TPcode::EEvalIdentifier:
			case TPcode::EIdentifier:
				{
				TPcodeSymbolReference aRef;
				aPcode>>aRef;

				TUint code=TQcode16::EIdentifier;

				// Left or Right side				
				if (aRef.Symbol()->Token()==TOplToken::EArray)
					RemoveFromStack(TOplToken::EWord);
				code|=AddToStackL(aRef.Side(),aRef.Symbol()->Type());

				// Direct or Indirect
				COplSymbol::TClass symClass=aRef.Symbol()->Class();
				if (symClass==COplSymbol::EExternalRef || symClass==COplSymbol::EArgument)
					code|=KOpl16ExternalReference;

				// Simple or array 
				if (aRef.Symbol()->Token()==TOplToken::EArray)
					code|=KOpl16ArrayReference;

				// Put out the Qcode
				if (next.Code()==TPcode::EIdentifier) // 'Normal' qcode module
					aQcode<<TQcode16(code|aRef.Symbol()->Type())<<TUint16(aRef.Symbol()->Address());
				else // Eval identifier reference.
					{
					TUint code=(aRef.Side()==TPcode::ERight ? TQcode16::EEvalRightSideExternal : TQcode16::EEvalLeftSideExternal);
					aQcode<<TQcode16(code)<<TLbc(aRef.Symbol()->Name())<<TGlobalType(aRef.Symbol());
					}
                break;
				}
			case TPcode::EField:
				{
				CPcodeFieldReference *field=CPcodeFieldReference::NewLC(aPcode);
				TUint code=TQcode16::EField|AddToStackL(field->Side(),field->Type());

				// Stack field name, then Field code and logical device
				aQcode<<TQcode16(TQcode16::EConstant|TOplToken::EString)<<TLbc(field->Name())<<TQcode16(code|field->Type())<<TUint8(field->Device());
				CleanupStack::PopAndDestroy();
				}
				break;
			case TPcode::EProcCallName: // Ignore these, they exist for the benefit of the Munger
				break;
			case TPcode::EArgList:
				iStackDepths->PushL(&iStackDepth); // Save the stack depth
				break;

			case TPcode::EProcArg:
			case TPcode::EOpxArg:
			case TPcode::EFunctionArg:
				{
				TPcodeCallArgument arg;
				aPcode>>arg;

				if (next.Code()==TPcode::EProcArg) // For procedures we also stack the argument type
					{
					aQcode<<TQcode16(TQcode16::EStackByteAsWord)<<TUint8(arg.Type());
					AddToStackL(TOplToken::EWord);
					}
				break;
				}			
			
			case TPcode::EOpxCall:
			case TPcode::EProcCall: // Procedure call
				{
				TPcodeCall call;
				aPcode>>call;
				AdjustStackForCallL(call.Symbol()->Type());

				TUint addr=call.Symbol()->Address();
				if (next.Code()==TPcode::EProcCall)
					aQcode<<TQcode16(TQcode16::ECallProcedure)<<TUint16(addr);
				else
					{
					TOpxAddress opxFunc(addr);
					aQcode<<TQcode16(TQcode16::EOpxCall)<<TUint8(opxFunc.Module())<<TUint16(opxFunc.Function());
					}
				break;
				}
			case TPcode::EProcByNameCall:
				{
				TPcodeProcByName proc;
				aPcode>>proc;
				AdjustStackForCallL(proc.Type());

				aQcode<<TQcode16(TQcode16::ECallProcByName)<<TUint8(proc.ArgumentCount())<<TUint8(procByNameTypeBytes[proc.Type()]);
				break;
				}
			case TPcode::EFixedFunctionCall:
			case TPcode::ECountedFunctionCall:
				{
				TPcodeFunctionCall function;
				aPcode>>function;
				AdjustStackForCallL(function.Type());

				RWriteStream& code=aQcode<<TQcode16(TQcode16::EFunctionCall)<<FunctionTable[function.Number()];
				if (next.Code()==TPcode::ECountedFunctionCall)
					code<<TUint8(function.ArgumentCount());
				break;
				}
			case TPcode::EDrop:
				{
				TPcodeDrop drop;
				aPcode>>drop;

				RemoveFromStack(drop.Type());
				__ASSERT_ALWAYS(iStackDepth==0,Panic(EOpl16StackError));

				aQcode<<TQcode16(TQcode16::EDropValue|drop.Type());
				break;
				}
			case TPcode::EAssign:
				{
				TPcodeAssign assign;
				aPcode>>assign;

				aQcode<<TQcode16(TQcode16::EAssign|assign.Type());
				ZeroStack();
				break;
				}
			case TPcode::ECast:
				{
				TPcodeCast cast;
				aPcode>>cast;

				TUint castCode=casts[cast.From()][cast.To()];
				if (castCode==TQcode16::EExtended) // type mismatch
					User::Leave(EErrTypeMismatch);
				if (castCode!=0) // Really do need a cast
					{
					RemoveFromStack(cast.From());
					AddToStackL(cast.To());
					aQcode<<TQcode16(castCode);
					}
				break;
				}
			case TPcode::EOperator:
				{
				TPcodeOperator oper;
				aPcode>>oper;

				RemoveFromStack(oper.OperandType());
				if (oper.Arity()==TPcodeOperator::EBinary)
					RemoveFromStack(oper.OperandType());
				AddToStackL(oper.ResultingType());
				
				TUint code=operators[oper.Oper()-TOplToken::EStartOfExpression];
				if (code!=0) // Some operators are only there for the Qcode cracker
					{
					if (code<TQcode16::EPercLess) // Not a % operator
						code|=oper.OperandType();
					aQcode<<TQcode16(code);
					}
				break;
				}
			case TPcode::ECommand:
				{
				TPcodeCommand command;
				aPcode>>command;
				
				aQcode<<TQcode16(StatementQcodeL(aQcode,command));
				ZeroStack();
				break;
				}
			case TPcode::ETypedCommand:
				{
				TPcodeTypedCommand command;
				aPcode>>command;

				aQcode<<TQcode16(StatementQcodeL(aQcode,command)|command.Type());
				ZeroStack();
				break;
				}
			case TPcode::EQualifiedCommand:
				{
				TPcodeQualifiedCommand command;
				aPcode>>command;

				aQcode<<TQcode16(StatementQcodeL(aQcode,command))<<TUint8(command.Qualifier());
				ZeroStack();
				break;
				}
			case TPcode::ELabel: // Label declaration
				{
				TPcodeLabel label;

				aPcode>>label;
				label.Symbol()->SetAddress(aQcode.Sink()->SeekL(0,EStreamEnd).Offset());
				iLabels->AppendL(label.Symbol());
				break;
				}
			case TPcode::EBranchFalse:
			case TPcode::EBranchAlways:
			case TPcode::EOnErr:
				{
				TInt base=aQcode.SizeL(); // Calculate label offset from before branch instruction
				if (next.Code()==TPcode::EBranchFalse)
					{
					RemoveFromStack(TOplToken::EWord); // Takes the conditional expression off the stack
					aQcode<<TQcode16(TQcode16::EBranchFalse);
					}
				else if (next.Code()==TPcode::EBranchAlways)
					aQcode<<TQcode16(TQcode16::EGoto);
				else
					aQcode<<TQcode16(TQcode16::EOnerr);
				LabelReferenceL(aPcode,aQcode,base);
				break;
				}
			case TPcode::EFieldName:
				{
				CPcodeFieldName *field=CPcodeFieldName::NewLC(aPcode);
				aQcode<<TUint8(field->Type())<<TLbc(field->Name());
				CleanupStack::PopAndDestroy();
				break;
				}
			case TPcode::EEndFieldList:
				{
				aQcode<<TUint8(KOpl16EndOfFieldList);
				break;
				}
			case TPcode::EVector:
				{
				vectorBase=aQcode.SizeL();
				aQcode<<TQcode16(TQcode16::EVector);
				vectorPatchPos=aQcode.AddPatch16L();
				vectorLabelsCount=0;
				ZeroStack();
				break;
				}
			case TPcode::EVectorLabel:
				LabelReferenceL(aPcode,aQcode,vectorBase);
				vectorLabelsCount++;
				break;
			case TPcode::EEndVector:
				aQcode.Patch16L(vectorPatchPos,vectorLabelsCount);
				break;
			default:
				Panic(EOpl16GenUnknownPCode);
			}
		if (aQcode.SizeL()>iErrorPos)
			User::Leave(EErrFound);
		}
	}

void COpl16PcodeConverter::LabelReferenceL(RReadStream& aPcode, ROpoWriteStream& aQcode,TInt aBase)
/*
Does everytyhing needed to put out a lebel refernce
*/	
	{
	COplLabelSymbol* pLabel;
	pLabel=(COplLabelSymbol*)aPcode.ReadUint32L();
	
	if (pLabel==NULL)
		aQcode<<TUint16(0);
	else
		{
		if (!pLabel->IsDefined())
			User::Leave(EErrMissingLabel);
		pLabel->AddReferenceL(TLabelReference(aQcode.AddPatch16L(),aBase));
		}
	}


void COpl16PcodeConverter::AddToStackL(TOplToken::TType aType)
	{
	AddToStackL(SizeOnStack(aType));
	}

void COpl16PcodeConverter::AddToStackL(TUint byteCount)
	{
	iStackDepth+=byteCount;
	if (iStackDepth>iMaxStackDepth)
		iMaxStackDepth=iStackDepth;
	}

TUint COpl16PcodeConverter::AddToStackL(TPcode::TIdentifierSide aSide ,TOplToken::TType aType)
/*
Adds the appropriate side to the stack	
*/
	{
	TUint sideBits=0;
	if (aSide==TPcode::ERight) // It's a rightside reference
		AddToStackL(aType);
	else
		{
		AddToStackL(KOpl16SizeOfLeftSideReference);
		sideBits=KOpl16LeftSideReference;
		}
	return sideBits;
	}


void COpl16PcodeConverter::RemoveFromStack(TOplToken::TType aType)
	{
	
	iStackDepth-=SizeOnStack(aType);
	}


TUint COpl16PcodeConverter::SizeOnStack(TOplToken::TType aType)
	{
	return stackSizes[aType];
	}


void COpl16PcodeConverter::AdjustStackForCallL(TOplToken::TType aReturnType)
	{
	
	iStackDepths->Pop(&iStackDepth); // Pop the arguments off the stack
	AddToStackL(aReturnType); // Replace them with the return type
	}

TInt COpl16PcodeConverter::RunL(CBufBase& aPcodeBuffer, ROpoWriteStream& aQcodeStream,
								TTranslateError& anError, CTextTranslator::TDebugFlag aFlag)
	
//
// Streams Qcode out to aQcodeBuffer according to Pcode in aPCodeBuffer
//
	{
	RBufReadStream pcodeStream(aPcodeBuffer);
	iStackDepth=0;
	iMaxStackDepth=0;

	TRAPD(ret,ConvertPcodeL(pcodeStream,aQcodeStream,anError,aFlag));

	if (ret!=KErrEof) // Run out of stream.
		User::Leave(ret);

	// Patch the label references now that we know where the labels actually are
	for (TUint index=0,max=iLabels->Count();index<max;index++)
		{
		COplLabelSymbol* pLabel=(COplLabelSymbol*)((*iLabels)[index]);
		const CArrayFixFlat<TLabelReference>& references=pLabel->References();
		for (TUint refIndex=0,refMax=references.Count();refIndex<refMax;refIndex++)
			{
			const TLabelReference& ref=references[refIndex];
			aQcodeStream.Patch16L(ref.Position(),pLabel->Address()-ref.Base()); // Plus one is becase references are off 
			}
		}
	iLabels->Reset();
	iStackDepths->Reset();
	return iMaxStackDepth;
	}

//////////////////////////////////////////////////////////////////////////////////
//
// TOpl16ProcEntry
//
//////////////////////////////////////////////////////////////////////////////////
TOpl16ProcEntry::TOpl16ProcEntry(const TDesC& aName,TInt aLine, TInt aPosition)
	: iName(aName),iLineNumber(aLine), iModulePos(aPosition)
	{
	}


//////////////////////////////////////////////////////////////////////////////////
//
// TSymbolArrayWalkL(s) - classes for walking the symbol arrays
//
//////////////////////////////////////////////////////////////////////////////////
class TSymbolArrayWalk
	{
public:
	void WalkL(const CArrayFix<COplSymbol*>& aSymbolArray, TInt &aTotal, TInt *anArg=NULL);
private:
	virtual void ProcessSymbolL(COplSymbol *aSymbol, TInt& aTotal, TInt* anArg)=0;
	};

void TSymbolArrayWalk::WalkL(const CArrayFix<COplSymbol*>&aSymbolArray,TInt& aTotal,TInt *anArg)
//
// Walks an array of symbols
//
	{
	
	TInt index=0;
	TInt count=aSymbolArray.Count();
	while (index<count)
		{
		ProcessSymbolL(aSymbolArray[index],aTotal,anArg);
		index++;
		}
	}

//////////////////////////////////////////////////////////////////////////////////
//
// TGlobalTableWalk - Works out the size of the global table
//
//////////////////////////////////////////////////////////////////////////////////
class TGlobalTableWalk : public TSymbolArrayWalk
	{
private:
	void ProcessSymbolL(COplSymbol* aSymbol,TInt& aTotal, TInt * anArg);
	};

// Extra space used by an entry in the global lookup table
// above and beyond the klength of the name.
// 2 for the lbc for the name length
// 2 for the type
// 2 are for the address of the variable.
const TInt KOpl16GlobalNameOverhead=6;

void TGlobalTableWalk::ProcessSymbolL(COplSymbol * aSymbol,TInt& aTotal, TInt* anArg)
//
// Works out the size of the entry.
//	
	{
	TInt entrySize=aSymbol->Name().Length()*sizeof(TText)+KOpl16GlobalNameOverhead;
	aTotal+=entrySize; // Total data size
	(*anArg)+=entrySize; // Size of globals table
	}

//////////////////////////////////////////////////////////////////////////////////
//
// TProcTableWalk - Works out details of the procedure table
//
//////////////////////////////////////////////////////////////////////////////////
class TProcTableWalk : public TSymbolArrayWalk
	{
private:

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?