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

📄 opltran.cpp

📁 在手机操作系统symbina上使用的一个脚本扩展语言的代码实现,可以参考用于自己的开发
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// OPLTRAN.CPP
//
// WINC Command line OPL translator for Symbian OS
//
// Copyright (c) 1998-2002 Symbian Ltd. All rights reserved.

#include <f32file.h>
#include <fbs.h>
#include <opltran.h>
#include <e32cons.h>
#include <barsc.h>
#include <opltran.rsg>
#include "opltranerr.h" // mapping OPL error numbers.
#if !defined(__UIQ__)
#include <stdlib.h> // Windows exit
#endif
#include <bautils.h>

#include "winutil.h"
#include "opltrant.h"

// Version and copyright notices:
_LIT(KOpltranVersionDetails,"Opltran v2.09\n");

_LIT(KDefaultAppPath,"epoc32\\wins\\c\\System\\Apps\\.app");
_LIT(KOpltranResourceFile,"epoc32\\release\\winc\\udeb\\z\\system\\data\\opltran.rsc");
_LIT(KEikResourceFile,"epoc32\\release\\wins\\udeb\\z\\system\\data\\eikcore.rsc");

// Error output format details
enum {EErrorFormatODE=0,EErrorFormatMSD};

// Resource file details
enum {EOplResource=0, EEikResource};

const TInt KOpltranResourceSignature=0x00000004; // Should really be in .HRH file.
const TInt KEikResourceSignature=0x00000004; // EEikResourceSignatureValue;

// Drives, paths and buffers
GLDEF_D TFileName InputPath;
GLDEF_D TFileName IncludePath;
GLDEF_D TPtrC EpocRoot;
GLDEF_D TText8 CurrentWorkingDirectory8[KMaxFileName+1]; // Tmp buffer for Windows call. ("+1" is for zero terminator)
GLDEF_D RFs theFileServer;
GLDEF_D TFileName OutputPath;
GLDEF_D TConvertFlag ConvertFlag=ENoConvert;

LOCAL_C TFileName ExeDrive;
LOCAL_C TFileName CurrentWorkingDirectory;

LOCAL_C void ShowError(const TDesC& aMsg,TInt aErr,const TDesC& aExtra=KNullDesC);

// #define _ERROR_FILE
#ifdef _ERROR_FILE
	_LIT(KErrNameLiteral,"OPLTRAN.err");
	const TPtrC KErrName(KErrNameLiteral);
	LOCAL_C TBool	ErrorFileOpen=EFalse;
	LOCAL_C RFile	ErrorFile;
	LOCAL_C TParse	ErrorFileDetails;
#endif

#if !defined(__UIQ__)
LOCAL_C TInt	ExitValue=EXIT_SUCCESS; // ERRORLEVEL exit value
#endif
LOCAL_C TInt	ErrorFormatFlag=EErrorFormatODE; // Format of translator error msgs.
LOCAL_D ROplTextSystem theTextSystem;

class CConsoleReporter : public CConsoleBase
	{
public:
	inline void PVerbose(TRefByValue<const TDesC> aFmt,...) // only print if iVerboseFlag set.
		{
		if (iVerboseFlag)
			{
			VA_LIST list;
			VA_START(list,aFmt);
			TBuf<0xff> buf(0xff);
			buf.FillZ(0xff);
			buf.Zero();
			buf.AppendFormatList(aFmt,list);
			HeadedPrintf(buf);
			}
		}
	inline void PError(TRefByValue<const TDesC> aFmt,...) // always print these!
		{
		VA_LIST list;
		VA_START(list,aFmt);
		TBuf<0xff> buf(0xff);
		buf.FillZ(0xff);
		buf.Zero();
		buf.AppendFormatList(aFmt,list);
		HeadedPrintf(buf);
		}
	inline void Printf(TRefByValue<const TDesC> aFmt,...) // only print if iQuietFlag clear.
		{
		if (!iQuietFlag)
			{
			VA_LIST list;
			VA_START(list,aFmt);
			TBuf<0xff> buf(0xff);
			buf.FillZ(0xff);
			buf.Zero();
			buf.AppendFormatList(aFmt,list);
			HeadedPrintf(buf);
			}
		}
	inline void SetQuiet(TBool aFlag)	{ iQuietFlag=aFlag; }
	inline void SetVerbose(TBool aFlag)	{ iVerboseFlag=aFlag; }
private:
	inline void HeadedPrintf(TPtrC aBuf)
		{
		if (iOneShot==EFalse)
			{
			iOneShot=ETrue;
			CConsoleBase::Printf(KOpltranVersionDetails);
			}
		CConsoleBase::Printf(aBuf);
		}
	TBool iQuietFlag;
	TBool iVerboseFlag;
	TBool iOneShot;
	};

