imgtools/sisutils/src/sis2iby.cpp
changeset 0 044383f39525
child 590 360bd6b35136
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imgtools/sisutils/src/sis2iby.cpp	Tue Oct 27 16:36:35 2009 +0000
@@ -0,0 +1,675 @@
+/*
+* 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 "sis2iby.h"
+
+/**
+Constructor: Sis2Iby class
+Initilize the parameters to data members.
+
+@internalComponent
+@released
+
+@param aFile	- SIS file name
+*/
+Sis2Iby::Sis2Iby(char* aFile) : SisUtils(aFile)
+{
+}
+
+/**
+Destructor: Sis2Iby class
+Deallocates the memory for data members
+
+@internalComponent
+@released
+*/
+Sis2Iby::~Sis2Iby()
+{
+	PKGFILE_MAP::iterator begin = iPkgFileMap.begin();
+	PKGFILE_MAP::iterator end = iPkgFileMap.end();
+	while(begin != end)
+	{
+		PPKGPARSER ptemp = 0;
+		ptemp = (*begin).second;
+
+		if(ptemp)
+			delete ptemp;
+		++begin;
+	}
+	iPkgFileMap.clear();
+}
+
+/**
+ProcessSisFile: Processes the input sis file
+  Invoke the DUMPSIS tool to extract the sis file contents
+  Creates package parser object for each of the package file
+
+@internalComponent
+@released
+*/
+void Sis2Iby::ProcessSisFile()
+{
+	TUint32 retStatus = STAT_SUCCESS;
+	String sisFile = SisFileName();
+
+	if(IsVerboseMode())
+	{
+		std::cout << "Processing " << (char*)sisFile.data() << std::endl;
+	}
+
+	if(IsFileExist(sisFile))
+	{
+		retStatus = InvokeExtractTool(sisFile);
+
+		switch(retStatus)
+		{
+		case STAT_SUCCESS:
+			{
+				UpdatePkgFileMap(iExtractPath, sisFile);
+			}
+			break;
+		case STAT_FAILURE:
+			{
+				throw SisUtilsException((char*)sisFile.data(), "Failed to extract SIS file");
+			}
+		}
+	}
+	else
+		throw SisUtilsException((char*)sisFile.data(), "File not found");
+}
+
+/**
+GenerateOutput: Generates IBY for each of the package file
+
+@internalComponent
+@released
+*/
+void Sis2Iby::GenerateOutput()
+{
+	PKGFILE_MAP::iterator begin = iPkgFileMap.begin();
+	PKGFILE_MAP::iterator end = iPkgFileMap.end();
+	while(begin != end)
+	{
+		GenerateIby((*begin).first, (*begin).second);
+		++begin;
+	}
+}
+
+/**
+GenerateOutput: Generates IBY file for the given package file
+
+@internalComponent
+@released
+
+@param aPkgFile - package file name
+@param aParser - corresponding package file reader object
+*/
+void Sis2Iby::GenerateIby(String aPkgFile, PPKGPARSER aParser)
+{
+	String ibyFile = iOutputPath;
+	
+	AppendFileName(ibyFile, aPkgFile);
+	ibyFile.append(".iby");
+
+	if( !MakeDirectory(iOutputPath) )
+		throw SisUtilsException((char*)iOutputPath.data(), "Failed to create path");
+
+	if(IsVerboseMode())
+	{
+		std::cout << "Generating IBY file " << (char*)ibyFile.data() << std::endl;
+	}
+
+	ibyHandle.open((char*)ibyFile.data(),(std::ios::out));
+
+	if(!ibyHandle.good())
+	{
+		throw SisUtilsException((char*)ibyFile.data(), "Failed to create IBY file");
+	}
+
+	// Generating Header
+	MakeFullPath(aPkgFile);
+	ibyHandle << "\n// Generated IBY file for the package file: ";
+	ibyHandle << aPkgFile;
+
+	// Language Supported
+	WriteLanguages(aParser);
+
+	// Package Header
+	WritePackageHeader(aParser);
+
+	// Install options list
+	WriteInstallOptions(aParser);
+
+	// Package Body
+	WritePackageBody(aParser);
+
+	ibyHandle.close();
+}
+
+/**
+InvokeExtractTool: Invokes the SIS file extraction tool and returns the status
+
+@internalComponent
+@released
+
+@param sisFile - SIS file name
+*/
+TUint32 Sis2Iby::InvokeExtractTool(String sisFile)
+{
+	String cmdLine;
+
+	cmdLine.append(SISEXTRACT_TOOL_NAME SISEXTRACT_TOOL_DEFOPT);
+
+	AppendFileName(iExtractPath, sisFile);
+
+	cmdLine.append(SISEXTRACT_TOOL_EXTOPT);
+	cmdLine.append("\"" + iExtractPath + "\" ");
+	cmdLine.append(sisFile);
+
+	if(IsVerboseMode())
+	{
+		std::cout << "Executing " << (char*)cmdLine.data() << std::endl;
+	}
+
+	return RunCommand(cmdLine);
+}
+
+/**
+UpdatePkgFileMap: Update the package file map by getting the embedded sis file list from the parser object
+
+@internalComponent
+@released
+
+@param aPath - Extract path
+@param aFile - SIS file name
+*/
+void Sis2Iby::UpdatePkgFileMap(String aPath, String aFile)
+{
+	String pkgFileName;
+	std::list<String> sisList;
+
+	// main pkg file
+	pkgFileName = aPath;
+	AppendFileName(pkgFileName, aFile);
+	pkgFileName.append(".pkg");
+
+	// create an instance for the pkg file parser
+	// get the embedded sis file list
+	// add each as pkg file into the list
+	pkgParser = 0;
+	if( IsFileExist(pkgFileName) )
+	{
+		pkgParser = new PkgParser(pkgFileName);
+
+		if(pkgParser)
+		{
+			pkgParser->ParsePkgFile();
+
+			iPkgFileMap[pkgFileName] = pkgParser;
+
+			pkgParser->GetEmbeddedSisList(sisList);
+			SISFILE_LIST::iterator begin = sisList.begin();
+			SISFILE_LIST::iterator end = sisList.end();
+
+			while(begin != end)
+			{
+				String currPath = aPath;
+
+				currPath.append(PATHSEPARATOR);
+				GetFileName((*begin), currPath);
+				UpdatePkgFileMap(currPath, (*begin));
+
+				++begin;
+			}
+		}
+		else
+			throw SisUtilsException((char*)pkgFileName.data(), "Could not create parser object");
+	}
+	else
+		throw SisUtilsException((char*)pkgFileName.data(), "File not found");
+}
+
+/**
+WriteLanguages: Writes language section in the IBY file
+
+@internalComponent
+@released
+
+@param aParser - Package file parser object
+*/
+void Sis2Iby::WriteLanguages(PPKGPARSER aParser)
+{
+	LANGUAGE_LIST lanMap;
+	PLANG_LIST langCode;
+
+	aParser->GetLanguageList(lanMap);
+	ibyHandle << "\n// Languages: ";
+
+	LANGUAGE_LIST::iterator begin = lanMap.begin();
+	LANGUAGE_LIST::iterator end = lanMap.end();
+
+	while(begin != end)
+	{
+		langCode = (*begin);
+
+		ibyHandle << " " << langCode->langName;
+		ibyHandle << "(" << langCode->langCode;
+
+		if(langCode->dialectCode)
+		{
+			ibyHandle << "-" << langCode->dialectCode;
+		}
+		ibyHandle << ")";
+
+		++begin;
+	}
+}
+
+/**
+WritePackageHeader: Writes package header section in the IBY file
+
+@internalComponent
+@released
+
+@param aParser - Package file parser object
+*/
+void Sis2Iby::WritePackageHeader(PPKGPARSER aParser)
+{
+	PKG_HEADER pkgHeader;
+	std::list<String> pkgList;
+	std::ostringstream str;
+
+	aParser->GetHeader(pkgHeader);
+
+	ibyHandle << "\n// Header: ";
+
+	pkgList = pkgHeader.pkgNameList;
+	while(pkgList.size())
+	{
+		ibyHandle << "\"" << pkgList.front() << "\" ";
+		pkgList.pop_front();
+	}
+
+	str << "(0x" << std::setbase(16) << pkgHeader.pkgUid << ")";
+
+	ibyHandle << str.str();
+}
+
+/**
+WriteInstallOptions: Writes install option section in the IBY file
+
+@internalComponent
+@released
+
+@param aParser - Package file parser object
+*/
+void Sis2Iby::WriteInstallOptions(PPKGPARSER aParser)
+{
+	std::list<String> optList;
+	String ibyName;
+
+	aParser->GetInstallOptions(optList);
+	SISFILE_LIST::iterator begin = optList.begin();
+	SISFILE_LIST::iterator end = optList.end();
+
+	if(begin != end)
+	{
+		ibyHandle << "\n// Install Options: ";
+	}
+
+	while(begin != end)
+	{
+		ibyHandle << " \"" << (*begin) << "\"";
+		++begin;
+	}
+}
+
+/**
+InsertTabs: Inserts spaces for indentation in the output IBY file
+
+@internalComponent
+@released
+
+@param num - num of spaces to be inserted
+*/
+void Sis2Iby::InsertTabs(int num)
+{
+	ibyHandle << "\n";
+	while(num--)
+	{
+		ibyHandle << "  ";
+	}
+}
+
+/**
+WritePackageBody: Writes package body details in the IBY file
+
+@internalComponent
+@released
+
+@param aParser - Package file parser object
+*/
+void Sis2Iby::WritePackageBody(PPKGPARSER aParser)
+{
+	CMDBLOCK_LIST cmdList;
+	PCMD_BLOCK cmd;
+	int pad = 0;
+
+	ibyHandle << "\n\n";
+	aParser->GetCommandList(cmdList);
+
+	CMDBLOCK_LIST::iterator begin = cmdList.begin();
+	CMDBLOCK_LIST::iterator end = cmdList.end();
+
+	while(begin != end)
+	{
+		cmd = (*begin);
+
+		switch(cmd->cmdType)
+		{
+		case IF:
+			{
+				InsertTabs(pad);
+				ibyHandle << "#if " << cmd->cmdExpression;
+				pad++;
+			}
+			break;
+		case ELSEIF:
+			{
+				InsertTabs(pad-1);
+				ibyHandle << "#elif " << cmd->cmdExpression;
+			}
+			break;
+		case ELSE:
+			{
+				InsertTabs(pad-1);
+				ibyHandle << "#else";
+			}
+			break;
+		case ENDIF:
+			{
+				--pad;
+				InsertTabs(pad);
+				ibyHandle << "#endif";
+			}
+			break;
+		case INSTALLFILE:
+			{
+				WriteInstallFileList(cmd->iInstallFileList, aParser, pad);
+			}
+			break;
+		case PACKAGE:
+			{
+				InsertTabs(pad);
+				ibyHandle << "#include " << "\"" << cmd->cmdExpression << "\"";
+			}
+			break;
+		}
+
+		++begin;
+	}
+}
+
+/**
+WriteFileInclusion: Writes installable file details in the IBY file
+
+@internalComponent
+@released
+
+@param aSrcFile - Name of the source file
+@param aDestFile - Name of the destination file
+@param aPkgName - Name of the package file
+*/
+void Sis2Iby::WriteFileInclusion(String aSrcFile, String aDestFile, String aPkgName, int pad)
+{
+	NormaliseSourceFile(aSrcFile, aPkgName);
+
+	InsertTabs(pad);
+	if(IsValidE32Image(aSrcFile))
+	{
+		ibyHandle << "file = ";
+	}
+	else
+	{
+		ibyHandle << "data = ";
+	}
+
+	ibyHandle << aSrcFile << " ";
+	NormaliseDestFile(aDestFile);
+	ibyHandle << aDestFile;
+}
+
+/**
+WriteInstallFileList: Writes installable file details in the IBY file
+
+@internalComponent
+@released
+
+@param aFileList - Installable file list structure
+@param aParser - Package file parser object
+@param pad - Number of spaces for indentation purpose
+*/
+void Sis2Iby::WriteInstallFileList(PINSTALLFILE_LIST aFileList, PPKGPARSER aParser, int pad)
+{
+	WriteFileInclusion(aFileList->srcFiles.front(), aFileList->destFile, aParser->GetPkgFileName(), pad);
+}
+
+/**
+AppendFileName: Appends file name to the given path
+
+@internalComponent
+@released
+
+@param aPath - Source path
+@param aFile - File name
+*/
+void Sis2Iby::AppendFileName(String& aPath, String aFile)
+{
+	TUint pos = 0;
+
+	TrimQuotes(aPath);
+	TrimQuotes(aFile);
+
+	pos = aPath.rfind(PATHSEPARATOR);
+	if(pos == String::npos)
+	{
+		aPath.append(PATHSEPARATOR);
+	}
+
+	if(pos < (aPath.length()-1))
+	{
+		aPath.append(PATHSEPARATOR);
+	}
+
+	GetFileName(aFile, aPath);
+	return;
+}
+
+/**
+GetFileName: Returns the base file name
+
+@internalComponent
+@released
+
+@param aName - Input file name
+@param aFile - Output parameter to hold the return value
+*/
+void Sis2Iby::GetFileName(String aName, String& aFile)
+{
+	TUint spos = 0, epos = 0;
+
+	spos = aName.rfind(PATHSEPARATOR);
+	if(spos != String::npos)
+	{
+		spos += 1;
+	}
+	else
+	{
+		spos = 0;
+	}
+
+	epos = aName.rfind(".");
+	if(epos == String::npos)
+	{
+		epos = aName.size();
+	}
+
+	aFile.append(aName.substr(spos, (epos-spos)));
+}
+
+/**
+MakeFullPath: Returns the absolute path of the given file
+
+@internalComponent
+@released
+
+@param aFile - Input file name
+*/
+void Sis2Iby::MakeFullPath(String& aFile)
+{
+#ifdef WIN32
+	char fPath[_MAX_PATH];
+
+	if( _fullpath(fPath, (char*)aFile.data(), _MAX_PATH) != NULL )
+	{
+		aFile.assign(fPath);
+	}
+#else
+#error "TODO: Implement this function under other OS than Windows"
+#endif
+	return;
+}
+
+/**
+NormaliseSourceFile: Normalise the source file with its absolute path
+
+@internalComponent
+@released
+
+@param aFile - Input file name
+@param aPkgFile - Package file path
+*/
+void Sis2Iby::NormaliseSourceFile(String& aFile, String aPkgFile)
+{
+	String result;
+	TUint pos = 0;
+
+	pos = aPkgFile.rfind(PATHSEPARATOR);
+	if(pos != String::npos)
+	{
+		result = aPkgFile.substr(0,pos);
+	}
+	else
+	{
+		result = ".";
+	}
+
+	result.append(PATHSEPARATOR);
+	result.append(aFile);
+
+	MakeFullPath(result);
+
+	aFile = "\"" + result + "\"";
+}
+
+/**
+NormaliseDestFile: Normalise the destination file
+
+@internalComponent
+@released
+
+@param aFile - Input file name
+*/
+void Sis2Iby::NormaliseDestFile(String& aFile)
+{
+	TUint pos = 0;
+
+	/** Comment by KunXu to fix DEF122540 on 18 Jun 2008
+	pos = aFile.find("$:");
+	if(pos != String::npos)
+	{
+		aFile.replace(pos, 2, "");
+	}
+
+	pos = aFile.find("!:");
+	if(pos != String::npos)
+	{
+		aFile.replace(pos, 2, "");
+	}
+	**/
+
+	/** Add by KunXu to fix DEF122540 on 18 Jun 2008 **/
+	/** Ignore any drive indication in the filename to generate an iby file **/
+	/** Begin **/
+	pos = aFile.find(":");
+	if (1 == pos)
+	{
+		char chFirst = aFile[0];
+		if ('$' == chFirst || '!' == chFirst || (chFirst >='a' && chFirst <='z') || (chFirst >='A' && chFirst <='Z'))
+		{
+			aFile.replace(0, 2, "");
+		}
+	}
+	/** End **/
+
+	aFile = "\"" + aFile + "\"";
+}
+
+/**
+IsValidE32Image: Checks whether the given file is E32 image
+
+@internalComponent
+@released
+
+@param aFile - Input file name
+*/
+TBool Sis2Iby::IsValidE32Image(String aFile)
+{
+	std::ifstream aIfs;
+	TInt8 aSig[5];
+	TUint32 e32SigOffset = 0x10, fileSize = 0;
+	TBool validE32 = EFalse;
+
+	TrimQuotes(aFile);
+
+	aIfs.open(aFile.c_str(), std::ios::in | std::ios::binary);
+
+	if( !aIfs.is_open() )
+	{
+		throw SisUtilsException((char*)aFile.data(), "Cannot open file");
+	}
+
+	aIfs.seekg(0,std::ios::end);
+	fileSize = aIfs.tellg();
+	if(fileSize > 20)
+	{
+		aIfs.seekg(e32SigOffset,std::ios::beg);
+		aIfs.read((char*)aSig, 4);
+		aSig[4] = '\0';
+
+		if(!strcmp((char*)aSig, "EPOC"))
+		{
+			validE32 = ETrue;
+		}
+	}
+
+	aIfs.close();
+
+	return validE32;
+}