⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.cpp

📁 在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己的开发
💻 CPP
字号:
// MODULE.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//
#include <oplr.h>
#include <module.h>
#include <opcodes.h>
#include "frame.h"

typedef COpxBase * (*TOpxSetTls)(OplAPI& aAPI);

// to be shared between CModuleCollection and COpxModule
GLDEF_C void ParseName(const RFs& aFsClient,TFileName& aPath,const TDesC& aName,TDes& aFileName,TOplParseType aFlag)
// aPath may be changed, useful for CModuleCollection
	{
	TParse parse;
	User::LeaveIfError(aFsClient.Parse(aName,aPath,parse));
	if (aPath.Length()==0) // top level module!
		aPath=parse.DriveAndPath();
	aFileName=parse.FullName();
	if (!parse.ExtPresent())
		{
		_LIT(KOpo,".OPO");
		_LIT(KOpx,".OPX");
		TBuf<4> ext=KOpo();
		if (aFlag!=EOplParseModule)
			ext=KOpx;
		aFileName.Append(ext);
		}
	}


CProcDef::CProcDef(CModule *aModule,TOpoProcHeader *aProcHeader)
: iModule(aModule)
	{
	iProcName.Set((TText*)aProcHeader->iOplProcName->iModuleName,aProcHeader->iOplProcName->iLength);
	iFileOffset=aProcHeader->iProcOffset;
	iLineInSource=aProcHeader->iLineNumber;
	}

CProcDef::~CProcDef()	
	{
	delete iProcedure;
	}

void CProcDef::IncCountL()
	{
	if (iProcedure==NULL)
		{
		CProcedure* procedure=new(ELeave) CProcedure;
		CleanupStack::PushL(procedure);
		procedure->ConstructL(this,iModule->FileHandle());
		CleanupStack::Pop();
		iProcedure=procedure;
		}
	iModule->IncCount();
	}

void COpxModule::ConstructL(CModuleReader& aModuleReader)
	{
	aModuleReader.SeekOpxHeaderL();
	TInt total=aModuleReader.ReadCountOfOpxsL();
	iOpxs=new(ELeave) CArrayFixFlat<SOpxData>(total);
	for (;iOpxCount<total;iOpxCount++)
		{
		// !!! This must be changed to a CBase class!!!
		SOpxData s;
		s.iTls=NULL; 

		//
		iOpxs->AppendL(s);
		LoadOpxL(aModuleReader,(*iOpxs)[iOpxCount]);
		}
	}

COpxModule *COpxModule::NewL(CModuleReader& aModuleReader)
	{
	COpxModule *This=new(ELeave) COpxModule;
	CleanupStack::PushL(This);
	This->ConstructL(aModuleReader);
	CleanupStack::Pop();
	return This;
	}

COpxModule::~COpxModule()
	{
	TInt i;
	for (i=0;i<(*iOpxs).Count() && (*iOpxs)[i].iTls!=NULL;i++) // relies on last element loaded
		{
		if (((*iOpxs)[i].iTls)->DecAccessCount()==0)    // SOpxData should be a CBase class
														// COplrOpxData (OPXs already use COpxData)
			delete (*iOpxs)[i].iTls;
		(*iOpxs)[i].iHandle.Close();	// ?? Can we close it many times
		}
	delete iOpxs;
	}

void COpxModule::LoadOpxL(CModuleReader& aModuleReader,SOpxData& aOpxData)  
	{
	TOpoOpxHeader *opxHeader=aModuleReader.ReadOpxHeaderL();

	COplRuntime& rt=*TheRuntime();
	TInt ret=aOpxData.iHandle.Load(opxHeader->iOpxFileName);
	if (ret<0)
		{
		rt.SetErrorBuffer(&opxHeader->iOpxFileName);
		User::Leave(ret);
		}
	TOpxSetTls setTls=(TOpxSetTls)aOpxData.iHandle.Lookup(EOpxCreate);
	aOpxData.iTls=(*setTls)(*rt.TheOplAPI());
	aOpxData.iTls->IncAccessCount();
	if (!aOpxData.iTls->CheckVersion(opxHeader->iVersion))
		{
		rt.SetErrorBuffer(&opxHeader->iOpxFileName);
		User::Leave(KOplErrOpxVersion);
		}
	}