LOCAL_D CConsoleReporter* theConsole=NULL;
LOCAL_D COplModuleTranslator *theTranslator=NULL;
LOCAL_D CTextTranslator::TDebugFlag theDebugFlag=CTextTranslator::ERelease;

// Unicode resource file handling.
class RResourceFileU : public RResourceFile
	{
public:
	void ReadL(TDes16& aDes,TInt aResourceId) const;
	};

void RResourceFileU::ReadL(TDes16& aDes, TInt aResourceId) const
	{
	TPtr8 readBuffer((TText8* ) aDes.Ptr(),aDes.MaxSize());
	TRAPD(err,RResourceFile::ReadL(readBuffer,aResourceId));
	if (err!=KErrNone)
		User::Leave(err);
	if (readBuffer.Length()%2!=0)
		User::Leave(KErrCorrupt);
	aDes.SetLength((readBuffer.Length()+1)>>1);
	}

LOCAL_C TInt SetOutputPath(const TParse& aSourceFile)
// Build the OutputPath based on the optional command line token,
// filling in the missing bits from the source filename.
	{
	TParse SourceAllButExt;
	TFileName sourceName=aSourceFile.Name();
	SourceAllButExt.Set(aSourceFile.DriveAndPath(),&sourceName,NULL);
	// OutputPath construction.
	TParse OutputDrvAndPathParse, OutputParse;
	OutputDrvAndPathParse.Set(OutputPath,NULL,NULL);
	OutputParse.Set(OutputDrvAndPathParse.DriveAndPath(),&(SourceAllButExt.FullName()),NULL);
	OutputPath=OutputParse.FullName();
	return (ETrue);
	}

LOCAL_C void ForceTrailingSlash(TFileName &aPath)
	{
	_LIT(KTrailingSlash,"\\");
	const TPtrC Slash=KTrailingSlash();
	if (!((aPath.Length())&&(aPath.Right(1)==Slash)))
		aPath.Append(Slash);
	}

/*
 *  Convert the relative path of a filename to an absolute path.
 *  e.g. ..\src\fred.opl in J:\TEST\GROUP becomes J:\TEST\src\fred.opl
 *  [A bit convoluted, because unlike DOS, F32 can't cope with 
 *  'j:\test\group\..\src\fred.opl' as a valid filename.]
 */
LOCAL_C void ConvertRelativePathToAbsolute(TDes& aFileName)
	{
	// Ensure argument is valid
	_LIT(KRelativePathHeader,"..\\");
	const TInt rlen=KRelativePathHeader().Length(); // Save my fingers.
	if (aFileName.Length()<rlen)
		return;

	// Filename should start with "..\"
	if (aFileName.Left(rlen)!=KRelativePathHeader())
		return;

	TParse cwd;
	cwd.Set(CurrentWorkingDirectory,NULL,NULL);
	while (aFileName.Left(rlen)==KRelativePathHeader())
		{
		aFileName.Delete(0,rlen);
		cwd.PopDir();
		}

	// There must be no more relative folders...
	if (aFileName.Find(KRelativePathHeader) != KErrNotFound)
		{
		_LIT(KParsingCommandLine,"parsing relative path");
		ShowError(KParsingCommandLine,KErrPathNotFound);
		}

	// Prepend the truncated working directory to the filename.
	aFileName.Insert(0,cwd.DriveAndPath());
	}


