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