--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/sisutils/src/pkgfileparser.cpp Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,1435 @@
+/*
+* 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);
+}