LOCAL_C TBool ParseCommandLineL(TParse &aParse)
// Gets the command line from source. Returns ETrue if there is a possible
// OPL filename on the command line and EFalse otherwise.
// Sets aParse to the OPL filename if one is found.
//
// Drives&Paths			Location		Default		Used for locating:
// ExeDrive				EXE file		c:			RSC
// (oplfile drive)		OPL filename	ExeDrive	OPL
// OutputPath drive		-o arg			opl drive	OPO and debug
// IncludePath drive	-i arg			opl drive	OPH
	{
	TBool ret=EFalse;
	
	TBuf<0x100> cmd;
	RProcess().CommandLine(cmd);
	cmd.Trim();
	TLex iLex(cmd);

	TFileName OplName;

	FOREVER
		{
		TPtrC token = iLex.NextToken();
		if (token.Length()==0) // No more tokens.
			break;
		_LIT(KSwitchDelimiters,"-/");
		TBufC<2> switchDelimiters(KSwitchDelimiters);
		if (switchDelimiters.Find(token.Left(1))!=KErrNotFound)
			{
			TBool ValidArgument=EFalse;
			if (token.Length()>1)
				{
				HBufC* theSwitch;
				theSwitch = HBufC::NewL(token.Length()-1);
				*theSwitch = token.Mid(1);
				_LIT(KIncludePathSwitch,"i");
				_LIT(KOutputDirectorySwitch,"o");
				_LIT(KSymbolicDebugSwitch,"s");
				_LIT(KAlternativeErrorFormatSwitch,"e");
				_LIT(KConvertSwitch,"conv");
				_LIT(KQuietSwitch,"q");
				_LIT(KVerboseSwitch,"v");
				if (theSwitch->Left(1).CompareF(KIncludePathSwitch)==0)
					{ // The Include path.
					if (theSwitch->Length()>1)
						{
						IncludePath=theSwitch->Mid(1);
						ForceTrailingSlash(IncludePath);
						ValidArgument=ETrue;
						}
					}
				else if (theSwitch->Left(1).CompareF(KOutputDirectorySwitch)==0)
					{ // Output directory.
					if (theSwitch->Length()>1)
						{
						OutputPath=theSwitch->Mid(1);
						ForceTrailingSlash(OutputPath);
						ValidArgument=ETrue;
						}
					}
				else if (theSwitch->Left(1).CompareF(KSymbolicDebugSwitch)==0)
					{ // Symbolic debug flag
					theDebugFlag=CTextTranslator::EDebug;
					ValidArgument=ETrue;
					}
				else if (theSwitch->CompareF(KAlternativeErrorFormatSwitch)==0)
					{ // alternate error format flag
					ErrorFormatFlag=EErrorFormatMSD;
					ValidArgument=ETrue;
					}
				else if (theSwitch->CompareF(KConvertSwitch)==0)
					{ // Convert flag
					ConvertFlag=EConvert;
					ValidArgument=ETrue;
					}
				else if (theSwitch->CompareF(KVerboseSwitch)==0)
					{
					theConsole->SetVerbose(ETrue);
					ValidArgument=ETrue;
					}
				else if (theSwitch->CompareF(KQuietSwitch)==0)
					{ 
					theConsole->SetQuiet(ETrue);
					ValidArgument=ETrue;
					}
				}

			if (!ValidArgument)
				{
				_LIT(KErrInvalidArgIgnored,"Invalid argument %S ignored.\n");
				theConsole->PError(KErrInvalidArgIgnored,&token);
				}
			}
		else
			{ // the OPL program name.
			if (OplName.Length()==0)
				OplName=token;
			else
				{
				// Skip further program names.
				_LIT(KErrFileNamesIgnored,"Other filename %S ignored.\n");
				theConsole->PError(KErrFileNamesIgnored,&token);
				}
			}
		}

	if (OplName.Length())
		{
		// Pluck the drive letter from the process filename.
		// Note that if the filename doesn't have a drive letter, it must be
		// running on the same drive as the SDK, so use the drive letter from
		// the current working directory.
		TFileName exe=RProcess().FileName();
		TParse ParseExe;
		ParseExe.Set(exe,NULL,NULL);

		ConvertToUnicodeL(CurrentWorkingDirectory,TPtrC8(CurrentWorkingDirectory8));
		ForceTrailingSlash(CurrentWorkingDirectory);

		if (ParseExe.Drive().Length())
			{
			ExeDrive=ParseExe.Drive();
			//
			_LIT(KVerboseExeDrive,"[ExeDrive=%S]\n");
			theConsole->PVerbose(KVerboseExeDrive,&ExeDrive);
			}
		else
			{
			TParse ParseCWD;
			ParseCWD.Set(CurrentWorkingDirectory,NULL,NULL);
			ExeDrive=ParseCWD.Drive();
			//
			_LIT(KVerboseCwdSupplied,"[cwd supplied ExeDrive=%S]\n");
			theConsole->PVerbose(KVerboseCwdSupplied,&ExeDrive);
			}

		// Convert relative pathname to absolute.
		ConvertRelativePathToAbsolute(OplName);

		// Now massage the command line arguments...
		if (ConvertFlag!=ENoConvert)
			{
			// However, lose the default .opl extension for convert option
			// This allows command-lines such as "opltran -conv *" to convert Toolbar to Toolbar.opl
			// (it may be nice to lose this altogether in a future version).
			aParse.Set(OplName,NULL,&CurrentWorkingDirectory);
			}
		else
			{
			_LIT(KAnyOpl,"*.opl");
			const TPtrC anyOpl(KAnyOpl);
			aParse.Set(OplName,&anyOpl,&CurrentWorkingDirectory);
			}

		InputPath=aParse.DriveAndPath();
		SetOutputPath(aParse);
		// IncludePath construction.
		TParse IncludePathParse;
		TFileName parsePath=aParse.DriveAndPath();
		IncludePathParse.Set(IncludePath,&parsePath,NULL);
		IncludePath=IncludePathParse.FullName();

		_LIT(KVerboseSource,"[source=%S]\n");
		_LIT(KVerboseInputPath,"[InputPath=%S]\n");
		_LIT(KVerboseIncludePath,"[IncludePath=%S]\n");
		_LIT(KVerboseCwd,"[cwd=%S]\n");
		_LIT(KVerboseOutputPath,"[OutputPath=%S]\n");
		theConsole->PVerbose(KVerboseSource,&aParse.FullName());
		theConsole->PVerbose(KVerboseInputPath,&InputPath);
		theConsole->PVerbose(KVerboseIncludePath,&IncludePath);
		theConsole->PVerbose(KVerboseCwd,&CurrentWorkingDirectory);
		theConsole->PVerbose(KVerboseOutputPath,&OutputPath);

		ret = ETrue;
		}
	else
		{
		_LIT(KNoOPLFileName,"[No OPL filename recognised]\n");
		theConsole->PVerbose(KNoOPLFileName);
		}
	return ret;
	}

