Latest bug-fixes with added tests.
// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// NetDial Script Commands
//
//
/**
@file Scommand.cpp
*/
#include "SSCRREAD.H"
#include "SSCREXEC.H"
#include "SIO.H"
#include "SLOGGER.H"
// Command names
_LIT(KSetCommand,"SET");
_LIT(KSendCommand,"SEND");
_LIT(KWaitCommand,"WAIT");
_LIT(KLoopCommand,"LOOP");
_LIT(KGotoCommand,"GOTO");
_LIT(KExitCommand,"EXIT");
_LIT(KDTRCommand,"DTR");
_LIT(KDropDTRCommand,"RAISE");
_LIT(KRaiseDTRCommand,"DROP");
_LIT(KReadCommand,"READ");
_LIT(KCharmapCommand,"CHARMAP");
_LIT(KTempVarName,"$$TMPVAR$$%d"); //< Temporary variable name
// Characters used in scripts
const TText KCommentChar='!';
const TText KPlusChar='+';
const TText KQuoteChar='\"';
const TText KOpenChevronChar='<';
const TText KCloseChevronChar='>';
const TText KOpenExprChar='{';
const TText KCloseExprChar='}';
const TText KEqualsChar='=';
const TText KTabChar='\t';
const TText KSpaceChar=' ';
const TText KColonChar=':';
const TText KOpenSquareBracketChar='[';
const TText KCloseSquareBracketChar=']';
const TInt KLabelArrayGranularity=5;
const TInt32 KMinScriptInteger=0;
const TInt32 KMaxScriptInteger=500000;
const TReal KMinScriptReal=0.0;
const TReal KMaxScriptReal=500000.0;
const TInt KMinLoopCounter=1;
const TInt KMaxLoopCounter=10000;
//
// Glossary
// ========
// String - a text string enclosed in ".."
// Character - a single character expressed numnerically enclosed in <..>
// Variable - named variable (preset or set in script) ending in $
// Expression - any one of the three above
// Compound expression - a number of expressions concatenated with +
// Token - an expression, compound expression, label or command
//
//
// CScriptCommandBase definitions
//
CScriptCommandBase::CScriptCommandBase(TScriptStatus& aStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
: iScriptReader(aScriptReader), iVarMan(aVarMan), iCharConv(aCharConv), iTempVarNum(0), iStatus(aStatus)
/**
Constructor for CScriptCharacterConverter.
*/
{}
CScriptCommandBase::~CScriptCommandBase()
/**
Destructor.
*/
{}
void CScriptCommandBase::ConstructL()
/**
Instantiates member variables.
*/
{}
void CScriptCommandBase::Cleanup()
/**
Cleanup.
*/
{}
TPtrC CScriptCommandBase::ParseCompoundExpressionL(TInt& aOffset)
/**
Parses a compound string expression starting at aOffset into a single string
constant and returns it.
*/
{
TPtrC wholeExpr;
wholeExpr.Set(ParseExpressionL(aOffset));
TBuf<KMaxVarNameLength> varName;
varName.Format(KTempVarName,iTempVarNum++);
iVarMan->AddVariableL(varName,wholeExpr);
HBufC* val=NULL;
HBufC* oldVal=NULL;
FOREVER
{
EatSpaces(aOffset);
if (aOffset>=iStatus.iLine.Length())
break;
if (iStatus.iLine[aOffset]!=KPlusChar)
break;
TPtrC nextExpr;
nextExpr.Set(ParseExpressionL(++aOffset));
val=HBufC::NewLC(wholeExpr.Length()+nextExpr.Length());
TPtr currentExpr(val->Des());
currentExpr.Append(wholeExpr);
currentExpr.Append(nextExpr);
varName.Format(KTempVarName,iTempVarNum++);
iVarMan->AddVariableL(varName,val->Des());
CleanupStack::Pop();
wholeExpr.Set(val->Des());
delete oldVal;
oldVal=val;
}
delete val;
User::LeaveIfError(iVarMan->FindVariable(varName,wholeExpr));
return wholeExpr;
}
TPtrC CScriptCommandBase::ParseExpressionL(TInt& aOffset)
/**
Parses string expression starting at aOffset according to starting character
and returns value.
*/
{
EatSpaces(aOffset);
if(iStatus.iLine.Length()<=aOffset)
User::Leave(KErrNoExpression);
switch(iStatus.iLine[aOffset]) //switch(iLine[aOffset+1])
{
case KQuoteChar:
aOffset++; // skip quote char
return ParseStringL(aOffset);
case KOpenChevronChar:
aOffset++; // skip chevron char
return ParseCharacterL(aOffset);
default:
return ParseVariableL(aOffset);
}
}
TPtrC CScriptCommandBase::ParseStringL(TInt& aOffset)
/**
Parses a string constant enclosed in "" and returns its value.
*/
{
return ParseEnclosedStringL(aOffset,KQuoteChar,KErrMissingQuote);
}
TPtrC CScriptCommandBase::ParseCharacterL(TInt& aOffset)
/**
Parses a character enclosed in <> and returns its value.
*/
{
TPtrC charString=ParseEnclosedStringL(aOffset,KCloseChevronChar,KErrMissingChevron);
TRadix radix=EDecimal;
TInt len=charString.Length();
if (len>2)
{
if(charString[0]=='0')
{
switch(charString[1])
{
case 'x':
case 'X':
len-=2;
radix=EHex;
break;
case 'd':
case 'D':
len-=2;
radix=EDecimal;
break;
case 'o':
case 'O':
len-=2;
radix=EOctal;
break;
case 'b':
case 'B':
len-=2;
radix=EBinary;
break;
default:
break;
}
}
}
TLex lex(charString.Right(len));
TUint val=0;
if (lex.Val(val,radix)!=KErrNone)
User::Leave(KErrInvalidNumber);
TBuf<1> character=(TText*)&val;
TBuf<KMaxVarNameLength> varName;
varName.Format(KTempVarName,iTempVarNum++);
iVarMan->AddVariableL(varName,character);
TPtrC temp;
iVarMan->FindVariable(varName,temp);
return temp;
}
TPtrC CScriptCommandBase::ParseVariableL(TInt& aOffset)
/**
Parses a variable and returns its value.
*/
{
TInt end=FindTokenEnd(aOffset);
TPtrC varName=iStatus.iLine.Mid(aOffset,end-aOffset);
aOffset=end;
TPtrC varValue;
if (iVarMan->FindVariable(varName,varValue)==KErrNotFound)
{
if(!iStatus.iSkip)
User::Leave(KErrVariableNotFound);
return TPtrC();
}
return varValue;
}
TInt32 CScriptCommandBase::ParseIntegerL(TInt& aOffset)
/**
Parses an integer and returns its value.
*/
{
EatSpaces(aOffset);
TLex lex(iStatus.iLine);
lex.Inc(aOffset);
TInt32 val=0;
if (lex.Val(val)!=KErrNone)
{
User::Leave(KErrInvalidNumber);
return KMinScriptInteger;
}
if ((val<KMinScriptInteger) || (val>KMaxScriptInteger))
{
User::Leave(KErrNumberOutOfRange);
return KMinScriptInteger;
}
aOffset=lex.Offset();
return val;
}
TReal CScriptCommandBase::ParseRealL(TInt& aOffset)
/**
Parses a real number and returns its value.
*/
{
EatSpaces(aOffset);
TLex lex(iStatus.iLine);
lex.Inc(aOffset);
TReal val=0.0;
if (lex.Val(val)!=KErrNone)
{
User::Leave(KErrInvalidNumber);
return KMinScriptReal;
}
if ((val<KMinScriptReal) || (val>KMaxScriptReal))
{
User::Leave(KErrNumberOutOfRange);
return KMinScriptReal;
}
aOffset=lex.Offset();
return val;
}
TPtrC CScriptCommandBase::ParseCharacterTypeL(TInt& aOffset)
/**
Parses character type.
*/
{
EatSpaces(aOffset);
if(iStatus.iLine.Length()<=aOffset) // nothing specified so assume default
return TPtrC();
TInt startChar=aOffset;
if (iStatus.iLine[startChar++]!=KOpenSquareBracketChar)
return TPtrC(); // No open bracket so assume default
aOffset=startChar;
return ParseEnclosedStringL(aOffset,KCloseSquareBracketChar,KErrMissingBracket);
}
HBufC8* CScriptCommandBase::ConvertLC(const TDesC& aString,TInt& aOffset)
/**
Converts to correct character set.
*/
{
TBuf<KMaxCharacterTypeLength> type=ParseCharacterTypeL(aOffset);
return iCharConv->ConvertLC(aString,type);
}
TInt CScriptCommandBase::FindTokenEnd(TInt aOffset)
/**
Finds end of string beginning at aOffset and returns length.
*/
{
__ASSERT_DEBUG(aOffset<=iStatus.iLine.Length(), NetDialPanic(EOffsetExceedsLineLength));
if(aOffset==iStatus.iLine.Length())
return aOffset;
TInt end;
for (end=aOffset; IsValidChar(iStatus.iLine[end]); end++)
{
if (end>=(iStatus.iLine.Length()-1))
{
end++;
break;
}
}
return end;
}
TBool CScriptCommandBase::IsValidChar(const TText& aChar)
/**
Checks if aChar is a valid character in a script command.
*/
{
return TChar(aChar).IsAlphaDigit() || (aChar==KDollarChar) || (aChar==KUnderscoreChar) || (aChar==KCommentChar);
}
void CScriptCommandBase::EatSpaces(TInt& aOffset)
/**
Ignores spaces, tabs, line feeds and carriage returns and sets aOffset to
next non-blank character, or end of line
*/
{
if(aOffset>=iStatus.iLine.Length())
return;
while((iStatus.iLine[aOffset]==KSpaceChar) || (iStatus.iLine[aOffset]==KTabChar) || (iStatus.iLine[aOffset]==KLineFeed) || (iStatus.iLine[aOffset]==KCarriageReturn))
{
aOffset++;
if(aOffset>=iStatus.iLine.Length())
break;
}
}
void CScriptCommandBase::EatSpacesAndLinesL()
/**
Ignores spaces and empty lines and sets aOffset to next non-blank character.
*/
{
EatSpaces(iStatus.iOffset);
while(iStatus.iOffset>=iStatus.iLine.Length())
{
User::LeaveIfError(iScriptReader->GetNextLine()); // This also resets iStatus.iOffset
EatSpaces(iStatus.iOffset);
}
}
void CScriptCommandBase::EatSpacesAndLinesAndCommentsL()
/**
Ignores spaces, empty lines and comments and sets aOffset to next non-blank or
non-comment character
*/
{
EatSpacesAndLinesL();
while (iStatus.iLine[iStatus.iOffset]==KCommentChar)
{
iStatus.iOffset=iStatus.iLine.Length();
EatSpacesAndLinesL(); // this will reset iStatus.iOffset if necessary
}
}
TPtrC CScriptCommandBase::ParseEnclosedStringL(TInt& aOffset,TText aChar,TInt aError)
/**
Parses enclosed string
*/
{
if(aOffset>=iStatus.iLine.Length())
User::Leave(aError); // no end character before EOL
TInt end=aOffset;
while (end<iStatus.iLine.Length())
{
if (iStatus.iLine[end]==aChar)
break;
end++;
}
if (end>=iStatus.iLine.Length())
User::Leave(aError); // no end character before EOL
TInt start=aOffset;
aOffset=end+1;
return iStatus.iLine.Mid(start,end-start);
}
//
// CSetCommand definitions
//
CSetCommand* CSetCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
/**
2 phased constructor for CSetCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CSetCommand object.
*/
{
CSetCommand* c=new(ELeave) CSetCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CSetCommand::CSetCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv)
/**
Constructor for CSetCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
*/
{}
CSetCommand::~CSetCommand()
/**
Destructor.
*/
{}
TBool CSetCommand::ParseL()
/**
Parses a SET command. Determines variable name and value and adds to variable list.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KSetCommand)==KErrNone)
{
if (!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(KLogStringExecutingSet,"Script:\tExecuting Set");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),KLogStringExecutingSet());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
end=FindTokenEnd(iStatus.iOffset);
TPtrC varName=iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset);
EatSpaces(end);
if (iStatus.iLine[end++]!=KEqualsChar)
User::Leave(KErrNoEquals);
EatSpaces(end);
TPtrC value=ParseCompoundExpressionL(end);
if (!iStatus.iSkip)
{
iVarMan->AddVariableL(varName,value);
__FLOG_STMT(_LIT(KLogStringSetVar,"Script:\tSet Var: %S To %S"));
__FLOG_STATIC2(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC>(KLogStringSetVar()),&varName,&value);
}
iStatus.iOffset=end;
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
//
// CSendCommand definitions
//
CSendCommand* CSendCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO)
/**
2 phased constructor for CSendCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CSendCommand object.
*/
{
CSendCommand* c=new(ELeave) CSendCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv,aScriptIO);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CSendCommand::CSendCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iScriptIO(aScriptIO)
/**
Constructor for CSendCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
*/
{}
CSendCommand::~CSendCommand()
/**
Destructor.
*/
{}
TBool CSendCommand::ParseL()
/**
Parses SEND command. Parses expression to send and sends it.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if(iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KSendCommand)==0)
{
if(!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(KLogStringExecutingSend,"Script:\tExecuting Send");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),KLogStringExecutingSend());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
TPtrC temp;
temp.Set(ParseCompoundExpressionL(iStatus.iOffset));
HBufC8* buf=ConvertLC(temp,iStatus.iOffset);
iSendString.Set(buf->Des());
if(!iStatus.iSkip)
{
iScriptIO->Write(iSendString);
#ifdef __FLOG_ACTIVE
_LIT(KLogStringSending,"Script:\tSending %S");
TBuf16<KLogBufferSize> temp;
temp.Copy(iSendString.Left(Min(iSendString.Length(),KLogBufferSize)));
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC>(KLogStringSending()),&temp);
#endif
}
CleanupStack::PopAndDestroy();
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
//
// CLabelSearch definitions
//
CLabelSearch* CLabelSearch::NewLC(const TDesC& aLabelName)
/**
2 phased constructor for CLabelSearch, first phase.
@param aLabelName is label name.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CLabelSearch object.
*/
{
CLabelSearch* label=new(ELeave) CLabelSearch();
CleanupStack::PushL(label);
label->ConstructL(aLabelName);
return label;
}
CLabelSearch::CLabelSearch()
: iStatus(ENotFound), iPosition()
/**
Constructor for CLabelSearch, used in the first phase of construction.
*/
{}
void CLabelSearch::ConstructL(const TDesC& aLabelName)
/**
Instantiates member variables.
*/
{
iChatString=NULL;
iLabelName=HBufC::NewL(aLabelName.Length());
(*iLabelName)=aLabelName;
}
CLabelSearch::~CLabelSearch()
/**
Destructor.
Don't delete iChatString - that is dealt with by CScriptIO.
*/
{
delete iLabelName;
}
void CLabelSearch::CreateCommChatStringL(const TDesC8& aDes,TBool aIsFolded)
/**
Creates CCommChatString object.
*/
{
iChatString=CCommChatString::NewL(aDes,aIsFolded);
}
//
// CWaitCommand definitions
//
CWaitCommand* CWaitCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO,CScriptLabelMan* aLabelMan, CScriptExecutor* aScriptExec)
/**
2 phased constructor for CWaitCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
@param aLabelMan a pointer to label manager.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CWaitCommand object.
*/
{
CWaitCommand* c=new(ELeave) CWaitCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv,aScriptIO,aLabelMan,aScriptExec);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CWaitCommand::CWaitCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO,CScriptLabelMan* aLabelMan, CScriptExecutor* aScriptExec)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iScriptIO(aScriptIO), iLabelMan(aLabelMan), iScriptExec(aScriptExec)
/**
Constructor for CWaitCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
@param aLabelMan a pointer to label manager.
*/
{}
CWaitCommand::~CWaitCommand()
/**
Destructor.
Clears label array.
*/
{
DeleteLabelArray();
}
TBool CWaitCommand::ParseL()
/**
Parses WAIT command. Parse according to whether in skip mode or not.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KWaitCommand)==KErrNone)
{
iStatus.iOffset=end;
if (iStatus.iSkip)
ParseSkipL();
else
ParseActionL();
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
void CWaitCommand::Cleanup()
/**
Cancels the read and clears out the labels
*/
{
if (!iStatus.iSkip)
{
iScriptIO->Cancel();
DeleteLabelArray();
iLabelArray=NULL;
}
}
void CWaitCommand::ParseActionL()
/**
Parses WAIT command when not in skip mode. Parses wait period, strings and labels and
queue a read.
*/
{
__FLOG_STMT(_LIT8(KLogStringExecutingWait,"Script:\tExecuting Wait");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),KLogStringExecutingWait());
EatSpaces(iStatus.iOffset);
TReal waitPeriod=ParseRealL(iStatus.iOffset);
EatSpacesAndLinesAndCommentsL();
if (iStatus.iLine[iStatus.iOffset++]!=KOpenExprChar)
User::Leave(KErrNoOpenExpression);
iLabelArray=new(ELeave) CLabelSearchArray(KLabelArrayGranularity);
TBool completed=EFalse;
while(!completed)
{
EatSpacesAndLinesAndCommentsL();
if (iStatus.iLine[iStatus.iOffset]==KCloseExprChar)
{
completed=ETrue;
iStatus.iOffset++;
}
else
{
TPtrC temp=ParseCompoundExpressionL(iStatus.iOffset);
HBufC8* buf=ConvertLC(temp,iStatus.iOffset);
CLabelSearch* label=ParseLabelLC();
TPtrC8 waitString(buf->Des());
label->CreateCommChatStringL(waitString,EFalse);
iLabelArray->AppendL(label);
// for logging
TBuf<KLogBufferSize> labelName;
labelName.Copy(label->LabelName().Left(Min(KLogBufferSize,label->LabelName().Length())));
//
#ifdef __FLOG_ACTIVE
_LIT(KLogStringGog,"Script:\tIf %S is found, Goto %S");
TBuf16<KLogBufferSize> string;
string.Copy(waitString.Left(Min(waitString.Length(),KLogBufferSize)));
__FLOG_STATIC2(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC>(KLogStringGog()),&string,&labelName);
#endif
CleanupStack::Pop(); // label - will be deleted from array
CleanupStack::PopAndDestroy(); // buf - will have been copied into label array
}
}
// Tell the script executor how long we are going to wait since it
// may need to force the server to resend the login prompt and will
// need to know how long to wait the second time around
iScriptExec->SetRetransmittedLoginTimeout(waitPeriod);
iScriptIO->Read(iLabelArray,waitPeriod);
}
void CWaitCommand::ParseSkipL()
/**
Parses a WAIT command when in skip mode. Parses expressions and labels but do not queue read.
*/
{
EatSpaces(iStatus.iOffset);
ParseRealL(iStatus.iOffset); // ignore the actual value returned
EatSpacesAndLinesAndCommentsL();
if (iStatus.iLine[iStatus.iOffset++]!=KOpenExprChar)
User::Leave(KErrNoOpenExpression);
TBool completed=EFalse;
while (!completed)
{
EatSpacesAndLinesAndCommentsL();
if (iStatus.iLine[iStatus.iOffset]==KCloseExprChar)
{
completed=ETrue;
iStatus.iOffset++;
}
else
{
ParseCompoundExpressionL(iStatus.iOffset); // ignore the return value in skip mode
ParseLabelLC();
CleanupStack::PopAndDestroy(); // ignore the label returned
}
}
}
CLabelSearch* CWaitCommand::ParseLabelLC()
/**
Parses label. Parses label name and looks for it in the label list.
Returns results of search.
*/
{
EatSpaces(iStatus.iOffset);
TInt start=iStatus.iOffset;
iStatus.iOffset=FindTokenEnd(start);
TPtrC var=iStatus.iLine.Mid(start,iStatus.iOffset-start);
CLabelSearch* labelSearch=CLabelSearch::NewLC(var);
TLinePosition pos;
if(iLabelMan->FindLabel(var,pos)==KErrNotFound)
{
pos.Reset();
labelSearch->Set(CLabelSearch::ENotFound,pos);
}
else
labelSearch->Set(CLabelSearch::EResolved,pos);
return labelSearch;
}
TPtrC CWaitCommand::LabelFromIndexL(TInt aIndex)
/**
Gets label from array by index.
*/
{
if ((aIndex<0) && (aIndex>iLabelArray->Count()))
User::Leave(KErrIllegalWaitLabelIndex);
return (*iLabelArray)[aIndex]->LabelName();
}
void CWaitCommand::DeleteLabelArray()
/**
Deletes label array.
*/
{
if (iLabelArray!=NULL)
{
TInt count=iLabelArray->Count();
for(TInt i=0; i<count; i++)
{
delete (*iLabelArray)[i];
}
iLabelArray->Delete(0,count);
delete iLabelArray;
}
}
//
// CLoopCommand definitions
//
CLoopCommand* CLoopCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
/**
2 phased constructor for CLoopCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CLoopCommand object.
*/
{
CLoopCommand* c=new(ELeave) CLoopCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CLoopCommand::CLoopCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iLoop(EFalse)
/**
Constructor for CLoopCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
*/
{}
CLoopCommand::~CLoopCommand()
/**
Destructor.
*/
{}
TBool CLoopCommand::ParseL()
/**
Parses LOOP command. Checks how many times to loop and records position of beginning of loop.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KLoopCommand)==KErrNone)
{
if (iLoop)
User::Leave(KErrNestedLoop);
if (!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(KLogStringExecutingLoop,"Script:\tExecuting Loop");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),KLogStringExecutingLoop());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
iLoopCounter=ParseIntegerL(iStatus.iOffset);
if ((iLoopCounter<KMinLoopCounter) || (iLoopCounter>KMaxLoopCounter))
User::Leave(KErrLoopCounterOutOfRange);
EatSpacesAndLinesAndCommentsL();
if (iStatus.iLine[iStatus.iOffset++]!=KOpenExprChar)
User::Leave(KErrNoOpenExpression);
iLoop=ETrue;
iScriptReader->CurrentPos(iLoopPosition,iStatus.iOffset);
if (!iStatus.iSkip)
{
__FLOG_STMT(_LIT(KLogStringLoopCounter,"Script:\tLoop Counter %d");)
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),KLogStringLoopCounter(),iLoopCounter);
}
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
TBool CLoopCommand::CheckLoopL()
/**
Checks how many times loop has been executed and returns to beginning if necessary.
*/
{
if (iLoop)
{
EatSpacesAndLinesAndCommentsL();
if(iStatus.iLine[iStatus.iOffset]==KCloseExprChar)
{
if((--iLoopCounter==0) || (iStatus.iSkip))
{
iLoop=EFalse;
iStatus.iOffset++;
}
else
{
iScriptReader->SetCurrentPos(iLoopPosition);
__FLOG_STMT(_LIT8(logString1,"Script:\tRepeat Loop");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString1());
__FLOG_STMT(_LIT8(logString2,"Script:\tLoop Counter %d");)
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),logString2(),iLoopCounter);
}
return ETrue; // Consumed Something
}
}
return EFalse; // Nothing doing...
}
//
// CGotoCommand definitions
//
CGotoCommand* CGotoCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptLabelMan* aLabelMan)
/**
2 phased constructor for CGotoCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aLabelMan a pointer to label manager.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CGotoCommand object.
*/
{
CGotoCommand* c=new(ELeave) CGotoCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv,aLabelMan);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CGotoCommand::CGotoCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptLabelMan* aLabelMan)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iLabelMan(aLabelMan)
/**
Constructor for CGotoCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aLabelMan a pointer to label manager.
*/
{}
CGotoCommand::~CGotoCommand()
/**
Destructor.
*/
{}
TBool CGotoCommand::ParseL()
/**
Parses GOTO command. Parses label and goto label.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KGotoCommand)==KErrNone)
{
if(!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString,"Script:\tExecuting Goto");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
end=FindTokenEnd(iStatus.iOffset);
TPtrC var=iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset);
// HBufC* labelName=HBufC::NewLC(var.Length());
// (*labelName)=var;
// GotoL(labelName->Des());
// CleanupStack::PopAndDestroy();
Goto(var);
iStatus.iOffset=end;
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
void CGotoCommand::Goto(const TDesC& aLabelName)
/**
Finds label in those passed already, or skip lines until it is found.
*/
{
TLinePosition pos;
if(!iStatus.iSkip)
{
if (iLabelMan->FindLabel(aLabelName,pos)==KErrNotFound)
{
iSearchName.Copy(aLabelName);
iStatus.iSkipModeToggleReq=ETrue;
__FLOG_STMT(_LIT(logString1,"Script:\tSearching for Label %S");)
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC>(logString1()),&aLabelName);
__FLOG_STMT(_LIT8(logString2,"Script:\tEntering Skip Mode");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2());
}
else
iScriptReader->SetCurrentPos(pos);
}
}
TBool CGotoCommand::ParseLabelL()
/**
Parses label and adds it to label list. Compares label against one to be found.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt start=iStatus.iOffset;
TInt end=FindTokenEnd(start);
if ((iStatus.iLine.Length()>=(end+1)) && (iStatus.iLine[end]==KColonChar))
{
TLinePosition pos;
iScriptReader->CurrentPos(pos,end+1);
iLabelMan->AddLabelL(iStatus.iLine.Mid(start,end-start),pos);
iStatus.iOffset=++end;
TLinePosition dummyPos;
if (iStatus.iSkip && (iLabelMan->FindLabel(iSearchName,dummyPos)==KErrNone))
{
iStatus.iSkipModeToggleReq=ETrue;
__FLOG_STMT(_LIT8(logString,"Script:\tExiting Skip Mode");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString());
}
return ETrue;
}
return EFalse;
}
void CGotoCommand::ServiceSkipReqs()
/**
Toggles skip mode.
*/
{
if(iStatus.iSkipModeToggleReq)
{
iStatus.iSkipModeToggleReq=EFalse;
iStatus.iSkip=!iStatus.iSkip;
}
}
//
// CDTRCommand definitions
//
CDTRCommand* CDTRCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO)
/**
2 phased constructor for CDTRCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CDTRCommand object.
*/
{
CDTRCommand* c=new(ELeave) CDTRCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv,aScriptIO);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CDTRCommand::CDTRCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptIO* aScriptIO)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iScriptIO(aScriptIO)
/**
Constructor for CDTRCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptIO a pointer to serial comms I/O handler.
*/
{}
CDTRCommand::~CDTRCommand()
/**
Destructor.
*/
{}
TBool CDTRCommand::ParseL()
/**
Parses DTR command. Drops or raises appropriately.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KDTRCommand)==KErrNone)
{
if(!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString1,"Script:\tExecuting DTR");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString1());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KRaiseDTRCommand)==KErrNone)
{
if(!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString2,"Script:\tRaising DTR");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString2());
iScriptIO->RaiseDTR(NULL);
}
}
else if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KDropDTRCommand)==KErrNone)
{
if(!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString3,"Script:\tDropping DTR");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString3());
iScriptIO->DropDTR(NULL);
}
}
else
User::Leave(KErrNoDropOrRaise);
iStatus.iOffset=end;
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
//
// CReadPCTCommand definitions
//
CReadPCTCommand* CReadPCTCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptExecutor* aScriptExec)
/**
2 phased constructor for CReadPCTCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptExec a pointer to script executioner.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CReadPCTCommand object.
*/
{
CReadPCTCommand* c=new(ELeave) CReadPCTCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv,aScriptExec);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CReadPCTCommand::CReadPCTCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv,CScriptExecutor* aScriptExec)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv), iScriptExec(aScriptExec)
/**
Constructor for CDTRCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@param aScriptExec a pointer to script executioner.
*/
{}
CReadPCTCommand::~CReadPCTCommand()
/**
Destructor.
*/
{}
TBool CReadPCTCommand::ParseL()
/**
Parses Read command.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KReadCommand)==KErrNone)
{
if (!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString,"Script:\tExecuting Read");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString());
iCharSet=ParseCharacterTypeL(iStatus.iOffset);
iScriptExec->ReadPct();
}
iStatus.iOffset=end;
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
TBool CReadPCTCommand::CheckReadL()
/**
Checks Read.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KReadCommand)==KErrNone)
return ETrue;
else
return EFalse;
}
TPtrC CReadPCTCommand::CharSet()
/**
Returns used character set.
*/
{
return iCharSet;
}
//
// CCharMapCommand definitions
//
CCharMapCommand* CCharMapCommand::NewL(TScriptStatus& aScriptStatus, CScriptReader* aScriptReader, CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
/**
2 phased constructor for CCharMapCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CCharMapCommand object.
*/
{
CCharMapCommand* c=new(ELeave) CCharMapCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CCharMapCommand::CCharMapCommand(TScriptStatus& aScriptStatus, CScriptReader* aScriptReader, CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv)
/**
Constructor for CCharMapCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
*/
{}
CCharMapCommand::~CCharMapCommand()
/**
Destructor.
*/
{}
TBool CCharMapCommand::ParseL()
/**
Parse.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KCharmapCommand)==KErrNone)
{
iStatus.iOffset=end;
if (!iStatus.iSkip)
{
iCharConv->SetDefaultCharSet(ParseCharacterTypeL(iStatus.iOffset));
}
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}
//
// CExitCommand definiton
//
CExitCommand* CExitCommand::NewL(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
/**
2 phased constructor for CExitCommand, first phase.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
@exception Leaves if ConstructL() leaves, or not enough memory is available.
@return a new CExitCommand object.
*/
{
CExitCommand* c=new(ELeave) CExitCommand(aScriptStatus,aScriptReader,aVarMan,aCharConv);
CleanupStack::PushL(c);
c->ConstructL();
CleanupStack::Pop();
return c;
}
CExitCommand::CExitCommand(TScriptStatus& aScriptStatus,CScriptReader* aScriptReader,CScriptVarMan* aVarMan,CScriptCharacterConverter* aCharConv)
: CScriptCommandBase(aScriptStatus,aScriptReader,aVarMan,aCharConv)
/**
Constructor for CExitCommand, used in the first phase of construction.
@param aScriptStatus is script status.
@param aScriptReader a pointer to script reader.
@param aVarMan a pointer to variable manager.
@param aCharConv a pointer to script character converter.
*/
{}
CExitCommand::~CExitCommand()
/**
Destructor.
*/
{}
TBool CExitCommand::ParseL()
/**
Parses EXIT command. Parses number or variable and leaves with the appropriate value.
*/
{
EatSpacesAndLinesAndCommentsL();
TInt end=FindTokenEnd(iStatus.iOffset);
if (iStatus.iLine.Mid(iStatus.iOffset,end-iStatus.iOffset).CompareF(KExitCommand)==KErrNone)
{
if (!iStatus.iSkip)
{
__FLOG_STMT(_LIT8(logString1,"Script:\tExecuting Exit");)
__FLOG_STATIC(KNetDialLogFolder(),KNetDialLogFile(),logString1());
}
iStatus.iOffset=end;
EatSpaces(iStatus.iOffset);
TPtrC exitStatus;
TRAPD(ret,(exitStatus.Set(ParseCompoundExpressionL(iStatus.iOffset))));
if (!iStatus.iSkip)
{
if (ret==KErrNone)
{
TInt32 val;
TLex lex(exitStatus);
if(lex.Val(val)!=KErrNone)
User::Leave(KErrInvalidNumber);
if(val>0)
User::Leave(KErrNumberOutOfRange);
if(val==0)
val=(TInt32)KErrScriptCompleted;
User::Leave(val);
}
else if (ret==KErrNoExpression)
User::Leave(KErrScriptCompleted);
else
{
__FLOG_STMT(_LIT8(logString2,"Script:\tExit With Error %d");)
__FLOG_STATIC1(KNetDialLogFolder(),KNetDialLogFile(),TRefByValue<const TDesC8>(logString2()),ret);
User::Leave(ret);
}
}
return ETrue; // Consumed
}
return EFalse; // Not Consumed
}