void CModule::ConstructL(RFs &aFsClient)
	{
 	CModuleReader *moduleReader=new(ELeave) CModuleReader;
	CleanupStack::PushL(moduleReader);
	iFileHandle=moduleReader->CreateL(aFsClient,iOpoName);

#ifdef INTERNAL_RELEASE
	if (!moduleReader->IsOpler1OPO() && !moduleReader->SignatureOK())
		User::Leave(KOplErrBadFileType);
#endif
	TOplName *pOplName=NULL;
	if ((pOplName=moduleReader->ReadOplNameL())==NULL)
		User::Leave(KOplErrBadFileType);
	iUid=moduleReader->Uid();
	iOplName.Copy((TText*)pOplName->iModuleName,pOplName->iLength);
	const TOpoRootStream& root=moduleReader->RootStream();
	if (moduleReader->IsOpler1OPO())
		{
		iOplVersion=root.iTransVersion;
		if (root.iMinRunVersion>KOplRuntimeModuleVersion)	 
			// error if requires rt to handle module version greater than it does 
			// (ie. incompatible module from future)
			User::Leave(KOplErrNewVer);
		}
#ifdef INTERNAL_RELEASE
	else
		{
		TOpoModuleHeader16 *pModuleHeader=moduleReader->ReadModuleHeader16L();
		iOplVersion=pModuleHeader->iTransVersion;
		if (iOplVersion!=EOplTranVersionOpl1993 &&	// error if not opl1993 module or incompat module from future
								pModuleHeader->iMinRunVersion>KOplRuntimeModuleVersion)
			User::Leave(KOplErrNewVer);
		}
#endif
	iProcsQueHeader.SetOffset(_FOFF(CProcDef,iLink));  // was Link
	moduleReader->SeekProcHeaderL();

	moduleReader->ReadProcTableL(iProcTable);
	TUint8* pProcInfo=(TUint8*)iProcTable->Ptr();

	TOpoProcHeader *pProcHeader=NULL;

	while ((pProcHeader=moduleReader->ReadProcHeaderL(pProcInfo))!=NULL)
		iProcsQueHeader.AddLast(*(new(ELeave) CProcDef(this,pProcHeader)));

	if (root.iOpxTableId!=NULL)
		iOpxs=COpxModule::NewL(*moduleReader);
	iDebugFlag=root.iDebugFlag;
	CleanupStack::PopAndDestroy();
	}

CModule *CModule::NewL(RFs &aFsClient,const TDesC &aOpoName)
	{
	CModule *This=new(ELeave) CModule;
	CleanupStack::PushL(This);
	This->iOpoName.Copy(aOpoName);
	This->ConstructL(aFsClient);
	CleanupStack::Pop();
	return This;
	}

CModule::~CModule()
	{
	CProcDef *pProc;
 	TSglQueIter<CProcDef> iterator(iProcsQueHeader);	// was TDblQueIter
	while ((pProc=iterator++)!=NULL)
		delete pProc; 
	delete iOpxs;
	iFileHandle.Close();
	User::Free(iProcTable);
	}

CProcDef *CModule::FindFirstProcedure() 
	{
	if (iProcsQueHeader.IsEmpty())
		return NULL;
	else
		return iProcsQueHeader.First();
	}

CProcDef *CModule::FindProcedure(const TDesC &aProcName) 
	{
	CProcDef *pProc;
	TSglQueIter<CProcDef> iterator(iProcsQueHeader);  // was TDblQueIter
	while ((pProc=iterator++)!=NULL)
		{
		TInt lenProcName=aProcName.Length()*sizeof(TText);
		TInt lenNameInModule=pProc->ProcName().Length()*sizeof(TText);
		if (lenProcName==lenNameInModule)
			{
			const TUint8* pProcName=(TUint8*)aProcName.Ptr();
			const TUint8* pNameInModule=(TUint8*)pProc->ProcName().Ptr();
			if (Mem::Compare(pNameInModule,lenNameInModule,pProcName,lenProcName)==0)
				break;
			}
		}
	return pProc;							
	}
void CModule::DecCount() 
	{
	if ((--iAccessCount)==0)
		delete this;
	}

void CModulesCollection::Init(RFs &aFsClient)
	{
	iNumModulesLoaded=0;
	iFsClient=aFsClient;
	}

