opl16gen.cpp
来自「在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己」· C++ 代码 · 共 2,125 行 · 第 1/5 页
CPP
2,125 行
void ProcessSymbolL(COplSymbol* aSymbol,TInt& aTotal, TInt *);
};
// Extra space used in addition to the name in the
// table containing thh names of all the procedures called
// 2 is for the name lbc
// 2 for the number of paramters passed
const TInt KOpl16ProcedureNameOverhead=4;
void TProcTableWalk::ProcessSymbolL(COplSymbol * aSymbol,TInt& aTotal, TInt*anArg)
//
// Works out the size of teh entry.
//
{
aSymbol->SetAddress(aTotal);
TInt entrySize=aSymbol->Name().Length()*sizeof(TText)+KOpl16ProcedureNameOverhead;
aTotal+=entrySize;
(*anArg)+=entrySize; // Procedure table size
}
//////////////////////////////////////////////////////////////////////////////////
//
// TArgumentIndirectionsWalk - Works out teh addresses of an entry in the indirections table
//
//////////////////////////////////////////////////////////////////////////////////
class TIndirectionsWalk : public TSymbolArrayWalk
{
private:
void ProcessSymbolL(COplSymbol* aSymbol,TInt& aTotal, TInt *);
};
void TIndirectionsWalk::ProcessSymbolL(COplSymbol * aSymbol,TInt& aTotal, TInt* /*anArg*/)
//
// Works out the size of the entry.
//
{
aSymbol->SetAddress(aTotal);
aTotal+=sizeof(TUint16);
}
//////////////////////////////////////////////////////////////////////////////////
//
// TVariableAddresesWalk - Works out the addresses of the variables in the frame (LOCAL, GLOBAL)
//
//////////////////////////////////////////////////////////////////////////////////
class TVariableAddressesWalk : public TSymbolArrayWalk
{
private:
void ProcessSymbolL(COplSymbol* aSymbol,TInt& aTotal, TInt *);
};
const TInt KOpl16StringLenOverhead=2; // Two lbc bytes.
const TInt KOpl16StringMaxLenOverhead=2; // Max length
const TInt KOpl16ArraySizeOverhead=2; // Array size
void TVariableAddressesWalk::ProcessSymbolL(COplSymbol * aSymbol,TInt& aTotal, TInt* /*anArg*/)
//
// Works out the address of a global or Local symbol
//
{
aSymbol->SetAddress(aTotal);
COplAutomaticSymbol *automatic=(COplAutomaticSymbol *)aSymbol;
TInt size=stackSizes[aSymbol->Type()];
if (!size) // It's a string
{
size=automatic->StringLength()*sizeof(TText)+KOpl16StringLenOverhead;
aSymbol->SetAddress(aTotal+KOpl16StringLenOverhead);
}
// It's an array
if (aSymbol->Token()==TOplToken::EArray)
{
size*=automatic->ArraySize();
size+=KOpl16ArraySizeOverhead;
aSymbol->SetAddress(aSymbol->Address()+KOpl16ArraySizeOverhead);
}
// Now add in overhead for max string length if needed
if (aSymbol->Type()==TOplToken::EString)
size+=KOpl16StringMaxLenOverhead;
aTotal+=size;
}
//////////////////////////////////////////////////////////////////////////////////
//
// TOutputWalk
//
//////////////////////////////////////////////////////////////////////////////////
LOCAL_C void NameTypeAndAddressL(COplSymbol *aSymbol, RWriteStream& aStream)
{
aStream<<TLbc(aSymbol->Name())<<TGlobalType(aSymbol)<<TUint16(aSymbol->Address());
}
class TOutputWalk
{
public:
void WalkL(const CArrayFix<COplSymbol*>& anArray,RWriteStream& aStream);
private:
virtual void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)=0;
};
void TOutputWalk::WalkL(const CArrayFix<COplSymbol*>& anArray, RWriteStream& aStream)
{
TInt count=anArray.Count();
TInt index=0;
while (index<count)
{
OutputSymbolL(anArray[index], aStream);
index++;
}
}
///////////////////////////////////////////////////////////////////////////////////
//
// TGlobalOutputWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TGlobalOutputWalk : public TOutputWalk
{
private:
void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TGlobalOutputWalk::OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)
{
NameTypeAndAddressL(aSymbol,aStream);
}
///////////////////////////////////////////////////////////////////////////////////
//
// TProcOutputWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TProcOutputWalk : public TOutputWalk
{
private:
void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TProcOutputWalk::OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)
//
// Getting back to the original call is a bit horrendous Most of the time we don't need to do this
//
{
COplCallSymbol *call=(COplCallSymbol *)(&((COplReferenceSymbol *)aSymbol)->Declaration());
(aStream<<TLbc(aSymbol->Name())).WriteUint16L(call->Signature().ArgumentCount());
}
///////////////////////////////////////////////////////////////////////////////////
//
// TStringsOutputWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TStringsOutputWalk : public TOutputWalk
{
private:
void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TStringsOutputWalk::OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)
{
if (aSymbol->Type()==TOplToken::EString)
{
COplAutomaticSymbol *automatic=(COplAutomaticSymbol *)aSymbol;
aStream<<TUint16(automatic->Address()-KOpl16StringLenOverhead)<<TUint16(automatic->StringLength());
}
}
///////////////////////////////////////////////////////////////////////////////////
//
// TArraysOutputWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TArraysOutputWalk : public TOutputWalk
{
private:
void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TArraysOutputWalk::OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)
{
if (aSymbol->Token()==TOplToken::EArray)
{
COplAutomaticSymbol *automatic=(COplAutomaticSymbol *)aSymbol;
TUint addr=automatic->Address()-sizeof(TUint16);
if (automatic->Type()==TOplToken::EString)
addr-=sizeof(TUint16);
aStream<<TUint16(addr)<<TUint16(automatic->ArraySize());
}
}
///////////////////////////////////////////////////////////////////////////////////
//
// TExternalsOutputWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TExternalsOutputWalk : public TOutputWalk
{
private:
void OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TExternalsOutputWalk::OutputSymbolL(COplSymbol *aSymbol, RWriteStream& aStream)
{
aStream<<TLbc(aSymbol->Name())<<TGlobalType(aSymbol);
}
///////////////////////////////////////////////////////////////////////////////////
//
// TSymbolWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TSymbolWalk
{
public:
TStreamId WalkL(CFileStore *aFileStore, const CArrayFix<COplSymbol*>& anArray);
private:
virtual void OutputSymbolDetailsL(COplSymbol *aSymbol, RWriteStream& aStream);
};
TStreamId TSymbolWalk::WalkL(CFileStore *aFileStore, const CArrayFix<COplSymbol*>& anArray)
//
// Creates a stream and does the walk. Returns the stream id2
//
{
RStoreWriteStream stream;
TStreamId streamId=stream.CreateLC(*aFileStore);
TInt count=anArray.Count();
TInt index=0;
while (index<count)
{
COplSymbol *symbol=anArray[index];
NameTypeAndAddressL(symbol, stream);
OutputSymbolDetailsL(symbol, stream);
index++;
}
stream<<TUint8(0); // Terminate the list
stream.CommitL();
CleanupStack::PopAndDestroy();
return streamId;
}
void TSymbolWalk::OutputSymbolDetailsL(COplSymbol* /* aSymbol*/, RWriteStream& /*aStream*/)
//
// Just a place marker
//
{
}
///////////////////////////////////////////////////////////////////////////////////
//
// TAutomaticSymbolWalk
//
///////////////////////////////////////////////////////////////////////////////////
class TAutomaticSymbolWalk : public TSymbolWalk
{
private:
virtual void OutputSymbolDetailsL(COplSymbol *aSymbol, RWriteStream& aStream);
};
void TAutomaticSymbolWalk::OutputSymbolDetailsL(COplSymbol* aSymbol, RWriteStream& aStream)
//
// Puts out the maximum string and array sizes - may be 0
//
{
COplAutomaticSymbol *automatic=(COplAutomaticSymbol *)aSymbol;
//!!TODO Debugger alignment: need to force alignment here?
aStream<<TUint16(automatic->ArraySize())<<TUint16(automatic->StringLength()*sizeof(TText));
}
/////////////////////////////////////////////////////////////////////////
//
// TBackEndFile - Used to cleanup writing the output file if anything goes wrong
//
/////////////////////////////////////////////////////////////////////////
struct TBackEndFile
{
inline TBackEndFile(COpl16Opl1993BackEnd& aBackEnd,RFile& aFile) : iBackEnd(aBackEnd), iFile(aFile) {}
COpl16Opl1993BackEnd& iBackEnd;
RFile& iFile;
};
void FileCleanup(void *aBackEndFile)
// Closes and deletes the output file if anything goes wrong
//
{
TBackEndFile *backEndFile=(TBackEndFile *)aBackEndFile;
backEndFile->iBackEnd.TidyFile(backEndFile->iFile);
}
//////////////////////////////////////////////////////////////////////////////////
//
// COpl16ModuleBackEnd - Common 16 bit opcode back end
//
/////////////////////////////////////////////////////////////////////////////////
void COpl16ModuleBackEnd::StartL(const TDesC& aSourceName,CTextTranslator::TDebugFlag aDebugFlag, TSourceTranslateError& anError)
//
// Sets things up ready to go.
//
{
__ASSERT_DEBUG(iState==EReset,Panic(EOpl16BackEndReentrantStart));
iError=&anError;
iDebugFlag=aDebugFlag;
iOpo.Open(*iQcodeBuffer); // Gives a Patchable in memory stream to play with
DoStartL(aSourceName);
iState=EStarted;
}
COplParseApp* COpl16ModuleBackEnd::GetAppLC(TOplTranTarget aTarget,COplLexerBase& aLexer)
//
// Returns 16 bit APP ENDA parser
//
{
COpl16App *pA=new(ELeave) COpl16App(aTarget,aLexer);
CleanupStack::PushL(pA);
return pA;
}
void COpl16ModuleBackEnd::OplTargetIsApp()
{
if (iAppCB!=NULL)
iAppCB->OplTargetIsAppL(iOutputName);
}
void COpl16ModuleBackEnd::AppL(COplParseApp* anApp)
//
// Just parsed an APP...ENDA construct and need to add it to file
// Takes ownership of the passed object IF it succeeds
//
{
__ASSERT_DEBUG(iState==EStarted,Panic(EOpl16BackEndAppState));
DoAppL((COpl16App *)anApp);
delete anApp;
iState=EAppSeen;
}
void COpl16ModuleBackEnd::StartProcL(const TDesC& aName,TInt aLineNumber, TInt anErrorOffset )
//
// Starts a new procedure
//
{
__ASSERT_DEBUG(iState!=EReset && iState!=EAwaitingBody,Panic(EOpl16BackEndProcState));
if (iState!=EProcSeen)
FirstProcL();
iConverter->SetErrorOffset(anErrorOffset);
TInt pos=DoStartProcL();
TOpl16ProcEntry tableEntry(aName, aLineNumber, pos);
//!!TODO fix this to be upper case in Unicode???
TKeyArrayFix aKey(_FOFF(TOpl16ProcEntry,iName),ECmpFolded);
TInt dummy;
if (iProcs->Find(tableEntry,aKey,dummy)==0)
User::Leave(EErrDuplicateName);
iProcs->AppendL(tableEntry);
iState=EAwaitingBody;
}
void COpl16ModuleBackEnd::ProcL(COplProcHeader *aHeader, CBufSeg *aPcodeBuffer)
//
// We construct the stream fragment for the Procedure in the iOpo
// stream and then have the particular back end do with it what it will
//
{
__ASSERT_DEBUG(iState==EAwaitingBody,Panic(EOpl16BackEndBodyState));
// First we process the header
TStreamPos qcodeSizePatchPos;
TStreamPos stackDepthPatchPos;
ProcessProcHeaderL(aHeader,qcodeSizePatchPos,stackDepthPatchPos);
// And now generate the main Qcode
TInt qcodeStart=iOpo.SizeL();
iConverter->RunL(*aPcodeBuffer,iOpo,*iError,iDebugFlag);
// Go back and make patches in header based on what we now know.
iOpo.Patch16L(qcodeSizePatchPos,iOpo.SizeL()-qcodeStart);
iOpo.Patch16L(stackDepthPatchPos,iConverter->MaxStackDepth());
// Now do whatever's needed to add this
// to the particular file type
DoProcL();
// And finally tidy up a bit
delete aHeader;
delete aPcodeBuffer;
iState=EProcSeen;
}
void COpl16ModuleBackEnd::EndOfFileL()
//
// Reached the end of the source. Sort out all the bits
// and pieces at the end of the file.
//
{
// Procedure table
RWriteStream& procTable=StartProcTableL();
for (TInt index=0;index<iProcs->Count();index++)
{
TOpl16ProcEntry& proc=(*iProcs)[index];
procTable<<TLbc(proc.iName)<<TUint32(proc.iModulePos)<<TUint16(proc.iLineNumber);
}
// This is still 8bit -- see corresponding OPLR CModuleReader::ReadProcHeaderL()
procTable.WriteUint8L(0); // Terminate the list
DoEndOfFileL();
}
void COpl16ModuleBackEnd::EnsurePathL()
//
// Ensures that the path for the output file exists
//
{
TInt ret=iFs.MkDirAll(iOutputName);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?