fix: stop using "magic" numbers in string operations for the copyannofile2log feature
fix: When using the copylogfromannofile workaround, extract the build ID and build duration and add to the log as these are useful for analysis. The log should now be identical to the stdout file.
fix: Remove extra blank lines from output in copylogfromannofile mode.
/*
* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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:
*
*/
#include "sisutils.h"
#include "pkgfileparser.h"
// Parse options lookups
#define MAXTOKENLEN 30
struct SParseToken
{
WCHAR pszOpt[MAXTOKENLEN];
DWORD dwOpt;
};
const SParseToken KTokens[] =
{
{L"if", IF_TOKEN},
{L"elseif", ELSEIF_TOKEN},
{L"else", ELSE_TOKEN},
{L"endif", ENDIF_TOKEN},
{L"exists", EXISTS_TOKEN},
{L"devprop",DEVCAP_TOKEN},
{L"appcap", APPCAP_TOKEN},
{L"package",DEVCAP_TOKEN},
{L"appprop",APPCAP_TOKEN},
{L"not", NOT_TOKEN},
{L"and", AND_TOKEN},
{L"or", OR_TOKEN},
{L"type", TYPE_TOKEN},
{L"key", KEY_TOKEN},
};
#define NUMPARSETOKENS (sizeof(KTokens)/sizeof(SParseToken))
/**
Constructor: PkgParser class
Initilize the parameters to data members.
@internalComponent
@released
@param aFile - Name of the package script file
*/
PkgParser::PkgParser(String aFile) : iPkgFile(aFile), m_nLineNo(0)
{
}
/**
Destructor: PkgParser class
Deallocates the memory for data members
@internalComponent
@released
*/
PkgParser::~PkgParser()
{
if(iPkgHandle != INVALID_HANDLE_VALUE)
{
::CloseHandle(iPkgHandle);
}
DeleteAll();
}
/**
OpenFile: Opens the package script file
@internalComponent
@released
*/
int PkgParser::OpenFile()
{
iPkgHandle = ::CreateFileW(string2wstring(iPkgFile).data(),GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
return (iPkgHandle != INVALID_HANDLE_VALUE) ? 1 : 0;
}
/**
GetEmbeddedSisList: Returns the embedded sis file list
@internalComponent
@released
@param embedSisList - reference to sis file list structure
*/
void PkgParser::GetEmbeddedSisList(SISFILE_LIST& embedSisList)
{
embedSisList = iEmbedSisFiles;
}
/**
GetInstallOptions: Returns the install options read from the package file
@internalComponent
@released
@param aOptions - reference to the string list structure
*/
void PkgParser::GetInstallOptions(FILE_LIST& aOptions)
{
aOptions = iInstallOptions;
}
/**
GetLanguageList: Returns the language list read from the package file
@internalComponent
@released
@param langList - reference to the language list structure
*/
void PkgParser::GetLanguageList(LANGUAGE_LIST& langList)
{
langList = iLangList;
}
/**
GetHeader: Returns the header details read from the package file
@internalComponent
@released
@param pkgHeader - reference to the package header structure
*/
void PkgParser::GetHeader(PKG_HEADER& pkgHeader)
{
pkgHeader = iPkgHeader;
}
/**
GetCommandList: Returns the package body details read from the package file
@internalComponent
@released
@param cmdList - reference to the command list structure
*/
void PkgParser::GetCommandList(CMDBLOCK_LIST& cmdList)
{
cmdList = iPkgBlock;
}
/**
ParsePkgFile: Parses the package file
@internalComponent
@released
*/
void PkgParser::ParsePkgFile()
{
if(!OpenFile())
{
throw SisUtilsException((char*)iPkgFile.data(), "Could not open file");
}
GetNextChar();
// skip unicode marker if present
if(m_pkgChar==0xFEFF) GetNextChar();
GetNextToken ();
while(m_token!=EOF_TOKEN)
{
ParseEmbeddedBlockL();
switch (m_token)
{
case '&':
GetNextToken ();
ParseLanguagesL();
break;
case '#':
GetNextToken ();
ParseHeaderL();
break;
case '%':
GetNextToken ();
ParseVendorNameL();
break;
case '=':
GetNextToken ();
ParseLogoL();
break;
case '(':
GetNextToken ();
ParseDependencyL();
break;
case ':':
GetNextToken ();
ParseVendorUniqueNameL();
break;
case '[':
GetNextToken ();
ParseTargetDeviceL();
break;
case EOF_TOKEN:
break;
default:
ParserError("Unexpected token");
break;
}
}
}
/**
ParseLanguagesL: Parses the language section
@internalComponent
@released
*/
void PkgParser::ParseLanguagesL()
{
unsigned long langCode = 0;
unsigned long dialect = 0;
while (true)
{
if (m_token==ALPHA_TOKEN)
{
langCode = PkgLanguage::GetLanguageCode(m_tokenValue.pszString);
}
else if (m_token==NUMERIC_TOKEN && m_tokenValue.dwNumber>=0 && m_tokenValue.dwNumber<=1000)
{
langCode = (m_tokenValue.dwNumber);
}
GetNextToken ();
// Check if a dialect is defined
if (m_token == '(')
{
GetNumericToken();
// Modify the last added language code, combining it with dialect code
dialect = (m_tokenValue.dwNumber);
GetNextToken ();
GetNextToken ();
}
AddLanguage(wstring2string(PkgLanguage::GetLanguageName(langCode)), langCode, dialect);
if (m_token!=',')
return;
GetNextToken ();
}
}
/**
ParseHeaderL: Parses the package header section
@internalComponent
@released
*/
void PkgParser::ParseHeaderL()
{
if (!iLangList.size())
{
//No languages defined, assuming English."
AddLanguage("EN", PkgLanguage::ELangEnglish, 0);
}
// process application names
ExpectToken('{');
for (WORD wNumLangs = 0; wNumLangs < iLangList.size(); wNumLangs++)
{
GetNextToken ();
ExpectToken(QUOTED_STRING_TOKEN);
iPkgHeader.pkgNameList.push_back(wstring2string(m_tokenValue.pszString));
GetNextToken ();
if (wNumLangs < (iLangList.size()-1) )
{
ExpectToken(',');
}
}
ExpectToken('}');
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken('(');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
iPkgHeader.pkgUid = m_tokenValue.dwNumber;
GetNextToken ();
ExpectToken(')');
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
iPkgHeader.vMajor = m_tokenValue.dwNumber;
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
iPkgHeader.vMinor = m_tokenValue.dwNumber;
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
iPkgHeader.vBuild = m_tokenValue.dwNumber;
GetNextToken ();
// Parse any options
while (m_token==',')
{
GetNextToken ();
if (m_token==TYPE_TOKEN)
{
GetNextToken ();
ExpectToken('=');
GetNextToken ();
iPkgHeader.pkgType = wstring2string(m_tokenValue.pszString);
GetNextToken ();
}
else
GetNextToken ();
}
}
/**
ParseEmbeddedBlockL: Parses the package body block
@internalComponent
@released
*/
void PkgParser::ParseEmbeddedBlockL ()
{
while(m_token!=EOF_TOKEN)
{
switch (m_token)
{
case QUOTED_STRING_TOKEN:
ParseFileL ();
break;
case '@':
GetNextToken ();
ParsePackageL ();
break;
case '!':
GetNextToken ();
ParseOptionsBlockL();
break;
case '+':
GetNextToken ();
ParsePropertyL ();
break;
case IF_TOKEN:
GetNextToken ();
ParseIfBlockL ();
break;
case ';' :
ParseCommentL ();
break;
default :
return;
}
}
}
/**
ParseFileL: Parses the file list section
@internalComponent
@released
*/
void PkgParser::ParseFileL()
{
PCMD_BLOCK pCmdBlock = 0;
PINSTALLFILE_LIST pFileList = 0;
std::wstring sourceFile (m_tokenValue.pszString);
// Linux and windows both support forward slashes so if source path is given '\' need to convert
// in forward slash for compatibility.
wchar_t *pBuffer = (wchar_t*)sourceFile.c_str();
wchar_t *pCurrent = pBuffer;
while (pBuffer && *pBuffer && (pCurrent = wcschr(pBuffer,L'\\')) != NULL)
{
*pCurrent = L'/';
pBuffer = pCurrent + 1;
}
GetNextToken ();
ExpectToken('-');
GetNextToken ();
ExpectToken(QUOTED_STRING_TOKEN);
std::wstring destinationFile (m_tokenValue.pszString);
// SWI only supports backward slashesh so need to convert destination path in backward slash if
// user gives '/' in Linux.
pBuffer = (wchar_t*)destinationFile.c_str();
pCurrent = pBuffer;
while (pBuffer && *pBuffer && (pCurrent = wcschr(pBuffer,L'/')) != NULL)
{
*pCurrent = L'\\';
pBuffer = pCurrent + 1;
}
GetNextToken ();
// Test for options
if (m_token!=',')
{
pCmdBlock = new CMD_BLOCK;
pFileList = new INSTALLFILE_LIST;
pCmdBlock->cmdType = INSTALLFILE;
pCmdBlock->iInstallFileList = pFileList;
pFileList->langDepFlg = 0;
pFileList->srcFiles.push_back(wstring2string(sourceFile));
pFileList->destFile = wstring2string(destinationFile);
iPkgBlock.push_back(pCmdBlock);
}
else
{
bool needAdd = false;
while(m_token==',')
{
GetNextToken ();
std::wstring installOption = m_tokenValue.pszString;
if((installOption == L"FF") || (installOption == L"FILE"))
{
needAdd = true;
}
GetNextToken ();
}
if (needAdd)
{
pCmdBlock = new CMD_BLOCK;
pFileList = new INSTALLFILE_LIST;
pCmdBlock->cmdType = INSTALLFILE;
pCmdBlock->iInstallFileList = pFileList;
pFileList->langDepFlg = 0;
pFileList->srcFiles.push_back(wstring2string(sourceFile));
pFileList->destFile = wstring2string(destinationFile);
iPkgBlock.push_back(pCmdBlock);
}
}
}
/**
ParseIfBlockL: Parses the conditional installation body
@internalComponent
@released
*/
void PkgParser::ParseIfBlockL()
{
PCMD_BLOCK pCmdBlock = 0;
//IF
pCmdBlock = new CMD_BLOCK;
pCmdBlock->cmdType = IF;
ParseLogicalOp(pCmdBlock->cmdExpression);
iPkgBlock.push_back(pCmdBlock);
ParseEmbeddedBlockL ();
while (m_token==ELSEIF_TOKEN)
{
GetNextToken ();
//ELSEIF
pCmdBlock = new CMD_BLOCK;
pCmdBlock->cmdType = ELSEIF;
ParseLogicalOp(pCmdBlock->cmdExpression);
iPkgBlock.push_back(pCmdBlock);
ParseEmbeddedBlockL ();
}
if (m_token==ELSE_TOKEN)
{
GetNextToken ();
//ELSEIF
pCmdBlock = new CMD_BLOCK;
pCmdBlock->cmdType = ELSE;
iPkgBlock.push_back(pCmdBlock);
ParseEmbeddedBlockL ();
}
ExpectToken(ENDIF_TOKEN);
//ENDIF
pCmdBlock = new CMD_BLOCK;
pCmdBlock->cmdType = ENDIF;
iPkgBlock.push_back(pCmdBlock);
GetNextToken ();
}
/**
ParseLogicalOp: Parses the logical expression
@internalComponent
@released
*/
void PkgParser::ParseLogicalOp (String& aExpression)
{
ParseRelation (aExpression);
switch (m_token)
{
case AND_TOKEN:
case OR_TOKEN:
{
if (m_token==AND_TOKEN)
aExpression.append(" && ");
else
aExpression.append(" || ");
GetNextToken ();
ParseLogicalOp (aExpression);
}
break;
}
}
/**
ParseRelation: Parses the relational expression
@internalComponent
@released
*/
void PkgParser::ParseRelation(String& aExpression)
{
ParseUnary (aExpression);
switch (m_token)
{
case '=':
case '>':
case '<':
case GE_TOKEN:
case LE_TOKEN:
case NE_TOKEN:
case APPCAP_TOKEN:
{
switch (m_token)
{
case '=':
aExpression.append(" == ");
break;
case '>':
aExpression.append(" > ");
break;
case '<':
aExpression.append(" < ");
break;
case GE_TOKEN:
aExpression.append(" >= ");
break;
case LE_TOKEN:
aExpression.append(" <= ");
break;
case NE_TOKEN:
aExpression.append(" != ");
break;
case APPCAP_TOKEN:
aExpression.append(" APPPROP ");
break;
}
GetNextToken ();
ParseUnary (aExpression);
break;
}
}
}
/**
ParseUnary: Parses the unary expression
@internalComponent
@released
*/
void PkgParser::ParseUnary(String& aExpression)
{
switch (m_token)
{
case NOT_TOKEN:
aExpression.append(" !");
GetNextToken ();
ParseUnary (aExpression);
break;
case EXISTS_TOKEN:
case DEVCAP_TOKEN:
{ // 1 arg function
int token=m_token;
GetNextToken ();
ExpectToken('(');
GetNextToken ();
if (token==EXISTS_TOKEN)
{
aExpression.append("EXISTS(\"");
ExpectToken(QUOTED_STRING_TOKEN);
GetNextToken ();
aExpression.append(wstring2string(m_tokenValue.pszString));
aExpression.append("\")");
}
else
{
aExpression.append("DEVCAP(");
ParseUnary (aExpression);
aExpression.append(")");
}
ExpectToken(')');
GetNextToken ();
break;
}
default:
ParseFactor (aExpression);
break;
}
}
/**
ParseFactor: Parses the expression factor
@internalComponent
@released
*/
void PkgParser::ParseFactor(String& aExpression)
{
switch (m_token) {
case '(':
{
aExpression.append("(");
GetNextToken ();
ParseLogicalOp (aExpression);
ExpectToken(')');
aExpression.append(")");
}
break;
case QUOTED_STRING_TOKEN:
case ALPHA_TOKEN:
case NUMERIC_TOKEN:
{
switch (m_token)
{
case QUOTED_STRING_TOKEN:
aExpression.append("\"");
aExpression.append(wstring2string(m_tokenValue.pszString));
aExpression.append("\"");
break;
case ALPHA_TOKEN:
if(!CompareNString(m_tokenValue.pszString,L"option",6))
{
aExpression.append(" defined(");
aExpression.append(wstring2string(m_tokenValue.pszString));
aExpression.append(") ");
}
else
{
aExpression.append(wstring2string(m_tokenValue.pszString));
}
break;
case NUMERIC_TOKEN:
{
std::ostringstream str;
str << "(0x" << std::setbase(16) << m_tokenValue.dwNumber << ")";
aExpression.append(str.str());
}
break;
}
}
break;
default:
ParserError("ErrBadCondFormat");
}
GetNextToken ();
}
/**
ParsePackageL: Parses the embedded package section
@internalComponent
@released
*/
void PkgParser::ParsePackageL()
{
PCMD_BLOCK pCmdBlock = 0;
int found = 0;
ExpectToken(QUOTED_STRING_TOKEN);
//if the sis file already exists then skip it
SISFILE_LIST::iterator begin = iEmbedSisFiles.begin();
SISFILE_LIST::iterator end = iEmbedSisFiles.end();
while(begin != end)
{
if((*begin).compare(wstring2string(m_tokenValue.pszString)) == 0)
{
found = 1;
break;
}
++begin;
}
if(!found)
{
iEmbedSisFiles.push_back(wstring2string(m_tokenValue.pszString));
}
//add as a command block as well
{
pCmdBlock = new CMD_BLOCK;
pCmdBlock->cmdType = PACKAGE;
pCmdBlock->iInstallFileList = 0;
pCmdBlock->cmdExpression = wstring2string(m_tokenValue.pszString);
iPkgBlock.push_back(pCmdBlock);
}
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken('(');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
GetNextToken ();
ExpectToken(')');
GetNextToken ();
}
/**
ParseCommentL: Parses the comment section
Parses a comment line (Does nothing, just throws the line away)
@internalComponent
@released
*/
void PkgParser::ParseCommentL()
{
// parse to end of line
while (m_pkgChar && (m_pkgChar!='\n')) GetNextChar();
GetNextToken ();
}
/**
ParseOptionsBlockL: Parses the install options section
@internalComponent
@released
*/
void PkgParser::ParseOptionsBlockL()
{
WORD wNumLangs;
ExpectToken('(');
GetNextToken ();
for (;;)
{
ExpectToken('{');
GetNextToken ();
wNumLangs = 0;
while (wNumLangs < iLangList.size())
{
ExpectToken(QUOTED_STRING_TOKEN);
iInstallOptions.push_back(wstring2string(m_tokenValue.pszString));
GetNextToken ();
if (wNumLangs < iLangList.size() - 1)
{
ExpectToken(',');
GetNextToken ();
}
wNumLangs++;
}
ExpectToken('}');
GetNextToken ();
if (m_token!=',') break;
GetNextToken ();
}
ExpectToken(')');
GetNextToken ();
}
/**
ParsePropertyL: Parses the capability options section
@internalComponent
@released
*/
void PkgParser::ParsePropertyL()
{
ExpectToken('(');
do
{
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
GetNextToken ();
ExpectToken('=');
GetNextToken ();
ExpectToken(NUMERIC_TOKEN);
GetNextToken ();
} while (m_token==',');
ExpectToken(')');
GetNextToken ();
}
/**
ParseVendorNameL: Parses the vendor options section
@internalComponent
@released
*/
void PkgParser::ParseVendorNameL()
{
ExpectToken('{');
for (WORD wNumLangs = 0; wNumLangs < iLangList.size(); wNumLangs++)
{
GetNextToken ();
ExpectToken(QUOTED_STRING_TOKEN);
GetNextToken ();
if (wNumLangs < iLangList.size() -1 )
{
ExpectToken(',');
}
}
ExpectToken('}');
GetNextToken ();
}
/**
ParseLogoL: Parses the logo options section
@internalComponent
@released
*/
void PkgParser::ParseLogoL()
{
ExpectToken (QUOTED_STRING_TOKEN);
GetNextToken ();
ExpectToken(',');
GetNextToken ();
ExpectToken (QUOTED_STRING_TOKEN);
GetNextToken ();
if (m_token==',')
{
GetNextToken ();
ExpectToken (QUOTED_STRING_TOKEN);
GetNextToken ();
}
}
/**
ParseVersion: Parses the version details
@internalComponent
@released
*/
void PkgParser::ParseVersion()
{
GetNextToken();
ExpectToken(NUMERIC_TOKEN);
GetNextToken();
ExpectToken(',');
GetNextToken();
ExpectToken(NUMERIC_TOKEN);
GetNextToken();
ExpectToken(',');
GetNextToken();
ExpectToken(NUMERIC_TOKEN);
GetNextToken();
}
/**
ParseDependencyL: Parses the dependency package section
@internalComponent
@released
*/
void PkgParser::ParseDependencyL()
{
ExpectToken(NUMERIC_TOKEN);
GetNextToken ();
ExpectToken(')');
GetNextToken ();
ExpectToken(',');
ParseVersion();
if (m_token == '~')
{
ParseVersion();
ExpectToken(',');
}
GetNextToken ();
ExpectToken('{');
for (TUint numLangs = 0; numLangs < iLangList.size(); ++numLangs)
{
GetNextToken ();
ExpectToken(QUOTED_STRING_TOKEN);
GetNextToken ();
if (numLangs < (iLangList.size() - 1))
ExpectToken(',');
}
ExpectToken('}');
GetNextToken ();
}
/**
ParseVendorUniqueNameL: Parses the vendor unique name section
@internalComponent
@released
*/
void PkgParser::ParseVendorUniqueNameL()
{
ExpectToken(QUOTED_STRING_TOKEN);
GetNextToken ();
}
/**
ParseTargetDeviceL: Parses the target device name section
@internalComponent
@released
*/
void PkgParser::ParseTargetDeviceL()
{
ExpectToken(NUMERIC_TOKEN);
GetNextToken ();
ExpectToken(']');
GetNextToken ();
ExpectToken(',');
ParseVersion();
if (m_token == '~')
{
ParseVersion();
ExpectToken(',');
}
GetNextToken ();
ExpectToken('{');
// must do this before adding language strings
for (TUint numLangs = 0; numLangs < iLangList.size(); ++numLangs)
{
GetNextToken ();
ExpectToken(QUOTED_STRING_TOKEN);
GetNextToken ();
if (numLangs < (iLangList.size() - 1))
ExpectToken(',');
}
ExpectToken('}');
GetNextToken ();
}
/**
GetNextChar: Reads the next character from the package file
@internalComponent
@released
*/
void PkgParser::GetNextChar()
{
#ifdef WIN32
DWORD dwBytesRead;
if (!::ReadFile(iPkgHandle, (LPVOID)&m_pkgChar, sizeof(WCHAR), &dwBytesRead, NULL) ||
dwBytesRead!=sizeof(wchar_t))
m_pkgChar='\0';
#else
#error "TODO: Implement this function under other OS than Windows"
#endif
}
/**
ExpectToken: Tests the current token value
@internalComponent
@released
@param aToken - expected token value
*/
void PkgParser::ExpectToken(int aToken)
{
if (m_token!=aToken)
{
ParserError("Unexpected Token");
}
}
/**
GetNextToken: Reads the next valid token from the package file
@internalComponent
@released
*/
void PkgParser::GetNextToken ()
{
// skip any white space & newLine's
while (m_pkgChar == '\n' || isspace(m_pkgChar) || m_pkgChar == 0xA0)
{
if (m_pkgChar == '\n') ++m_nLineNo;
GetNextChar();
}
if (m_pkgChar == '\0')
m_token=EOF_TOKEN;
else if (IsNumericToken())
{
GetNumericToken();
m_token=NUMERIC_TOKEN;
}
else if (isalpha(m_pkgChar))
{ // have some alphanumeric text
GetAlphaNumericToken();
m_token=ALPHA_TOKEN;
// check if it is a keyword
for(unsigned short wLoop = 0; wLoop < NUMPARSETOKENS; wLoop++)
{
if(CompareTwoString(m_tokenValue.pszString,(wchar_t*)KTokens[wLoop].pszOpt) == 0)
{
m_token=KTokens[wLoop].dwOpt;
break;
}
}
}
else if (m_pkgChar == '\"')
{ // have a quoted string
GetStringToken();
m_token=QUOTED_STRING_TOKEN;
}
else if (m_pkgChar == '>')
{
GetNextChar();
if (m_pkgChar == '=')
{
m_token=GE_TOKEN;
GetNextChar();
}
else
m_token='>';
}
else if (m_pkgChar == '<')
{
// check if start of an escaped string, e.g. <123>"abc"
if (GetStringToken())
m_token=QUOTED_STRING_TOKEN;
else
{
GetNextChar();
if (m_pkgChar == '=')
{
m_token=LE_TOKEN;
GetNextChar();
}
else if (m_pkgChar == '>')
{
m_token=NE_TOKEN;
GetNextChar();
}
else
m_token='<';
}
}
else
{
m_token=m_pkgChar;
GetNextChar();
}
}
/**
GetStringToken: Reads the string token from the package file
@internalComponent
@released
*/
bool PkgParser::GetStringToken()
{
DWORD wCount = 0;
bool done=false;
bool finished=false;
DWORD escapeChars = 0;
while (!finished)
{
if (m_pkgChar == '\"')
{
GetNextChar();
while(m_pkgChar && m_pkgChar != '\"')
{
if(wCount < (MAX_STRING - 1))
m_tokenValue.pszString[wCount++] = m_pkgChar;
else //We dont want the string with length greater than MAX_STRING to be cut off silently
ParserError("Bad String");
GetNextChar();
}
if(m_pkgChar == '\0')
ParserError("Bad String");
GetNextChar();
done=true;
}
if (m_pkgChar == '<')
{
m_tokenValue.pszString[wCount] = L'\0';
escapeChars=ParseEscapeChars();
if (escapeChars>0)
{
done=true;
wCount+=escapeChars;
if (wCount>=MAX_STRING) wCount=MAX_STRING-1;
}
}
if (escapeChars==0 || m_pkgChar != '\"')
finished=true;
}
m_tokenValue.pszString[wCount] = L'\0';
return done;
}
/**
ParseEscapeChars: Parses the escape sequence characters
@internalComponent
@released
*/
WORD PkgParser::ParseEscapeChars()
{
WORD found=0;
WCHAR temp[MAX_STRING];
#ifdef WIN32
while (m_pkgChar == '<')
{
wcscpy(temp,m_tokenValue.pszString);
DWORD fileOffset=::SetFilePointer(iPkgHandle, 0L, NULL, FILE_CURRENT);
try
{
GetNextChar();
GetNumericToken();
if (m_pkgChar=='>')
found++;
else
{
::SetFilePointer(iPkgHandle, fileOffset, NULL, FILE_BEGIN);
break;
}
}
catch (...)
{
wcscpy(m_tokenValue.pszString,temp);
::SetFilePointer(iPkgHandle, fileOffset, NULL, FILE_BEGIN);
break;
}
DWORD num=m_tokenValue.dwNumber;
// watch for CP1252 escapes which aren't appropriate for UNICODE
if (num>=0x80 && num<=0x9F) ParserError("Invalid Escape");
DWORD len=wcslen(temp);
wcscpy(m_tokenValue.pszString,temp);
if (len+2<=MAX_STRING)
{
m_tokenValue.pszString[len]=(WCHAR)num;
len++;
m_tokenValue.pszString[len]='\0';
}
GetNextChar();
}
#else
#error "TODO: Implement this function under other OS than Windows"
#endif
return found;
}
/**
GetAlphaNumericToken: Parse an alphanumeric string from the input line
@internalComponent
@released
*/
void PkgParser::GetAlphaNumericToken()
{
WORD wCount = 0;
while(m_pkgChar && (isalnum(m_pkgChar) || ((m_pkgChar) == '_')))
{
if(wCount < (MAX_STRING - 1))
m_tokenValue.pszString[wCount++] = m_pkgChar;
GetNextChar();
}
m_tokenValue.pszString[wCount] = L'\0';
}
/**
IsNumericToken: Determines if the next lexeme is a numeric token
@internalComponent
@released
*/
bool PkgParser::IsNumericToken()
{
bool lexemeIsNumber = false;
if (iswdigit(m_pkgChar))
lexemeIsNumber = true;
else if (m_pkgChar == '+' || m_pkgChar == '-')
{
// we may have a number but we must look ahead one char to be certain
WCHAR oldChar = m_pkgChar;
DWORD fileOffset=::SetFilePointer(iPkgHandle, 0L, NULL, FILE_CURRENT);
GetNextChar();
lexemeIsNumber = iswdigit(m_pkgChar) != FALSE;
m_pkgChar = oldChar;
::SetFilePointer(iPkgHandle,fileOffset,NULL,FILE_BEGIN);
}
return lexemeIsNumber;
}
/**
GetNumericToken: Parse a number from the input line
@internalComponent
@released
*/
void PkgParser::GetNumericToken()
{
WCHAR temp[MAX_STRING];
LPWSTR end;
bool hexString = false;
DWORD dwBytesRead;
DWORD fileOffset=::SetFilePointer(iPkgHandle, 0L, NULL, FILE_CURRENT);
temp[0]=m_pkgChar;
if (!::ReadFile(iPkgHandle, &temp[1], (MAX_STRING-2)*sizeof(WCHAR), &dwBytesRead, NULL) ||
dwBytesRead==0)
ParserError("Read failed");
temp[1+dwBytesRead/sizeof(WCHAR)]='\0';
hexString = (!CompareNString(temp, L"0x", 2) || !CompareNString(&temp[1], L"0x", 2));
m_tokenValue.dwNumber = wcstoul(temp, &end, (hexString) ? 16 : 10);
if (end==temp) ParserError("Read failed");
::SetFilePointer(iPkgHandle, fileOffset+(end-temp-1)*sizeof(WCHAR), NULL, FILE_BEGIN);
GetNextChar();
}
/**
AddLanguage: Updates the language list structure
@internalComponent
@released
@param aLang - Name of the language
@param aCode - Language code
@param aDialect - Language dialect code
*/
void PkgParser::AddLanguage(String aLang, unsigned long aCode, unsigned long aDialect)
{
PLANG_LIST lc = new LANG_LIST;
lc->langName = aLang;
lc->langCode = aCode;
lc->dialectCode = aDialect;
iLangList.push_back(lc);
}
/**
DeleteAll: Deallocates memory for the data members
@internalComponent
@released
*/
void PkgParser::DeleteAll()
{
while(iPkgBlock.size() > 0)
{
PCMD_BLOCK ptemp = 0;
ptemp = iPkgBlock.front();
iPkgBlock.pop_front();
if(ptemp->cmdType == INSTALLFILE)
{
delete ptemp->iInstallFileList;
}
delete ptemp;
}
{
LANGUAGE_LIST::iterator begin = iLangList.begin();
LANGUAGE_LIST::iterator end = iLangList.end();
while(begin != end)
{
PLANG_LIST ptemp = 0;
ptemp = (*begin);
if(ptemp)
delete ptemp;
++begin;
}
iLangList.clear();
}
}
/**
ParserError: Throws exception with the given error message
@internalComponent
@released
@param msg - error message to be thrown
*/
void PkgParser::ParserError(char* msg)
{
std::ostringstream str;
str << (char*)iPkgFile.data() << "(" << m_nLineNo << "): " << msg;
throw SisUtilsException("PakageFile-Parser Error", (char*)(str.str()).data());
}
/**
wstring2string: Converts wide string to string
@internalComponent
@released
@param aWide - input wide string
*/
String wstring2string (const std::wstring& aWide)
{
int max = ::WideCharToMultiByte(CP_OEMCP,0,aWide.c_str(),aWide.length(),0,0,0,0);
String reply;
if (max > 0 )
{
char* buffer = new char [max];
try
{
::WideCharToMultiByte(CP_OEMCP,0,aWide.c_str(),aWide.length(),buffer,max,0,0);
reply = String (buffer, max);
}
catch (...)
{
throw SisUtilsException("ParserError", "wstring to string conversion failed");
}
delete [] buffer;
}
return reply;
}
/**
string2wstring: Converts string to wide string
@internalComponent
@released
@param aNarrow - input string
*/
std::wstring string2wstring (const String& aNarrow)
{
int max = ::MultiByteToWideChar(CP_OEMCP,0,aNarrow.c_str(),aNarrow.length(),0,0);
std::wstring reply;
if (max > 0 )
{
wchar_t* buffer = new wchar_t [max];
try
{
::MultiByteToWideChar(CP_OEMCP,0,aNarrow.c_str(),aNarrow.length(),buffer,max);
reply = std::wstring (buffer, max);
}
catch (...)
{
throw SisUtilsException("ParserError", "string to wstring conversion failed");
}
delete [] buffer;
}
return reply;
}
/**
CompareTwoString: Compares two wide string
@internalComponent
@released
@param string - first string
@param option - second string
*/
int CompareTwoString(wchar_t* string ,wchar_t* option)
{
return wcsicmp(string,option);
}
/**
CompareNString: Compares two wide string for n characters
@internalComponent
@released
@param string - first string
@param option - second string
@param len - no of wide characters to be compared
*/
int CompareNString(wchar_t* string ,wchar_t* option, int len)
{
return wcsnicmp(string,option,len);
}