--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/CommandLine.cpp Tue Jan 12 14:52:39 2010 +0530
@@ -0,0 +1,681 @@
+/*
+* 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 "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 "CmdGlobals.h"
+#ifdef __WIN__
+#pragma warning(disable:4786)
+#endif
+
+#ifndef _MSC_VER
+#define stricmp strcasecmp
+#endif
+#include <iostream>
+#include <sstream>
+#include <map>
+
+#include "CommandLine.h"
+#include "HAException.h"
+#include "CmdGlobals.h"
+#include "CommandFile.h"
+#include "BBCFileUtils.h"
+#include "Utils.h"
+#include "ReportGeneratorConstants.h"
+
+
+using namespace std;
+
+
+// ----------------------------------------------------------------------------
+// CommandLine::CommandLine
+// Constructor
+// ----------------------------------------------------------------------------
+//
+CommandLine::CommandLine() : iParametersValid(-1)
+{
+ initializeAcceptableParametersList();
+}
+
+
+// ----------------------------------------------------------------------------
+// CommandLine::CommandLine
+// Constructor
+// ----------------------------------------------------------------------------
+//
+CommandLine::CommandLine(char** args, int argc) : iParametersValid(-1)
+{
+ // first check if the command line parameters contain any help command
+ int i=1;
+ while (i<argc)
+ {
+ if (stricmp("-?", args[i])==0 || stricmp("-h", args[i])==0 || stricmp("--help", args[i])==0)
+ {
+ showCommandLineOptionsAndExit();
+ }
+ i++;
+ }
+
+ initializeAcceptableParametersList();
+ iArgList = args;
+ iArgCount = argc;
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::~CommandLine
+// Destructor
+// ----------------------------------------------------------------------------
+//
+CommandLine::~CommandLine()
+{
+ iAcceptableParameterMap.clear();
+ parameterSpecifierSet.clear();
+ requiredParametersSet.clear();
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::getParameter
+// Returns the parameter value for a given parameter
+// ----------------------------------------------------------------------------
+//
+string CommandLine::getParameter(string aParm)
+{
+ map<string, string>::iterator mapitem = iParameterMap.find(aParm);
+ bool isValidParm = mapitem == iParameterMap.end() ? false : true;
+ if (!isValidParm)
+ {
+ string excstr = "No such parameter: ";
+ excstr += aParm;
+ throw HAException(excstr);
+ }
+ return mapitem->second;
+}
+
+const map <string, string>& CommandLine::getParameters()
+{
+ return iParameterMap;
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::CommandLine
+// ----------------------------------------------------------------------------
+//
+void CommandLine::insertParameter(string paramName, bool specifierRequired, bool optional)
+{
+ mapentry parm(paramName, "");
+ iAcceptableParameterMap.insert(parm);
+ if (specifierRequired)
+ {
+ parameterSpecifierSet.insert(paramName);
+ }
+ if (!optional)
+ {
+ requiredParametersSet.insert(paramName);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::parameterExists
+// Check parameter existence
+//
+// ----------------------------------------------------------------------------
+//
+bool CommandLine::parameterExists(const string& aParmName)
+{
+ bool ret = false;
+ map<string, string>::iterator mapitem = iParameterMap.find(aParmName);
+ if (mapitem != iParameterMap.end())
+ {
+ ret = true;
+ }
+ return ret;
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::initializeAcceptableParametersList
+// Initialize acceptable parameter list
+//
+// ----------------------------------------------------------------------------
+//
+void CommandLine::initializeAcceptableParametersList()
+{
+ // note: baseline/current may be long strings (ie. many filenames separated by semicolons)
+ insertParameter(BASELINE, true);
+ insertParameter(CURRENT, true);
+ insertParameter(BASELINEDIR, true);
+ insertParameter(CURRENTDIR, true);
+ insertParameter(REPORTFILE, true, false);
+ insertParameter(BASELINEVERSION, true);
+ insertParameter(CURRENTVERSION, true);
+ insertParameter(COMMANDFILE, false);
+ insertParameter(BASEPLATFORMDATA, true);
+ insertParameter(CURRENTPLATFORMDATA, true);
+
+ insertParameter(RECURSIVE, false);
+ insertParameter(FILEREPLACE, true);
+ insertParameter(HEADERSET, true);
+ insertParameter(BASELINEPLAT, true, false);
+ insertParameter(CURRENTPLAT, true, false);
+ insertParameter(BUNDLESIZE, true);
+ insertParameter(TRIMXML, true);
+ insertParameter(TEMPDIR, true, false);
+ insertParameter(BASEFORCEDHEADERSFILE, true);
+ insertParameter(CURRENTFORCEDHEADERSFILE, true);
+ insertParameter(DOCURL, true);
+ insertParameter(DISCARDDIRS, true);
+#if defined(_DEBUG) || defined(DEBUG)
+ insertParameter(COMMANDLINETEST, false);
+#endif
+ insertParameter(USETHREAD, false);
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::validateParameters
+// Validate parameters
+//
+// ----------------------------------------------------------------------------
+//
+string CommandLine::validateParameters()
+{
+ ostringstream ret;
+ parse(iArgList, iArgCount);
+
+ map<string, string>::iterator mapitem = iParameterMap.find(TEMPDIR);
+ if (mapitem == iParameterMap.end() || mapitem->second.length() < 1)
+ {
+ const char* env2 = getenv("TEMP");
+ if (env2 != NULL)
+ {
+ string tempfiles(env2);
+ if (mapitem != iParameterMap.end())
+ {
+ mapitem->second = tempfiles;
+ } else
+ {
+ pair <string,string> parm(TEMPDIR, tempfiles);
+ iParameterMap.insert(parm);
+ }
+ }
+ }
+
+ mapitem = iParameterMap.find(BASELINEPLAT);
+ if (mapitem == iParameterMap.end() || mapitem->second.length() < 1)
+ {
+ string envvar = BASELINEPLAT;
+ const char* env2 = getenv(toUpperCase(envvar).c_str());
+ if (env2 != NULL)
+ {
+ string tempfiles(env2);
+ if (mapitem != iParameterMap.end())
+ {
+ mapitem->second = tempfiles;
+ } else
+ {
+ pair <string,string> parm(TEMPDIR, tempfiles);
+ iParameterMap.insert(parm);
+ }
+ }
+ }
+
+ mapitem = iParameterMap.find(CURRENTPLAT);
+ if (mapitem == iParameterMap.end() || mapitem->second.length() < 1)
+ {
+ string envvar = CURRENTPLAT;
+ const char* env2 = getenv(toUpperCase(envvar).c_str());
+ if (env2 != NULL)
+ {
+ string tempfiles(env2);
+ if (mapitem != iParameterMap.end())
+ {
+ mapitem->second = tempfiles;
+ } else
+ {
+ pair <string,string> parm(TEMPDIR, tempfiles);
+ iParameterMap.insert(parm);
+ }
+ }
+ }
+
+ // START -- Support for multiple header directories --
+ mapitem = iParameterMap.find(BASELINEDIR);
+ if (mapitem == iParameterMap.end() || mapitem->second.length() < 1)
+ {
+ string envvar = BASELINEDIR;
+ const char* env2 = getenv(toUpperCase(envvar).c_str());
+ if (env2 != NULL)
+ {
+ string tempfiles(env2);
+ if (mapitem != iParameterMap.end())
+ {
+ mapitem->second = tempfiles;
+ } else
+ {
+ pair <string,string> parm(TEMPDIR, tempfiles);
+ iParameterMap.insert(parm);
+ }
+ }
+ }
+
+ mapitem = iParameterMap.find(CURRENTDIR);
+ if (mapitem == iParameterMap.end() || mapitem->second.length() < 1)
+ {
+ string envvar = CURRENTDIR;
+ const char* env2 = getenv(toUpperCase(envvar).c_str());
+ if (env2 != NULL)
+ {
+ string tempfiles(env2);
+ if (mapitem != iParameterMap.end())
+ {
+ mapitem->second = tempfiles;
+ } else
+ {
+ pair <string,string> parm(TEMPDIR, tempfiles);
+ iParameterMap.insert(parm);
+ }
+ }
+ }
+ // END -- Support for multiple header directories --
+
+ set<string>::iterator setitem = requiredParametersSet.begin();
+ while (setitem != requiredParametersSet.end())
+ {
+ string s = *setitem;
+ map<string, string>::iterator mapitem = iParameterMap.find(s);
+ if (mapitem == iParameterMap.end())
+ {
+ if (ret.str().length() == 0)
+ {
+ ret << "Missing required parameters: ";
+ }
+ ret << s;
+ ret << " ";
+ } else
+ {
+ // else branch not required anymore
+ if (mapitem->second.length() == 0)
+ {
+ if (ret.str().length() == 0)
+ {
+ ret << "Missing required parameters: ";
+ }
+ ret << s;
+ ret << " ";
+ }
+ }
+ setitem++;
+ }
+
+ if (ret.str().length() > 0)
+ {
+ ret << "\n";
+ }
+
+ if (!parameterExists(BASELINE) && !parameterExists(BASELINEDIR) && !parameterExists(CURRENT) && !parameterExists(CURRENTDIR))
+ {
+ ret << "One of the parameter listed next must be given: -"<< BASELINEDIR <<" -"<< BASELINE <<"\n";
+ ret << "One of the parameter listed next must be given: -"<< CURRENTDIR <<" -"<< CURRENT <<"\n";
+ }
+
+ // check for parameter conflicts in baseline parameters
+ if (parameterExists(BASELINE) && parameterExists(BASELINEDIR))
+ {
+ ret << "Parameter conflict: -"<< BASELINEDIR <<" and -"<< BASELINE <<" cannot co-exist\n";
+ } else
+ {
+ if (parameterExists(BASELINE) && !parameterExists(CURRENT))
+ {
+ ret << "Parameter conflict: When -"<< BASELINE <<" is specified then also -"<< CURRENT <<" is required.\n";
+ }
+ if (parameterExists(BASELINEDIR) && !parameterExists(CURRENTDIR))
+ {
+ ret << "Parameter conflict: When -"<< BASELINEDIR <<" is specified then also -"<< CURRENTDIR <<" is required.\n";
+ }
+ }
+
+ // Same for current headers
+ if (parameterExists(CURRENT) && parameterExists(CURRENTDIR))
+ {
+ ret << "Parameter conflict: -"<< CURRENTDIR <<" and -"<< CURRENT <<" cannot co-exist\n";
+ } else
+ {
+ if (parameterExists(CURRENT) && !parameterExists(BASELINE))
+ {
+ ret << "Parameter conflict: When -"<< CURRENT <<" is specified then also -"<< BASELINE <<" is required.\n";
+ }
+ if (parameterExists(CURRENTDIR) && !parameterExists(BASELINEDIR))
+ {
+ ret << "Parameter conflict: When -"<< CURRENTDIR <<" is specified then also -"<< BASELINEDIR <<" is required.\n";
+ }
+ }
+
+ // Check for parameters which are specific only for baselinedir/currentdir
+ if (parameterExists(BASELINE) || parameterExists(CURRENT))
+ {
+ if (parameterExists(FILEREPLACE))
+ {
+ ret << "Parameter conflict: -"<< FILEREPLACE <<" cannot be used in combination with file parameters (-"<< CURRENT <<"/-"<< BASELINE <<")\n";
+ }
+ if (parameterExists(RECURSIVE))
+ {
+ ret << "Parameter conflict: -"<< RECURSIVE <<" cannot be used in combination with file parameters (-"<< CURRENT <<"/-"<< BASELINE <<")\n";
+ }
+ if (parameterExists(HEADERSET))
+ {
+ ret << "Parameter conflict: -"<< HEADERSET <<" cannot be used in combination with file parameters (-"<< CURRENT <<"/-"<< BASELINE <<")\n";
+ }
+ }
+ if (!parameterExists(RECURSIVE) && parameterExists(DISCARDDIRS))
+ {
+ ret << "Parameter conflict: -"<< DISCARDDIRS <<" requires -"<< RECURSIVE <<"\n";
+ }
+ // Check that all the parameters that require a specifier
+ // indeed contain a specifier. If not, it's an error and must
+ // be reported
+ set<string>::iterator specIt = parameterSpecifierSet.begin();
+ while (specIt != parameterSpecifierSet.end())
+ {
+ map<string,string>::iterator parmIt = iParameterMap.find(*specIt);
+ if (parmIt != iParameterMap.end())
+ {
+ if (parmIt->second.length() < 1)
+ {
+ ret << "Missing required specifier for parameter -";
+ ret << *specIt;
+ ret << "\n";
+ }
+ }
+ specIt++;
+ }
+ return ret.str();
+}
+
+
+// ----------------------------------------------------------------------------
+// CommandLine::validParamValue
+// Check if the parameter value is valid.
+// ----------------------------------------------------------------------------
+//
+void CommandLine::validParamValue(string parm,string val)
+{
+ string ret;
+
+ // Don't check parameter 'recursive' , 'usethread' or any other that
+ // doesn't need a value.
+ int dontCheckParm = parm.compare( RECURSIVE);
+ int threadParm = parm.compare( USETHREAD);
+
+ if ( dontCheckParm !=0 && threadParm != 0 )
+ {
+ if ( parm.compare( BASELINEVERSION )==0 || parm.compare( CURRENTVERSION )==0 || parm.compare( BUNDLESIZE )==0 || parm.compare( HEADERSET )==0 )
+ {
+ //check for atleast one char long
+ if( val.length()<=0 )
+ {
+ ret = "Invalid value for parameter: " + parm + '\n';
+ throw HAException(ret);
+ }
+ }
+ else
+ {
+ //check for atleast two char long
+ if ( val.length()<=1 )
+ {
+ ret = "Invalid value for parameter: " + parm + '\n';
+ throw HAException(ret);
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::storeParameter
+// Stores a parameter.
+// ----------------------------------------------------------------------------
+//
+void CommandLine::storeParameter(string parm, string val, int parmType)
+{
+ map<string, string>::iterator mapitem;
+ bool isValidParm = false;
+ string errormsg;
+ mapitem = iAcceptableParameterMap.find(parm);
+ isValidParm = mapitem == iAcceptableParameterMap.end() ? false : true;
+ validParamValue(parm, val);
+ if (isValidParm && parm.length() > 0)
+ {
+ // Valid parameters are those that the map structure has been initialised with;
+ // any other parameter is invalid, and will yield an error.
+ bool needsSpecifier = parameterSpecifierSet.find(parm) == parameterSpecifierSet.end() ? false : true;
+ map<string, string>::iterator mapitem2;
+ mapitem2 = iParameterMap.find(parm);
+ pair<string,string> parmToInsert(parm, val);
+ if (needsSpecifier)
+ {
+ // Arguments that need specifier must have both the ARGUMENT_NAME and VALUE
+ // (ie. both fields in the map must be of nonzero length)
+ if (val.length() > 0)
+ {
+ if (parmType == EParmCommandFile)
+ {
+ // command file arguments can't replace (already existing) command-line
+ // arguments; command-file args will only be used when no similar
+ // argument was given in commandline.
+ if (mapitem2 != iParameterMap.end())
+ {
+#if ( defined(_DEBUG) || defined(DEBUG) ) && !defined(NO_DBG)
+ cout << "Not overriding parameter from file: " << parm << "\n";
+#endif
+ } else
+ {
+#if ( defined(_DEBUG) || defined(DEBUG) ) && !defined(NO_DBG)
+ cout << "Got command-file parameter: "<<parm<<" value: "<<val<<"\n";
+#endif
+ iParameterMap.insert(parmToInsert);
+ }
+ } else if (parmType == EParmCommandLine)
+ {
+ // command-line argument always overrides
+#if ( defined(_DEBUG) || defined(DEBUG) ) && !defined(NO_DBG)
+ cout << "Got command-line parameter: "<<parm<<" value: "<<val<<"\n";
+#endif
+ iParameterMap.insert(parmToInsert);
+ } else if (parmType == EParmEnvironment)
+ {
+ }
+ } else {
+ errormsg = "Expected non-empty specifier for parameter \"-" + parm + "\"\n";
+ throw(new HAException(errormsg));
+ }
+ } else
+ {
+#if ( defined(_DEBUG) || defined(DEBUG) ) && !defined(NO_DBG)
+ cout << "Got switch: "<<parm<<"\n";
+#endif
+ iParameterMap.insert(parmToInsert);
+ }
+ } else {
+ // Throw an exception containing the list of valid parameter names.
+ string errormsg = "Invalid parameter: " + parm + "\n";
+/*
+ errormsg += "Valid parameters are:\n";
+
+ map<string,string>::iterator iter;
+ iter = iAcceptableParameterMap.begin();
+ while (iter != iAcceptableParameterMap.end())
+ {
+ errormsg += "\t" + iter->first + "\n";
+ iter++;
+ }
+*/
+ HAException e(errormsg);
+ throw(e);
+ }
+
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::parse
+// ----------------------------------------------------------------------------
+//
+void CommandLine::parse(char** parms, size_t count, int parmsType)
+{
+ // "Key" string
+ string currentstr;
+ // "Value" string
+ string currentparam;
+ bool hasSpace = false;
+ bool isString = false;
+ int lastPos = -1;
+
+ // Iterate through the parameters, char by char.
+ // argument names have a preceding '-' (and whitespace),
+ // argument values only have a preceding ' ' (whitespace).
+ for (unsigned int i = 1; i < count; i++)
+ {
+ int j = 0;
+ char ch = parms[i][j];
+ if (i > 1 && j == 0 && ch == '-')
+ {
+ if (hasSpace == true && currentparam == FILEREPLACE)
+ {
+ if (currentstr.at(lastPos) != '\"')
+ {
+ currentstr = currentstr.substr(0, lastPos) + "\"" + currentstr.substr(lastPos);
+ }
+ currentstr = currentstr + "\"";
+ }
+ storeParameter(currentparam, currentstr, parmsType);
+ currentparam = "";
+ currentstr = "";
+ isString = false;
+ hasSpace = false;
+ } else if (i > 1 && j == 0 && isString == false)
+ {
+ isString = true;
+ hasSpace = false;
+ lastPos = 0;
+ } else if (i > 1 && j == 0)
+ {
+ if (hasSpace == true && currentparam == FILEREPLACE)
+ {
+ if (currentstr.at(lastPos) != '\"')
+ {
+ currentstr = currentstr.substr(0, lastPos) + "\"" + currentstr.substr(lastPos);
+ }
+ currentstr = currentstr + "\"";
+ }
+ currentstr += ' ';
+ hasSpace = false;
+ lastPos = (int)currentstr.length();
+ }
+ while (ch != '\0')
+ {
+ if (ch == '\\' || ch == '/')
+ {
+ ch = DIR_SEPARATOR;
+ }
+ if (!isString)
+ {
+ if (j > 0)
+ {
+ currentparam += ch;
+ }
+ } else
+ {
+ if (ch == ' ') hasSpace = true;
+ currentstr += ch;
+ }
+ j++;
+ ch = parms[i][j];
+ }
+ }
+
+ // Dump the last one as well
+ if ( count > 1)
+ {
+ if (hasSpace == true && currentparam == FILEREPLACE)
+ {
+ currentstr = "\"" + currentstr + "\"";
+ }
+ storeParameter(currentparam, currentstr, parmsType);
+ }
+
+ // If the processed arguments didn't come from command file,
+ // check out if one exists and parse it if necessary.
+ if (parmsType != EParmCommandFile && parameterExists(COMMANDFILE))
+ {
+ string s = BBCFileUtils::getFullPath(getParameter(COMMANDFILE));
+ storeParameter(COMMANDFILE, s);
+ if (s.size() > 0)
+ {
+
+ CommandFile f = CommandFile(s);
+ char** commands = f.getCommandBuffer();
+ size_t length = f.commandBufferLength();
+ parse(commands, length , EParmCommandFile);
+ }
+ }
+ iParametersValid = true;
+
+}
+
+// ----------------------------------------------------------------------------
+// CommandLine::showCommandLineOptionsAndExit
+// Show options and exit
+// ----------------------------------------------------------------------------
+//
+void CommandLine::showCommandLineOptionsAndExit()
+{
+ cout << "HeaderAnalyser v" << HEADER_ANALYSER_VERSION << " - " << HEADER_ANALYSER_DATE << endl;
+ cout << "Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.\n"
+ "\n"
+ "Usage: ha [parameters]\n"
+ "\n"
+ "Parameters:\n"
+ " -baseline FILE Baseline FILE used when comparing two files\n"
+ " -current FILE Current release FILE used when comparing two files\n"
+ " -baselinedir Baseline directory WILDCARDS used when comparing two files\n"
+ " WILDCARDS;WILDCARDS\n"
+ " -currentdir Current release DIR used when comparing two files\n"
+ " DIR;DIR\n"
+ " -baselineversion NAME NAME of the baseline\n"
+ " -currentversion NAME NAME of the current release\n"
+ " -reportfile FILE Save report to FILE\n"
+ " -commandfile FILE Read command line parameters from FILE\n"
+ " -baseplatformheaders Read baseline platform headers from DIR\n"
+ " DIR;DIR\n"
+ " -currentplatformheaders Read current release platform headers from DIR\n"
+ " DIR;DIR\n"
+ " -forcebaseinclude Force to include this FILE always for baseline\n"
+ " FILE;FILE\n"
+ " -forcecurrentinclude Force to include this FILE always for current release\n"
+ " FILE;FILE\n"
+ " -recursive Include sub directories when scanning files\n"
+ " -excludedirs DIR;DIR When recursive is in use, exclude DIR\n"
+ " -set FILE;FILE Include only this FILE to the analysis. Wildcards can be used also.\n"
+ " -replace FILE NEWFILE Notify FILE has been renamed as NEWFILE in current\n"
+ " -bundlesize COUNT Specifies COUNT files are processed in one go\n"
+ " -temp DIRECTORY DIRECTORY to store intermediate files\n"
+ " -docurl URL Includes documentation URL for each issue\n"
+ " -baseplatformdata FILE Read baseline platform data from FILE.\n"
+ " The data is used when compiling the baseline headers\n"
+ " -currentplatformdata FILE Read current platform data from FILE.\n"
+ " The data is used when compiling the current headers\n"
+ " -usethread Enables multiple threading logic.Useful for Public vs Rnd\n"
+ " Sdk analysis or small no of headers (<3000).\n"
+ "\n";
+
+ exit(0);
+}