diff -r c7c26511138f -r 360bd6b35136 imgtools/sisutils/src/pkgfileparser.cpp --- a/imgtools/sisutils/src/pkgfileparser.cpp Wed Jun 16 16:51:40 2010 +0300 +++ b/imgtools/sisutils/src/pkgfileparser.cpp Wed Jun 23 16:56:47 2010 +0800 @@ -1,1435 +1,1230 @@ -/* -* 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); -} +/* +* 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.htm ". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "sisutils.h" +#include "pkgfileparser.h" +#ifdef __LINUX__ +#include +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif +#include "utf16string.h" + +// Parse options lookups +#define MAXTOKENLEN 30 +struct SParseToken +{ + char pszOpt[MAXTOKENLEN]; + TUint32 dwOpt; +}; + +const SParseToken KTokens[] = +{ + { "if", IF_TOKEN}, + { "elseif", ELSEIF_TOKEN}, + { "else", ELSE_TOKEN}, + { "endif", ENDIF_TOKEN}, + { "exists", EXISTS_TOKEN}, + { "devprop",DEVCAP_TOKEN}, + { "appcap", APPCAP_TOKEN}, + { "package",DEVCAP_TOKEN}, + { "appprop",APPCAP_TOKEN}, + { "not", NOT_TOKEN}, + { "and", AND_TOKEN}, + { "or", OR_TOKEN}, + { "type", TYPE_TOKEN}, + { "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(const string& aFile) : iPkgFileContent(""),iContentPos(0),iContentStr("") ,iPkgFileName(aFile),iToken(EOF_TOKEN) , iLineNumber(0){ +} + +/** +Destructor: PkgParser class +Deallocates the memory for data members + +@internalComponent +@released +*/ +PkgParser::~PkgParser() { + + DeleteAll(); + +} + +/** +OpenFile: Opens the package script file + +@internalComponent +@released +*/ +bool PkgParser::OpenFile() { + + UTF16String str ; + if(!str.FromFile(iPkgFileName.c_str())) + return false ; + + if(!str.ToUTF8(iContentStr)) + return false ; + + iPkgFileContent = iContentStr.c_str(); + iContentPos = 0 ; + return true ; +} +/** + * GetNextChar : iContentStr is a UTF-8 String, of which char is as follows: + * + *0000-007F | 0xxxxxxx + *0080-07FF | 110xxxxx 10xxxxxx + *0800-FFFF | 1110xxxx 10xxxxxx 10xxxxxx + * 10000-10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + */ +void PkgParser::GetNextChar() { + if(iContentPos < iContentStr.length()){ + if(0 == (iPkgFileContent[iContentPos] & 0x80)) + iContentPos++; + else if(0xC0 == (iPkgFileContent[iContentPos] & 0xE0)) + iContentPos += 2 ; + else if(0xE0 == (iPkgFileContent[iContentPos] & 0xF0)) + iContentPos += 3 ; + else + iContentPos += 4 ; + if(iContentPos >= iContentStr.length()) + iContentPos = iContentStr.length() ; + } +} +/** +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(iPkgFileName.c_str(), "Could not open file"); + GetNextToken (); + while(iToken!=EOF_TOKEN) { + ParseEmbeddedBlockL(); + switch (iToken) + { + 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(){ + TUint32 iLangCode = 0; + TUint32 dialect = 0; + + while (true){ + if (iToken==ALPHA_TOKEN){ + iLangCode = GetLanguageCode(iTokenVal.iString); + } + else if (iToken==NUMERIC_TOKEN && iTokenVal.iNumber>=0 && iTokenVal.iNumber<=1000) { + iLangCode = (iTokenVal.iNumber); + } + + GetNextToken (); + + // Check if a dialect is defined + if (iToken == '(') + { + GetNumericToken(); + // Modify the last added language code, combining it with dialect code + dialect = (iTokenVal.iNumber); + GetNextToken (); + GetNextToken (); + } + const char* temp = GetLanguageName(iLangCode); + if(NULL != temp){ + AddLanguage(string(temp), iLangCode, dialect); + } + + if (iToken!=',') + 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 (TUint16 wNumLangs = 0; wNumLangs < iLangList.size(); wNumLangs++) { + GetNextToken (); + ExpectToken(QUOTED_STRING_TOKEN); + iPkgHeader.iPkgNames.push_back(string(iTokenVal.iString)); + GetNextToken (); + if (wNumLangs < (iLangList.size()-1) ) { + ExpectToken(','); + } + } + ExpectToken('}'); + GetNextToken (); + + ExpectToken(','); + GetNextToken (); + ExpectToken('('); + GetNextToken (); + + ExpectToken(NUMERIC_TOKEN); + iPkgHeader.iPkgUID = iTokenVal.iNumber; + GetNextToken (); + ExpectToken(')'); + + GetNextToken (); + ExpectToken(','); + GetNextToken (); + + ExpectToken(NUMERIC_TOKEN); + iPkgHeader.iMajorVersion = iTokenVal.iNumber; + GetNextToken (); + ExpectToken(','); + GetNextToken (); + + ExpectToken(NUMERIC_TOKEN); + iPkgHeader.iMinorVersion = iTokenVal.iNumber; + GetNextToken (); + ExpectToken(','); + GetNextToken (); + + ExpectToken(NUMERIC_TOKEN); + iPkgHeader.iBuildVersion = iTokenVal.iNumber; + GetNextToken (); + + // Parse any options + while (iToken==',') { + GetNextToken (); + if (iToken==TYPE_TOKEN) { + GetNextToken (); + ExpectToken('='); + GetNextToken (); + iPkgHeader.iPkgType = iTokenVal.iString; + GetNextToken (); + } + else + GetNextToken (); + } +} + +/** +ParseEmbeddedBlockL: Parses the package body block + +@internalComponent +@released +*/ +void PkgParser::ParseEmbeddedBlockL () { + while(iToken!=EOF_TOKEN) { + switch (iToken) { + 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; + + string sourceFile (iTokenVal.iString); + + // Linux and windows both support forward slashes so if source path is given '\' need to convert + // in forward slash for compatibility. + char* pBuffer = const_cast(sourceFile.data()); + char* pCurrent = pBuffer; + while (pBuffer && *pBuffer && (pCurrent = strchr(pBuffer,'\\')) != NULL) { + *pCurrent = '/'; + pBuffer = pCurrent + 1; + } + + GetNextToken (); + + ExpectToken('-'); + GetNextToken (); + + ExpectToken(QUOTED_STRING_TOKEN); + + string destinationFile (iTokenVal.iString); + + // SWI only supports backward slashesh so need to convert destination path in backward slash if + // user gives '/' in Linux. + pBuffer = const_cast(destinationFile.data()); + pCurrent = pBuffer; + while (pBuffer && *pBuffer && (pCurrent = strchr(pBuffer,'/')) != NULL) { + *pCurrent = '\\'; + pBuffer = pCurrent + 1; + } + + GetNextToken (); + + // Test for options + if (iToken!=',') { + pCmdBlock = new CMD_BLOCK; + pFileList = new INSTALLFILE_LIST; + + pCmdBlock->iCmdType = INSTALLFILE; + pCmdBlock->iInstallFileList = pFileList; + + pFileList->iLangDepFlag = 0; + pFileList->iSourceFiles.push_back(sourceFile); + pFileList->iDestFile = destinationFile; + + iPkgBlock.push_back(pCmdBlock); + } + else { + bool needAdd = false; + while(iToken==',') { + GetNextToken (); + string installOption = iTokenVal.iString; + if((installOption == "FF") || (installOption == "FILE")) { + needAdd = true; + } + GetNextToken (); + } + if (needAdd) { + pCmdBlock = new CMD_BLOCK; + pFileList = new INSTALLFILE_LIST; + + pCmdBlock->iCmdType = INSTALLFILE; + pCmdBlock->iInstallFileList = pFileList; + + pFileList->iLangDepFlag = 0; + pFileList->iSourceFiles.push_back(sourceFile); + pFileList->iDestFile = 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->iCmdType = IF; + ParseLogicalOp(pCmdBlock->iCmdExpr); + iPkgBlock.push_back(pCmdBlock); + + ParseEmbeddedBlockL (); + + while (iToken==ELSEIF_TOKEN){ + GetNextToken (); + //ELSEIF + pCmdBlock = new CMD_BLOCK; + pCmdBlock->iCmdType = ELSEIF; + ParseLogicalOp(pCmdBlock->iCmdExpr); + iPkgBlock.push_back(pCmdBlock); + + ParseEmbeddedBlockL (); + } + + if (iToken==ELSE_TOKEN) { + GetNextToken (); + //ELSEIF + pCmdBlock = new CMD_BLOCK; + pCmdBlock->iCmdType = ELSE; + iPkgBlock.push_back(pCmdBlock); + + ParseEmbeddedBlockL (); + } + + ExpectToken(ENDIF_TOKEN); + //ENDIF + pCmdBlock = new CMD_BLOCK; + pCmdBlock->iCmdType = ENDIF; + iPkgBlock.push_back(pCmdBlock); + + GetNextToken (); +} + +/** +ParseLogicalOp: Parses the logical expression + +@internalComponent +@released +*/ +void PkgParser::ParseLogicalOp (string& aExpression) { + ParseRelation (aExpression); + switch (iToken) { + case AND_TOKEN: + case OR_TOKEN: + { + if (iToken==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 (iToken) + { + case '=': + case '>': + case '<': + case GE_TOKEN: + case LE_TOKEN: + case NE_TOKEN: + case APPCAP_TOKEN: + { + switch (iToken) + { + 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 (iToken) { + case NOT_TOKEN: + aExpression.append(" !"); + GetNextToken (); + ParseUnary (aExpression); + break; + case EXISTS_TOKEN: + case DEVCAP_TOKEN: + { // 1 arg function + TInt token=iToken; + GetNextToken (); + ExpectToken('('); + GetNextToken (); + if (token==EXISTS_TOKEN) + { + aExpression.append("EXISTS(\""); + ExpectToken(QUOTED_STRING_TOKEN); + GetNextToken (); + aExpression.append(string(iTokenVal.iString)); + 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 (iToken) { + case '(': + { + aExpression.append("("); + GetNextToken (); + ParseLogicalOp (aExpression); + ExpectToken(')'); + aExpression.append(")"); + } + break; + case QUOTED_STRING_TOKEN: + case ALPHA_TOKEN: + case NUMERIC_TOKEN: + { + switch (iToken) + { + case QUOTED_STRING_TOKEN: + aExpression.append("\""); + aExpression.append(iTokenVal.iString); + aExpression.append("\""); + break; + case ALPHA_TOKEN: + if(!strnicmp(iTokenVal.iString,"option",6)) { + aExpression.append(" defined("); + aExpression.append(iTokenVal.iString); + ExpectToken(')'); + } + else { + aExpression.append(iTokenVal.iString); + } + break; + case NUMERIC_TOKEN: + { + ostringstream str; + + str << "(0x" << setbase(16) << iTokenVal.iNumber << ")"; + 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; + TInt 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) == iTokenVal.iString) { + found = 1; + break; + } + ++begin; + } + + if(!found) + iEmbedSisFiles.push_back(string(iTokenVal.iString)); + + //add as a command block as well + + pCmdBlock = new CMD_BLOCK; + + pCmdBlock->iCmdType = PACKAGE; + pCmdBlock->iInstallFileList = 0; + pCmdBlock->iCmdExpr = iTokenVal.iString; + + 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 (GetCurChar() && (GetCurChar()!='\n')) GetNextChar(); + GetNextToken (); +} + +/** +ParseOptionsBlockL: Parses the install options section + +@internalComponent +@released +*/ +void PkgParser::ParseOptionsBlockL() { + TUint16 wNumLangs; + + ExpectToken('('); + GetNextToken (); + + for (;;){ + ExpectToken('{'); + GetNextToken (); + + wNumLangs = 0; + while (wNumLangs < iLangList.size()){ + ExpectToken(QUOTED_STRING_TOKEN); + iInstallOptions.push_back(string(iTokenVal.iString)); + GetNextToken (); + if (wNumLangs < iLangList.size() - 1){ + ExpectToken(','); + GetNextToken (); + } + wNumLangs++; + } + + ExpectToken('}'); + GetNextToken (); + if (iToken!=',') 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 (iToken==','); + ExpectToken(')'); + GetNextToken (); +} + +/** +ParseVendorNameL: Parses the vendor options section + +@internalComponent +@released +*/ +void PkgParser::ParseVendorNameL() { + ExpectToken('{'); + for (TUint16 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 (iToken==',') + { + 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 (iToken == '~') { + 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 (iToken == '~') { + 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 (); +} + + + + +/** +GetNextToken: Reads the next valid token from the package file + +@internalComponent +@released +*/ +void PkgParser::GetNextToken () { + // skip any white space & newLine's + while (GetCurChar() == '\n' || isspace(GetCurChar()) || GetCurChar() == (char)0xA0) { + if (GetCurChar() == '\n') ++iLineNumber; + GetNextChar(); + } + + if (GetCurChar() == '\0') + iToken=EOF_TOKEN; + else if (IsNumericToken()){ + GetNumericToken(); + iToken=NUMERIC_TOKEN; + } + else if (isalpha(GetCurChar())){ // have some alphanumeric text + GetAlphaNumericToken(); + iToken=ALPHA_TOKEN; + // check if it is a keyword + for(unsigned short wLoop = 0; wLoop < NUMPARSETOKENS; wLoop++){ + if(stricmp(iTokenVal.iString,KTokens[wLoop].pszOpt) == 0){ + iToken=KTokens[wLoop].dwOpt; + break; + } + } + } + else if (GetCurChar() == '\"') { // have a quoted string + GetStringToken(); + iToken=QUOTED_STRING_TOKEN; + } + else if (GetCurChar() == '>') { + GetNextChar(); + if (GetCurChar() == '='){ + iToken=GE_TOKEN; + GetNextChar(); + } + else + iToken='>'; + } + else if (GetCurChar() == '<'){ + // check if start of an escaped string, e.g. <123>"abc" + if (GetStringToken()) + iToken=QUOTED_STRING_TOKEN; + else{ + GetNextChar(); + if (GetCurChar() == '='){ + iToken=LE_TOKEN; + GetNextChar(); + } + else if (GetCurChar() == '>'){ + iToken=NE_TOKEN; + GetNextChar(); + } + else + iToken='<'; + } + } + else{ + iToken=GetCurChar(); + GetNextChar(); + } +} + +/** +GetStringToken: Reads the string token from the package file + +@internalComponent +@released +*/ +bool PkgParser::GetStringToken() { + TUint32 wCount = 0; + bool done=false; + bool finished=false; + TUint32 escapeChars = 0; + + while (!finished){ + if (GetCurChar() == '\"'){ + GetNextChar(); + while(GetCurChar() && GetCurChar() != '\"'){ + if(wCount < (MAX_STRING - 1)) + iTokenVal.iString[wCount++] = GetCurChar(); + else //We dont want the string with length greater than MAX_STRING to be cut off silently + ParserError("Bad string"); + GetNextChar(); + } + if(GetCurChar() == '\0') + ParserError("Bad string"); + GetNextChar(); + done=true; + } + if (GetCurChar() == '<'){ + iTokenVal.iString[wCount] = L'\0'; + escapeChars=ParseEscapeChars(); + if (escapeChars>0) + { + done=true; + wCount+=escapeChars; + if (wCount>=MAX_STRING) wCount=MAX_STRING-1; + } + } + if (escapeChars==0 || GetCurChar() != '\"') + finished=true; + } + + iTokenVal.iString[wCount] = L'\0'; + return done; +} + +/** +ParseEscapeChars: Parses the escape sequence characters + +@internalComponent +@released +*/ +TUint16 PkgParser::ParseEscapeChars() { + TUint16 found=0; + char temp[MAX_STRING]; + + while (GetCurChar() == '<'){ + strcpy(temp,iTokenVal.iString); + TUint savedPos = iContentPos ; + try { + GetNextChar(); + GetNumericToken(); + if (GetCurChar()=='>') + found++; + else { + iContentPos = savedPos ; + break; + } + } + catch (...) { + strcpy(iTokenVal.iString,temp); + iContentPos = savedPos ; + break; + } + TUint32 num=iTokenVal.iNumber; + // watch for CP1252 escapes which aren't appropriate for UNICODE + if (num>=0x80 && num<=0x9F) ParserError("Invalid Escape"); + TUint32 len=strlen(temp); + memcpy(iTokenVal.iString,temp, len + 1); + if ((len + 2) <= MAX_STRING){ + iTokenVal.iString[len]= static_cast(num); + len++; + iTokenVal.iString[len]='\0'; + } + GetNextChar(); + } + + return found; +} + +/** +GetAlphaNumericToken: Parse an alphanumeric string from the input line + +@internalComponent +@released +*/ +void PkgParser::GetAlphaNumericToken() +{ + size_t length = 0; + TUint savedPos = iContentPos ; + TUint bound = iContentStr.length(); + while((iContentPos < bound) && + (isalnum(iPkgFileContent[iContentPos]) || (iPkgFileContent[iContentPos] == '_'))) { + iContentPos ++ ; + if(length < (MAX_STRING - 1)) length ++ ; + } + memcpy(iTokenVal.iString,&iPkgFileContent[savedPos],length); + iTokenVal.iString[length] = 0; +} + +/** +IsNumericToken: Determines if the next lexeme is a numeric token + +@internalComponent +@released +*/ +bool PkgParser::IsNumericToken() { + char ch = iPkgFileContent[iContentPos]; + if (isdigit(ch)) + return true ; + else if (ch == '+' || ch == '-'){ + // we may have a number but we must look ahead one char to be certain + return isdigit(iPkgFileContent[iContentPos + 1]) != 0; + } + return false ; +} + +/** +GetNumericToken: Parse a number from the input line + +@internalComponent +@released +*/ +void PkgParser::GetNumericToken() { + + int base = 10; + const char* temp = &iPkgFileContent[iContentPos] ; + if(*temp == '0' &&( temp[1] == 'x' || temp[1] == 'X')){ + base = 16 ; + temp += 2; + } + char *end = const_cast(temp) ; + iTokenVal.iNumber = strtoul(temp, &end, base); + iContentPos = end - iPkgFileContent ; +} + +/** +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(const string& aLang, TUint32 aCode, TUint32 aDialect) { + PLANG_LIST lc = new LANG_LIST; + + lc->iLangName = aLang; + lc->iLangCode = aCode; + lc->iDialectCode = 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->iCmdType == 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(); + iPkgFileContent = "" ; + iContentPos = 0 ; + iContentStr.clear(); + +} + +/** +ParserError: Throws exception with the given error message + +@internalComponent +@released + +@param msg - error message to be thrown +*/ +void PkgParser::ParserError(const char* aMsg) { + ostringstream str; + str << iPkgFileName.c_str() << "(" << iLineNumber << "): " << aMsg; + throw SisUtilsException("PakageFile-Parser Error", str.str().c_str()); +}