CProcDef* CModulesCollection::FindProcedure(const TDesC &aProcName)
	{
	TInt i;
	CProcDef *pProc=NULL;
	for (i=0; i<iNumModulesLoaded; i++)
		{
		if ((pProc=iModule[i]->FindProcedure(aProcName))!=NULL)
			break;
		}
	if (i==iNumModulesLoaded) //not found
		{
		TheRuntime()->SetErrorBuffer(&aProcName);
		User::Leave(KOplErrNoProc);
		}
	return pProc;
	}

CProcDef* CModulesCollection::FindFirstProcedure()
	{
	return	iModule[0]->FindFirstProcedure();
	}

CModule* CModulesCollection::FindModule(const TFileName &aFileName)	const
	{
	TInt i;
	for (i=0; i<iNumModulesLoaded; i++)
		{
		if (aFileName.CompareF(iModule[i]->OpoName())==0)
			break;
		}
	if (i<iNumModulesLoaded)
		return iModule[i];	   
	else
		return NULL;							
	}

TInt CModulesCollection::FindAndDestructModule(const TFileName &aFileName)
	{
	TInt i;
	for (i=0; i<iNumModulesLoaded; i++)
		{
		if (aFileName.CompareF(iModule[i]->OpoName())==0)
			break;
		}
	if (i<iNumModulesLoaded)
		{
		iModule[i]->DecCount();
		for (; i<(iNumModulesLoaded-1); i++)
			iModule[i]=iModule[i+1];
		iModule[i]=NULL;
		iNumModulesLoaded--; 
		return KErrNone;
		}	   
	else
		return KOplErrModNotLoaded;							
	}

void CModulesCollection::LoadModuleL(const TDesC &aFileName) 
	{
	TFileName fileName;
	ParseName(iFsClient,iModulePath,aFileName,fileName,EOplParseModule);
	
	if (fileName.Length() == 0)
		User::Leave(KErrBadName);
	
	if (FindModule(fileName)!=NULL)	
		User::Leave(KOplErrModLoad);				// module is loaded
	if (iNumModulesLoaded==KMaxModules)
		User::Leave(KOplErrMaxLoad);
	CModule* mod=iModule[iNumModulesLoaded]=CModule::NewL(iFsClient,fileName); 	
	iModule[iNumModulesLoaded++]->IncCount();
	if (iUid==KNullUid)
		iUid=mod->Uid();
	}

TInt CModulesCollection::UnloadModule(const TDesC &aFileName)
	{
	TFileName fileName;
	ParseName(iFsClient,iModulePath,aFileName,fileName,EOplParseModule);
	if (fileName.Length() == 0)
		return KErrBadName;
	return FindAndDestructModule(fileName);	
	}

CModulesCollection::~CModulesCollection()
	{
	TInt i;
	for (i=iNumModulesLoaded-1; i>=0; i--)
		delete (iModule[i]);
	iNumModulesLoaded=0;
	}

void OpCode::LoadM(CStack& aStack, COplRuntime& aRuntime, CFrame* /*aFramePtr*/)
	{
	aRuntime.ModulesCollection().LoadModuleL(aStack.PopString());
	aRuntime.ClearTrap();
	}
	
void OpCode::UnLoadM(CStack& aStack, COplRuntime& aRuntime, CFrame* /*aFramePtr*/)
	{
	User::LeaveIfError(aRuntime.ModulesCollection().UnloadModule(aStack.PopString()));
	aRuntime.ClearTrap();
	}

void OpCode::CallOpxFunc(CStack& /*aStack*/, COplRuntime& aRuntime, CFrame* aFramePtr)
	{
	COpxModule* opxs=aFramePtr->ProcDef().Module().Opxs();
	TInt opxNo=aRuntime.IP8();

	opxs->CallOpxFunc(opxNo,aRuntime.IP16());
	aRuntime.ConEnv()->Cancel(); // in case the opx leaves a Wserv request pending
	}

//////////////////////////////////////////////////////////////////////////
// COpxBase class

EXPORT_C void COpxBase::IncAccessCount()
    {
    ++iAccessCount;
    }

EXPORT_C TInt COpxBase::DecAccessCount()
    {
    return --iAccessCount;
    }

EXPORT_C COpxBase::COpxBase(OplAPI& aOplAPI)
: iOplAPI(aOplAPI)
    {
    ;
    }

⌨️ 快捷键说明

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