diff -r 000000000000 -r 638b9c697799 apicompatanamdw/compatanalysercmd/headeranalyser/src/CPPParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/CPPParser.cpp Tue Jan 12 14:52:39 2010 +0530 @@ -0,0 +1,801 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ +#include + +#include +#include "CmdGlobals.h" +#ifdef __WIN__ +#include +#include +#else +#include +#endif + + +#include +#include + +#include +#include +#include + +#include "CPPParser.h" +#include "XMLModuleErrorHandler.h" +#include "HAException.h" +#include "BBCFileUtils.h" +#include "Utils.h" +#include "XMLUtils.h" + +XERCES_CPP_NAMESPACE_USE + +const int KMaxFilenameLength = 512; +const int KMaxDirLength=1024; + +// The C++ parser executable +#ifdef __WIN__ +static const char* GCCXML_COMMAND = "ha_gccxml_cc1plus "; +#else +static const char* GCCXML_COMMAND = "./ha_gccxml_cc1plus "; +#endif + +// Parameters to parser +// +//static const char* GCCXML_DEFINE = " -D_DEBUG -D__wchar_t=wchar_t -D_UNICODE -D__SYMBIAN32__ -D__SERIES60_30__ -D__SERIES60_3X__ -D__GCC32__ -D__EPOC32__ -D__GCC32__ -D__MARM__ -D__GCCXML__ -D__MARM_ARM4__ -D__MARM_ARMV5__ -D__EXE__ -UWIN32 -U__i386__ -U_WIN32 -U__WIN32__"; +static const char* GCCXML_DEFINE = " -D_DEBUG -D_UNICODE -D__SYMBIAN32__ -D__SERIES60_30__ -D__SERIES60_3X__ -D__GCC32__ -D__GNUC__ -D__EPOC32__ -D__GCC32__ -D__MARM__ -D__GCCXML__ -D__MARM_ARM4__ -D__MARM_ARMV5__ -D__EXE__ -UWIN32 -U__i386__ -U_WIN32 -U__WIN32__"; + +static const char* GCCXML_OPTIONS = " -E -g -nostdinc -Wall -Wno-ctor-dtor-privacy -Wno-unknown-pragmas -fshort-wchar -quiet -w "; + +// Output file define +static const char* GCCXML_OUTPUT = " -o "; + +static const char* GCCXML_INCLUDEPATH = " -I "; + +// XML output file define +static const char* GCCXML_XML_OUTPUT = " -fxml="; + +static const char* GCCXML_MACRO_OUTPUT = " -dD "; + +#ifdef __WIN__ +// Error code when file remove fails +const int KErrorRemoveFailed=0; +static const char* GCCXML_COMP_OPTIONS = " -fpreprocessed -g -nostdinc -Wall -Wno-ctor-dtor-privacy -Wno-unknown-pragmas -fshort-wchar -quiet -w -o nul"; +#else +static const char* GCCXML_COMP_OPTIONS = " -fpreprocessed -g -nostdinc -Wall -Wno-ctor-dtor-privacy -Wno-unknown-pragmas -fshort-wchar -quiet -w -o /dev/null"; +#endif + + +// ---------------------------------------------------------------------------- +// CPPParser::GenerateCompilationCmd +// Generate command for compilation +// ---------------------------------------------------------------------------- +// +string CPPParser::GenerateCompilationCmd(const string& currentDir,const string& epocRoot,const string& inputFile,const string& outputFile) +{ + string cmdline; + if (currentDir != "") + { + cmdline = currentDir + "\"" + DIR_SEPARATOR + "\""; + } + cmdline += GCCXML_COMMAND; + cmdline += GCCXML_COMP_OPTIONS; + cmdline += GCCXML_XML_OUTPUT + string("\"") + outputFile + string("\" \""); + + + cmdline += inputFile + string("\"")+ string(" 2>\"") + iCompErrFile + string("\""); + + //cout << "-------COMPILATION-----------------------\n"; + //cout << cmdline << endl; + //cout << "-----------------------------------------\n"; + return cmdline; + +} + + +// ---------------------------------------------------------------------------- +// CPPParser::GeneratePreprocessCmd +// Generate GCXML command for prepocessing +// ---------------------------------------------------------------------------- +// +string CPPParser::GeneratePreprocessCmd(const string& currentDir,const string& epocRoot,const string& inputFile,const string& outputFile, + vector& aHeaders ) +{ + string cmdline; + + if (currentDir != "") + { + cmdline = currentDir + DIR_SEPARATOR; + } + cmdline += GCCXML_COMMAND; + + list > includes = BBCFileUtils::extractFilenames(epocRoot); + list >::iterator listbegin = includes.begin(); + list >::iterator listend = includes.end(); + for(; listbegin != listend; listbegin++) + { + cmdline += GCCXML_INCLUDEPATH + string("\"") + listbegin->first + string("\""); + } + + if ( !aHeaders.empty() ) + { + int size = (int)aHeaders.size(); + int i = 0; + + for(;i < size; i++) + { + string headerfile = aHeaders.at(i); + + cmdline += GCCXML_INCLUDEPATH + string("\"") + headerfile + string("\""); + } + } + + cmdline += GCCXML_DEFINE; + cmdline += GCCXML_OPTIONS; + cmdline += GCCXML_OUTPUT + string("\"") + outputFile + string("\" \""); + cmdline += inputFile + string("\""); + + //cout << "-------- PREPROCESS COMMAND --------------" << endl; + //cout << cmdline << endl; + //cout << "------------------------------------------" << endl; + + return cmdline; + +} + +// ---------------------------------------------------------------------------- +// CPPParser::GenerateMacroExtract +// Generate commanf or macro extract +// ---------------------------------------------------------------------------- +// +string CPPParser::GenerateMacroExtract(const string& currentDir,const string& epocRoot,const string& inputFile,const string& outputFile, + vector& aHeaders ) +{ + string cmdline; + + if (currentDir != "") + { + cmdline = currentDir + DIR_SEPARATOR; + } + cmdline += GCCXML_COMMAND; + + list > includes = BBCFileUtils::extractFilenames(epocRoot); + list >::iterator listbegin = includes.begin(); + list >::iterator listend = includes.end(); + for(; listbegin != listend; listbegin++) + { + cmdline += GCCXML_INCLUDEPATH + string("\"") + listbegin->first + string("\""); + } + + if ( !aHeaders.empty() ) + { + int size = (int)aHeaders.size(); + int i = 0; + + for(;i < size; i++) + { + string headerfile = aHeaders.at(i); + cmdline += GCCXML_INCLUDEPATH + string("\"") + headerfile + string("\""); + } + } + + cmdline += GCCXML_DEFINE; + cmdline += GCCXML_OPTIONS; + + cmdline += GCCXML_MACRO_OUTPUT; + cmdline += GCCXML_OUTPUT + string("\"") + outputFile + string("\" \""); + + cmdline += inputFile + string("\"")+ string(" 2>\"") + iCompErrFile + string("\""); + + //cout << "-----------------------------------------\n"; + //cout << cmdline << endl; + //cout << "-----------------------------------------\n"; + return cmdline; + +} + +// ---------------------------------------------------------------------------- +// CPPParser::CPPParser +// Constructor +// ---------------------------------------------------------------------------- +// +CPPParser::CPPParser(string epocroot) + : iInputFilename(), iOutputFilename(), iXMLOutputPath(), + iEpocRoot(epocroot), iDOMParser(NULL), iDOMDoc(NULL), + iDOMRootElement(NULL), iCompErrFile() +{ + +} + + +// ---------------------------------------------------------------------------- +// CPPParser::~CPPParser +// Destructor +// ---------------------------------------------------------------------------- +// +CPPParser::~CPPParser() +{ + if (iDOMParser != NULL) + { + iDOMParser->resetDocumentPool(); + iDOMParser->release(); + iDOMParser = NULL; + } +} + + +// ---------------------------------------------------------------------------- +// CPPParser::parse +// Please, note that iOutputFilename is changed internally in different +// function calls. +// ---------------------------------------------------------------------------- +// +DOMNode* CPPParser::parse(const vector& aFilenames, string aVersion, string aPath, list& notRemovedFiles) +{ + DOMNode* ret = NULL; + + int err = 0; + headervector headers; + string cppfilename = generateTempCPPFile(aFilenames, aVersion, headers ); + + string extensionStripped = BBCFileUtils::StripFilenameExtension(cppfilename); + iOriginalFilename = BBCFileUtils::StripPath(extensionStripped); + iCompErrFile = iTempDir + DIR_SEPARATOR + iOriginalFilename + "-" + aVersion + "-comperr.txt"; + try + { + err = PreprocessH(cppfilename, aVersion, headers); + } catch (HAException error) + { +#if !defined(_DEBUG) && !defined(DEBUG) + RemoveFile(cppfilename, notRemovedFiles); + RemoveFile(iMacroFilename, notRemovedFiles); +#endif + throw error; + } + RemoveFile(cppfilename, notRemovedFiles); + string prefilename = iOutputFilename; + HandleExports(iOutputFilename, aVersion); + string pre2filename = iOutputFilename; + try + { + err = ConvertHToXML(iOutputFilename, aVersion); + } catch (HAException error) + { +#if !defined(_DEBUG) && !defined(DEBUG) + RemoveFile(prefilename, notRemovedFiles); + RemoveFile(pre2filename, notRemovedFiles); + RemoveFile(iMacroFilename, notRemovedFiles); +#endif + throw error; + } + if (err == 0) + { + err = ExtractDOMFromXML(iOutputFilename); + ret = iDOMRootElement; + } + headers.clear(); + RemoveFile(prefilename, notRemovedFiles); + RemoveFile(pre2filename, notRemovedFiles); +#if !defined(_DEBUG) && !defined(DEBUG) + RemoveFile(iOutputFilename, notRemovedFiles); +#endif + + return ret; +} + + +// ---------------------------------------------------------------------------- +// CPPParser::RemoveFile +// Remove given file +// ---------------------------------------------------------------------------- +// +void CPPParser::RemoveFile(string file, list& notRemovedFiles) +{ + int success; +/*#ifdef __WIN__ + success = DeleteFile(file.c_str()); + if (success == KErrorRemoveFailed) + { + unsigned long int errorcode = GetLastError(); + if (errorcode != ERROR_FILE_NOT_FOUND) + { + notRemovedFiles.push_back(file); + } + } +#else + success = unlink(file.c_str()); + if (success == -1) + { + if (errno != ENOENT) + { + notRemovedFiles.push_back(file); + } + } +#endif*/ + REMOVE_FILE_FUNCTION +} + + +// ---------------------------------------------------------------------------- +// CPPParser::GenerateMacroExtract +// Converts a header file with given filename to an XML file +// (with same base filename and extension .xml). +// +// Throw an exception on error +// ---------------------------------------------------------------------------- +// +int CPPParser::ConvertHToXML(string aFilename, string aVersion) +{ + int ret = 0; + string oFilename; + string iFilename; + string tempOFilename; + + iFilename = aFilename; + tempOFilename = BBCFileUtils::StripPath(BBCFileUtils::StripFilenameExtension(iFilename)); + + oFilename = iTempDir + DIR_SEPARATOR + iOriginalFilename + "-" + aVersion + ".xml"; + char currentDir[KMaxDirLength]; + getcwd(currentDir,KMaxDirLength); + #ifdef USE_INCLUDED_GCC_DISTRIBUTION + string cmdline = GenerateCompilationCmd(currentDir, iEpocRoot, iFilename, oFilename); + #else + string empty(""); + string cmdline = GenerateCompilationCmd(empty, iEpocRoot, iFilename, oFilename); + #endif + + ret = system(cmdline.c_str()); + iXMLOutputPath = iTempDir; + iOutputFilename = oFilename; + iInputFilename = iFilename; + if (ret != 0) + { + throw(HAException("GCCXML Error, please see above for more information")); + } + return ret; +} + +// ---------------------------------------------------------------------------- +// CPPParser::GenerateMacroExtract +// Generate temporary CPP-file +// ---------------------------------------------------------------------------- +// +int CPPParser::DumpMacros(string mdumpfile, string ifile, vector& headers) +{ + int ret = 0; + string cmdbuf; + char currentDir[KMaxDirLength]; + getcwd(currentDir,KMaxDirLength); + #ifdef USE_INCLUDED_GCC_DISTRIBUTION + cmdbuf = GenerateMacroExtract(currentDir, iEpocRoot, ifile, mdumpfile, headers); + #else + string empty(""); + cmdbuf = GenerateMacroExtract(empty, iEpocRoot, ifile, mdumpfile,headers); + #endif + + ret = system(cmdbuf.c_str()); + return ret; +} + + +// ---------------------------------------------------------------------------- +// CPPParser::ExtractDOMFromXML +// Reads in and parses an XML file with given filename. +// ---------------------------------------------------------------------------- +// +int CPPParser::ExtractDOMFromXML(const string& aXMLFilename) +{ + int ret = 0; + + if (iDOMParser != NULL) { + iDOMParser->resetDocumentPool(); + iDOMParser->release(); + iDOMParser = NULL; + } + + return ParseXMLFile(aXMLFilename, iDOMParser, iDOMDoc, iDOMRootElement); +} + +// ---------------------------------------------------------------------------- +// CPPParser::setBaselineDir +// ---------------------------------------------------------------------------- +// +void CPPParser::setBaselineDir(string aRoot) +{ + iEpocRoot = aRoot; +} + + +// ---------------------------------------------------------------------------- +// CPPParser::PreprocessH +// ---------------------------------------------------------------------------- +// +int CPPParser::PreprocessH(string aFilename, string aVersion, vector& headers ) +{ + int ret = 0; + string oFilename; + string iFilename; + + string tempOFilename; + + iFilename = aFilename; + tempOFilename = iOriginalFilename; + + oFilename = iTempDir + DIR_SEPARATOR + tempOFilename + "-" + aVersion + ".pre"; + iMacroFilename = iTempDir + DIR_SEPARATOR + iOriginalFilename + "-" + aVersion + "-macros.txt"; + ret = DumpMacros(iMacroFilename, iFilename,headers); + if (ret != 0) + { + throw(HAException("GCCXML Error, please see above for more information")); + } + + char currentDir[KMaxDirLength]; + getcwd(currentDir,KMaxDirLength); + + #ifdef USE_INCLUDED_GCC_DISTRIBUTION + string cmdline = GeneratePreprocessCmd(currentDir,iEpocRoot,iFilename,oFilename, headers); + #else + string empty(""); + string cmdline = GeneratePreprocessCmd(empty,iEpocRoot,iFilename,oFilename, headers); + #endif + + ret = system(cmdline.c_str()); + if (ret != 0) + { + throw(HAException("GCCXML Error, please see above for more information")); + } + iXMLOutputPath = iTempDir; + iOutputFilename = oFilename; + iInputFilename = iFilename; + return ret; +} + +// ---------------------------------------------------------------------------- +// CPPParser::HandleExports +// ---------------------------------------------------------------------------- +// +int CPPParser::HandleExports(string aFilename, string aVersion) +{ + int ret = 0; + string ofilename = aFilename + ".2"; + + ifstream input(aFilename.c_str(), ios::in); + ofstream output(ofilename.c_str(), ios::out); + iOutputFilename = ofilename; + char c; + string toflush = ""; + unsigned int matches = 0; + string tofind = STR_EXPORT_HACK; + string attribstr = STR_ATTRIBUTE_STR; + string outputBuffer; + outputBuffer.reserve(PREPROCESS_BUFFERSIZE); + int state = EStateSearching; + bool purevirtual = false; + bool possiblepurevirtual = false; + while (input.get(c)) + { + if (outputBuffer.length() >= PREPROCESS_BUFFERSIZE) + { + output << outputBuffer; + outputBuffer = ""; + } + if (state == EStateSearching) + { + if (c == tofind.at(matches)) + { + matches++; + toflush += c; + } else + { + matches = 0; + if (!toflush.empty()) + { + outputBuffer += toflush; + toflush = ""; + } + outputBuffer += c; + } + if (matches == tofind.length()) + { + toflush = ""; + state = EStateReplacing; + matches = 0; + } + } else if (state == EStateReplacing) + { + if (c == '=') + { + if (possiblepurevirtual == true && !toflush.empty()) + { + outputBuffer += toflush; + toflush = ""; + } + possiblepurevirtual = true; + toflush += c; + } else if (possiblepurevirtual == true && c!= ';') + { + if (c == ' ') + { + toflush += c; + } else if (c == '\t') + { + toflush += c; + } else if (c == '0') + { + toflush += c; + purevirtual = true; + } else + { + outputBuffer += toflush; + outputBuffer += c; + toflush = ""; + possiblepurevirtual = false; + purevirtual = false; + } + } else if (c == ';') + { + state = EStateSearching; + if (purevirtual) + { + } else if (possiblepurevirtual) + { + outputBuffer += toflush; + toflush = ""; + } + + outputBuffer += " "; + outputBuffer += attribstr; + if (!toflush.empty()) + { + outputBuffer += " "; + outputBuffer += toflush; + toflush = ""; + } + possiblepurevirtual = false; + purevirtual = false; + outputBuffer += ';'; + } else + { + outputBuffer += c; + } + } else if (state == EStateReplaceDone) + { + + } + + } + if (outputBuffer.length() != 0) + { + output << outputBuffer; + } + return ret; +} + + +// ---------------------------------------------------------------------------- +// CPPParser::ReplaceExport +// ---------------------------------------------------------------------------- +// +#if 0 +int CPPParser::ReplaceExport(string line, string& processedline) +{ + int ret = 0; + if (processedline.length() == 0) + { + string tofind = STR_EXPORT_HACK; + size_t idx = line.find(tofind); + if (idx != string::npos) + { + unsigned int start = (unsigned int)idx + tofind.length(); + int len = (int)line.length() - start; + string sub = line.substr(start+1, len-1); + int insertidx = (int)sub.rfind("=0;"); + + if (insertidx < 0) + { + insertidx = (int)sub.rfind("= 0;"); + if (insertidx < 0) + { + insertidx = (int)sub.rfind(';'); + } + } + if (insertidx > 0) + { + sub.insert(insertidx, " __attribute((gccxml(\"exported\")))"); + } else + { + ret = 1; + } + processedline.append(sub); + } else + { + if (processedline.find("};") != string::npos ) + { + processedline.append(line); + ret = 0; + } + } + } else + { + string sub = line; + int insertidx = (int)sub.rfind("=0;"); + + if (insertidx < 0) + { + insertidx = (int)sub.rfind("= 0;"); + if (insertidx < 0) + { + insertidx = (int)sub.rfind(';'); + } + } + if (insertidx > 0) + { + sub.insert(insertidx, " __attribute((gccxml(\"exported\")))"); + ret = 0; + } else + { + ret = 1; + } + processedline = ""; + processedline.append(sub); + } + return ret; +} +#endif + + +// ---------------------------------------------------------------------------- +// CPPParser::getEnv +// ---------------------------------------------------------------------------- +// +char* CPPParser::getEnv(char* aEnvVarName) +{ + char* ret = getenv(aEnvVarName); + if (ret == NULL) + { + string s("Environment variable not defined: "); + s += aEnvVarName; + throw(new HAException(s)); + } + return ret; +} + +// ---------------------------------------------------------------------------- +// CPPParser::generateTempCPPFile +// ---------------------------------------------------------------------------- +// +string CPPParser::generateTempCPPFile(const vector& aFiles, string aVersion, vector& aHeaders) +{ + string headers = ""; + + if (!iForcedHeaders.empty()) + { + // START -- Support for multiple forced headers + list > fheaders = BBCFileUtils::extractFilenames(iForcedHeaders); + list >::iterator fheadersbegin = fheaders.begin(); + + for(; fheadersbegin != fheaders.end(); fheadersbegin++) + { + headers += "#include \""; + headers += fheadersbegin->first; + headers += "\"\n"; + } + // END -- Support for multiple forced headers + } + + size_t filecount = aFiles.size(); + int filehash = 0; + string ret = ""; + for (unsigned int i = 0; i < filecount; i++) + { + // Append header folder to include vector + //string& hdr = aFiles.at(i); + AppendHeader( aHeaders, aFiles.at(i) ); + + string fn = aFiles.at(i); + headers += "#include \""; + headers += fn; + headers += "\"\n"; + fn += "-"; + fn += aVersion; + filehash += BBCFileUtils::quickHash(fn); + } + string temp; + itoa(filehash, temp, 10); + ret = iTempDir + DIR_SEPARATOR + temp + ".cpp"; + + ofstream output(ret.c_str(), ios::out); + output << headers; + output.close(); + return ret; +} + +// ---------------------------------------------------------------------------- +// CPPParser::setForcedHeaders +// ---------------------------------------------------------------------------- +// +void CPPParser::setForcedHeaders(const string& aHeaders) +{ + iForcedHeaders = aHeaders; +} + +// ---------------------------------------------------------------------------- +// CPPParser::setTemp +// Set temp file +// ---------------------------------------------------------------------------- +// +void CPPParser::setTemp(const string& aTempDir) +{ + iTempDir = aTempDir; +} + +// ---------------------------------------------------------------------------- +// CPPParser::getMacroFilename +// Returns macro filename +// ---------------------------------------------------------------------------- +// +string CPPParser::getMacroFilename() +{ + return iMacroFilename; +} + +// ---------------------------------------------------------------------------- +// CPPParser::getCompErrFile +// Returns compilation error filename +// ---------------------------------------------------------------------------- +// +string CPPParser::getCompErrFile() +{ + return iCompErrFile; +} + +// ---------------------------------------------------------------------------- +// CPPParser::AppendHeader +// ---------------------------------------------------------------------------- +// +void CPPParser::AppendHeader( vector& aHeaders, string aFile ) +{ + string onlyFolder = aFile; + + string::size_type idx = onlyFolder.rfind(DIR_SEPARATOR); + + // for other separation formats + if (idx != string::npos) + { + onlyFolder.erase( idx ); + } + + if (onlyFolder.size() == ANALYSER_HEADER_SIZE) + { + onlyFolder += APPEND_DIR_SEPARATOR; + } + + bool notFound = true; + unsigned int size = (unsigned int)aHeaders.size(); + + for(unsigned int g = 0; g < size ; g++ ) + { + if( aHeaders.at(g) == onlyFolder ) + { + notFound = false; + size = (unsigned int)aHeaders.size(); + } + } + + if( notFound ) + { + aHeaders.push_back( onlyFolder ); + } +}