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 + -
显示快捷键?