LOCAL_C TInt GetOplErrResource(const TInt aError)
	// Return the resource id with R_OTRN_UNKNOWN_ERROR if unknown
	{
	TInt resourceNo=R_OTRN_UNKNOWN_ERROR;
 	if (aError<0&&aError>-26)
		resourceNo=R_OTRN_UNKNOWN_ERROR-aError; // NB aError is negative here
	else if (aError<-31&&aError>=KOplMaxErr) // may be more errors added !
		resourceNo-=(aError+6); // -32 is mapped to -26 etc.
	return resourceNo;
	}

LOCAL_C TInt MapTranslatorError(const TInt aErr,TInt& aResId)
// Return the mapped error and set aResId to OPLTRAN's resource number or R_OTRN_UNKNOWN_ERROR
// If an OPL-specific error the high word has KOplErrorMask ORed in to avoid clashes with E32 errors
// If not mapped the passed error code is returned unchanged
	{
	const TInt KOpltErrBase=-70+EErrMissingQuote;	// tran errors in same order as for Opl1993 but start at 2
	TBool oplError=ETrue;
	TInt map;
	switch (aErr)
		{
	case EErrMissingQuote:
	case EErrBadStringLength:
	case EErrBadIdentifier:
	case EErrIdentifierTooLong:
	case EErrBadLogicalDevice:
	case EErrBadFieldName:
	case EErrBadNumber:
	case EErrBadSuffices:
	case EErrBadCharacter:
	case EErrFnArgument:
	case EErrTypeMismatch:
	case EErrMissingLabel:
	case EErrDuplicateName:
	case EErrBadDeclaration:
	case EErrBadArraySize:
	case EErrStructure:
	case EErrUnexpectedEof:
	case EErrSyntax:
	case EErrMismatchedBracket:
	case EErrBadFieldList:
	case EErrTooComplex:
	case EErrMissingComma:
	case EErrDataTooLarge:
	case EErrArgNotReferencedByValue:
	case EErrSubscript:
	case EErrInconsistentArgs:
		map=(KOpltErrBase-aErr);
		break;
	case EErrLineTooLong:
		map=KOplErrRecord;
		break;
	case EErrAssignToConstant:
		map=KOplErrBadAssignment;
		break;
	case EErrIncludeProcedure:
		map=KOplErrIncludeProcedure;
		break;
	case EErrTooManyOPXs:
		map=KOplErrTooManyOPXs;
		break;
	case EErrTooManyOpxFunctions:
		map=KOplErrTooManyOpxFunctions;
		break;
	case EErrUndefinedVariable:
		map=KOplErrUndefinedVariable;
		break;
	case EErrUndefinedProcedure:
		map=KOplErrUndefinedProcedure;
		break;
	case EErrIconMaskMissing:
		map=KOplErrIconMaskMissing;
		break;
	case EErrIncompatibleDeclaration:
		map=KOplErrIncompatibleDeclaration;
		break;
	default:
		// must be E32 error
		oplError=EFalse;
		map=aErr;
		// map=OplUtil::MapError(aErr);
		}
	if (oplError)
		{
		aResId=GetOplErrResource(TInt16(map));
		map=OPLERR(map);
		}
	else
		aResId=R_OTRN_UNKNOWN_ERROR;
	return map;
	}

LOCAL_C TInt GetTranslatorErrorResourceNumber(TInt aErr)
	{
	TInt resNo=0;
	MapTranslatorError(aErr,resNo);
	return resNo;
	}

⌨️ 快捷键说明

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