📄 opltran.cpp
字号:
// 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 + -