diff -r d27dfa8884ad -r da2cedce4920 analyzetool/commandlineengine/src/arguments.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/analyzetool/commandlineengine/src/arguments.cpp Tue May 25 14:22:58 2010 +0300 @@ -0,0 +1,798 @@ +/* +* Copyright (c) 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: Argument parsing functions. +*/ +#include "../inc/ATCommonDefines.h" +#include "../inc/CATBase.h" + +//Forward declarations. +bool parseBaseArguments( vector& vArgs, ARGUMENTS& args ); +bool parseHookArguments( vector& vArgs, ARGUMENTS& args ); +bool parseAnalyzeArguments( vector& vArgs, ARGUMENTS& args ); +bool parseParseArguments( vector& vArgs, ARGUMENTS& args ); +bool checkDataFileName( string& sFileName ); +bool parseSbsConfiguration( string& sConfiguration, ARGUMENTS& args ); + +// Constants for old "hooking" parameter parsing. +#define INVALID_PARAMETER "AnalyzeTool : Error, invalid parameter: " +const char DATAFILENAME_INVALID_CHARS[] = " &^+-@$%*()|\\/[]{}<>?;:,\"'"; + +/** +* Check datafile name for invalid characters. +* @return true if file name ok. +*/ +bool checkDataFileName( string& sFileName ) +{ + for ( size_t i = 0; i < sFileName.length(); i++ ) + { + const char c = sFileName.at( i ); + if( strchr( DATAFILENAME_INVALID_CHARS, c ) != 0 ) + return false; + } + return true; +} + +/** +* Parse base arguments from given vector of strings. +* Removes debug / help arguments from vector. +*/ +bool parseBaseArguments( vector& vArgs, ARGUMENTS& args ) +{ + // Iterator used in this function. + vector::iterator it; + // If no arguments set show help true. + if ( vArgs.size() == 0 ) + { + args.eMainSwitch = SWITCH_UNKNOWN; + args.bHelp = true; + } + //Try find help and debug switches. + //Note: -help is main switch what shows syntax examples. + for(it = vArgs.begin(); it != vArgs.end(); it++ ) + { + //Help switches. + if ( ! _stricmp( (*it).c_str(), "-?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--help" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "/?" ) ) + { + args.bHelp = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + //Debug switches. + else if ( ! _stricmp( (*it).c_str(), "-show_debug" ) ) + { + args.bDebugConsole = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_debug" ) ) + { + args.bDebugConsole = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_debug_all" ) ) + { + args.bDebugConsole = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_debug_all" ) ) + { + args.bDebugConsole = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_dbgview" ) ) + { + args.bDebugDbgView = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_dbgview" ) ) + { + args.bDebugDbgView = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "-show_dbgview_all" ) ) + { + args.bDebugDbgView = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + else if ( ! _stricmp( (*it).c_str(), "--show_dbgview_all" ) ) + { + args.bDebugDbgView = true; + args.bDebugLowLevel = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + //Raptor switch. + else if ( ! _stricmp( (*it).c_str(), "-sbs2" ) ) + { + args.bEnableSbs2 = true; + it = vArgs.erase( it ); + if ( it == vArgs.end() ) + break; + } + } + if ( vArgs.size() > 0 ) + { + //Pick up main switch. + it = vArgs.begin(); + if ( ! _stricmp( (*it).c_str(), "-a" ) ) + args.eMainSwitch = SWITCH_ANALYZE; + else if ( ! _stricmp( (*it).c_str(), "-p" ) ) + args.eMainSwitch = SWITCH_PARSE_TRACE; + else if ( ! _stricmp( (*it).c_str(), "-c" ) ) + args.eMainSwitch = SWITCH_CLEAN; + else if ( ! _stricmp( (*it).c_str(), "-v" ) ) + args.eMainSwitch = SWITCH_VERSION; + else if ( ! _stricmp( (*it).c_str(), "-vdbghelp" ) ) + args.eMainSwitch = SWITCH_DBGHELP_VERSION; + else if ( ! _stricmp( (*it).c_str(), "-help" ) ) + args.eMainSwitch = SWITCH_HELP; + else if ( ! _stricmp( (*it).c_str(), "-me" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-e" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTERNAL_FAST; + } + else if ( ! _stricmp( (*it).c_str(), "-mi" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_INTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_i" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_INTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_e" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_EXTERNAL; + } + else if ( ! _stricmp( (*it).c_str(), "-instrument_ef" ) ) + { + args.eMainSwitch = SWITCH_HOOK; + args.eHookSwitch = HOOK_EXTENSION_EXTERNAL_FAST; + } + else if ( ! _stricmp( (*it).c_str(), "-uninstrument" ) ) + { + args.eMainSwitch = SWITCH_UNHOOK; + args.eHookSwitch = HOOK_EXTENSION_UNINSTRUMENT; + } + else if ( ! _stricmp( (*it).c_str(), "-uninstrument_failed" ) ) + { + args.eMainSwitch = SWITCH_UNHOOK; + args.eHookSwitch = HOOK_EXTENSION_FAILED; + } + } + return true; +} + +/** +* Parse analyze related arguments from given vector of strings. +*/ +bool parseAnalyzeArguments( vector& vArgs, ARGUMENTS& args ) +{ + bool bRet = true; + if ( vArgs.size() < 2 ) + { + cout << AT_MSG << "Error, missing datafile." << endl; + return false; + } + // Iterator used in this function. + vector::const_iterator it; + for(it = vArgs.begin()+1; it != vArgs.end(); it++ ) + { + if ( it->find("-l") != string::npos ) + { + if ( it->length() == 3 ) + { + // Create char array for atoi function + char level[2]; + level[0] = it->at(2); + level[1] = 0; // null terminate + // check that its digit first + if ( isdigit(level[0]) ) + { + // pass array to atoi + int iLoggingLevel = atoi( level ); + if ( iLoggingLevel >= 0 && iLoggingLevel <= 3 ) + { + // log level ok + args.ANALYZE.iLoggingLevel = iLoggingLevel; + continue; + } + } + bRet = false; + cout << AT_MSG << "Invalid logging level specified (0-3)." << endl; + args.ANALYZE.iLoggingLevel = -1; + } + } + // No else here because logging level check is done to all args in list. + // Rom symbol file + if( _stricmp( it->c_str(), "-s" ) == 0 ) + { + it++; + if ( it == vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Missing symbol file." << endl; + break; // Leave for loop. + } + else + { + args.ANALYZE.bSymbolFile = true; + args.ANALYZE.vSymbolFiles.push_back( *it ); + continue; + } + } + else + { + // If we got datafile we must assume this is output + if( ! args.ANALYZE.sDataFile.empty() ) + { + if ( args.ANALYZE.sOutputFile.empty() ) + args.ANALYZE.sOutputFile = *it; + else + { + bRet = false; + cout << AT_MSG << "Invalid parameter: " << *it << endl; + } + } + // If this is file we assume datafile + else if( CATBase::FileExists( it->c_str() ) ) + { + args.ANALYZE.sDataFile = *it; + } + else + { + bRet = false; + cout << AT_MSG << "Specified datafile does not exist." << endl; + } + } + } + if ( args.ANALYZE.sDataFile.empty() ) + bRet = false; + return bRet; +} + + +/** +* Parse hooking related arguments from given vector of strings. +*/ +bool parseHookArguments( vector& vArgs, ARGUMENTS& args ) +{ + bool bRet = true; + try { + // Iterator used in this function. + vector::const_iterator it; + + // Check that we have some arguments except main switch. + if ( vArgs.size() < 2 ) + { + if ( args.eHookSwitch == HOOK_EXTENSION_UNINSTRUMENT + || args.eHookSwitch == HOOK_EXTENSION_FAILED + ) + return bRet; + cout << AT_MSG << "Error, Missing build command." << endl; + bRet = false; + } + bool bBuildFound = false; + for(it = vArgs.begin()+1; it != vArgs.end(); it++ ) + { + // If's to pickup atool options + // no build switch + if ( _stricmp( it->c_str(), "-nobuild" ) == 0 ) + { + args.HOOK.bNoBuild = true; + } + // call stack size(s) + else if ( _stricmp( it->c_str(), "-acs" ) == 0 || _stricmp( it->c_str(), "-fcs" ) == 0 ) + { + // Free vs Alloc + bool bAlloc = true; + if ( _stricmp( it->c_str(), "-fcs" ) == 0 ) + bAlloc = false; + // Value + it++; + if ( it== vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Error, missing call stack size parameter." << endl; + break; + } + else if ( ! _stricmp( it->c_str(), "sbs" ) + || ! _stricmp( it->c_str(), "abld" ) + || ! _stricmp( it->c_str(), "-f" ) ) + { + bRet = false; + cout << AT_MSG << "Error, missing call stack size parameter." << endl; + break; + } + else + { + int i; + // Try to parse integer value using stream. + istringstream ss( *it ); + if ( ss>>i ) + { + // Value parsed ok now check bounds. + if ( i < AT_CALL_STACK_SIZE_MIN ) + { + bRet = false; + cout << AT_MSG << "Error, specified call stack size value too small." << endl; + break; + } + else if ( i > AT_CALL_STACK_SIZE_MAX ) + { + bRet = false; + cout << AT_MSG << "Error, specified call stack size value too big." << endl; + break; + } + else + { + // Value valid. + if ( bAlloc ) + args.HOOK.iAllocCallStackSize = i; + else + args.HOOK.iFreeCallStackSize = i; + } + } + else + { + // Error parsing value using stream. + bRet = false; + cout << AT_MSG << "Error, specified call stack size value invalid." << endl; + break; + } + + } + } + // Data file name. + else if ( _stricmp( it->c_str(), "-f" ) == 0 ) + { + it++; + if ( it == vArgs.end() ) + { + bRet = false; + cout << AT_MSG << "Error, missing internal data gathering file name." << endl; + break; + } + else if ( ! _stricmp( it->c_str(), "sbs" ) || ! _stricmp( it->c_str(), "abld" ) ) + { + bRet = false; + cout << AT_MSG << "Error, missing internal data gathering file name." << endl; + break; + } + else + { + if ( checkDataFileName( string( *it ) ) ) + { + // Pickup filename. + args.HOOK.bDataFileName = true; + args.HOOK.sDataFileName = *it; + } + else + { + bRet = false; + cout << AT_MSG << "Error, specified internal data gathering file name contains invalid character(s)." << endl; + break; + } + } + } + // Build command parsing. + else if ( _stricmp( it->c_str(), "sbs" ) == 0 ) + { + // By default sbs command is not valid. + bRet = false; + // By default build found + bBuildFound = true; + // Use raptor build system, pickup all rest arguments to sbs commmand. + bool bFoundConfig = false; // Is configuration defined. + args.HOOK.iBuildSystem = 2; + vector::const_iterator itC = it; + args.HOOK.sBuildCmd.clear(); + for ( ; itC != vArgs.end() ; itC++ ) + { + args.HOOK.sBuildCmd.append( *itC ); + args.HOOK.sBuildCmd.append( " " ); + args.HOOK.vBuildCmd.push_back( *itC ); + } + // Remove last space + if ( args.HOOK.vBuildCmd.size() > 1 ) + args.HOOK.sBuildCmd.erase( args.HOOK.sBuildCmd.size()-1 ); + + // Parse needed variables from sbs command. + vector::iterator itSbs; + for( itSbs = args.HOOK.vBuildCmd.begin(); itSbs != args.HOOK.vBuildCmd.end() ; itSbs++ ) + { + // Program(s). + if ( _stricmp( itSbs->c_str(), "-p" ) == 0 ) + { + // Next is program. + itSbs++; + args.HOOK.vTargetPrograms.push_back( *itSbs ); + } + else if ( itSbs->find( "--project=" ) != string::npos ) + { + itSbs->erase(0, 10 ); + args.HOOK.vTargetPrograms.push_back( *itSbs ); + } + // platform & build type ( configuration ) + else if ( _stricmp( itSbs->c_str(), "-c" ) == 0 || itSbs->find( "--config=" ) != string::npos ) + { + // Error message if config found more than once. + if ( bFoundConfig ) + { + cout << AT_MSG << "Error, no support defining more than one configuration." << endl; + bRet = false; + continue; + } + + if (_stricmp( itSbs->c_str(), "-c" ) == 0 ) + { + // Next is the configuration + itSbs++; + // Check that iterator is valid. + if ( itSbs == args.HOOK.vBuildCmd.end() ) + break; + } + else + { + // Remove the "--config=". + itSbs->erase( 0, 9 ); + // Check its not empty. + if ( itSbs->size() == 0 ) + break; + } + + // Identify configuration, if successful set sbs command as valid. + if ( parseSbsConfiguration( *itSbs, args ) ) + bRet = true; + // Set we encountered one configuration. + bFoundConfig = true; + } + } + // Error message if command is missing configuration. + if ( !bFoundConfig ) + cout << AT_MSG << "Error, missing configuration definition from sbs cmd." << endl; + } + else if ( _stricmp( it->c_str(), "abld" ) == 0 ) + { + bBuildFound = true; + // Use abld build system, pickup all rest argumenst as abld options. + args.HOOK.iBuildSystem = 1; + + vector::const_iterator itC = it; + args.HOOK.sBuildCmd.clear(); + for ( ; itC != vArgs.end() ; itC++ ) + { + args.HOOK.sBuildCmd.append( *itC ); + args.HOOK.sBuildCmd.append( " " ); + args.HOOK.vBuildCmd.push_back( *itC ); + } + + string sCmd( args.HOOK.sBuildCmd ); // build command to lower case here. + for( size_t i = 0 ; i < sCmd.size(); i++ ) + sCmd.at(i) = tolower( sCmd.at(i) ); + + // Remove all until platform + if ( sCmd.find("build ") != string::npos ) + { + // Check is test defined + if ( sCmd.substr(0, sCmd.find("build ")).find("test") != string::npos ) + args.HOOK.bAbldTest = true; + sCmd.erase( 0, sCmd.find("build")+6 ); + } + else + return false; + + //Is -debug switch in command? + if( sCmd.find( "-debug " ) != string::npos ) + { + sCmd.erase( sCmd.find( "-debug " ), 7 ); + } + + // Parse needed "variables" from command. + bool bOk = false; + + // Find platform + if ( sCmd.find( "armv5" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "armv5"; + sCmd.erase( sCmd.find( "armv5" ), 5 ); + } + else if ( sCmd.find( "winscw" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "winscw"; + sCmd.erase( sCmd.find( "winscw" ), 6 ); + } + else if ( sCmd.find( "gcce" ) != string::npos ) + { + bOk = true; + args.HOOK.sPlatform = "gcce"; + sCmd.erase( sCmd.find( "gcce" ), 4 ); + } + if ( bOk ) + { + // Feature variant. + if ( sCmd.at(0 ) == '.' ) + { + sCmd.erase(0,1); + args.HOOK.sFeatureVariant = sCmd.substr( 0, sCmd.find_first_of(' ') ); + sCmd.erase(0, sCmd.find_first_of(' ')+1 ); + } + } + else + { + // not platform specified. + cout << AT_MSG << "Error, no supported platform found in abld parameters (armv5/winscw/gcce)." << endl; + bRet = false; + } + + // find build type + bOk = false; + if ( sCmd.find( "urel" ) != string::npos ) + { + bOk = true; + args.HOOK.sBuildType = "urel"; + sCmd.erase( sCmd.find( "urel" ), 4 ); + } + + else if ( sCmd.find( "udeb" ) != string::npos ) + { + bOk = true; + args.HOOK.sBuildType = "udeb"; + sCmd.erase( sCmd.find( "udeb" ), 4 ); + } + if( !bOk ) + { + // no build type specified. + cout << AT_MSG << "Error, no build type specified in abld parameters (udeb/urel)." << endl; + bRet = false; + } + + // Is there multiple programs (only should be used from extension). + if ( sCmd.find(" -p") != string::npos ) + { + sCmd.erase( sCmd.find(" -p" ), sCmd.size() - sCmd.find(" -p" ) ); + // Loop thru all parameters and pick up programs. + vector::iterator it; + for( it = args.HOOK.vBuildCmd.begin(); it != args.HOOK.vBuildCmd.end(); it++ ) + { + if ( _stricmp( it->c_str(), "-p" ) == 0 ) + { + // Next is program. + it++; + string sProgram = *it; + // Make sure program name ends with ".mmp". + CATBase::ChangeToLower( sProgram ); + if ( sProgram.length() >= 4 ) + { + string sEnd = sProgram.substr( sProgram.length()-4, 4 ); + if ( sEnd.compare( ".mmp" ) != 0 ) + sProgram.append( ".mmp" ); + } + else + sProgram.append( ".mmp" ); + args.HOOK.vTargetPrograms.push_back( sProgram ); + } + } + } + else { + // find single defined program. + if ( sCmd.find_first_not_of(' ') != string::npos ) + { + size_t iS = sCmd.find_first_not_of(' '); + size_t iE = sCmd.find_first_of(' ', iS ); + string sProgram; + if ( iE == string::npos ) + sProgram = sCmd.substr( iS, sCmd.size()-iS ); + else + sProgram = sCmd.substr( iS, iE-iS); + // Make sure program name ends with ".mmp". + CATBase::ChangeToLower( sProgram ); + if ( sProgram.length() >= 4 ) + { + string sEnd = sProgram.substr( sProgram.length()-4, 4 ); + if ( sEnd.compare( ".mmp" ) != 0 ) + sProgram.append( ".mmp" ); + } + else + sProgram.append( ".mmp" ); + args.HOOK.vTargetPrograms.push_back( sProgram ); + } + } + } + else + { + if ( ! bBuildFound ) + { + bRet = false; + cout << AT_MSG << "Error, invalid parameter :" << *it << endl; + break; + } + } + } + } + catch(...) + { + bRet = false; + cout << AT_MSG << "Error parsing arguments." << endl; + } + return bRet; +} + + +/** +* Parse trace parsing related arguments from given vector of strings. +*/ +bool parseParseArguments( vector& vArgs, ARGUMENTS& args ) +{ + // Iterator used in this function. + vector::const_iterator it = vArgs.begin(); + + if ( it == vArgs.end() ) + return false; + + it++; + + if ( it == vArgs.end() ) + { + cout << AT_MSG << "Error, input file not defined (raw data file)." << endl; + return false; + } + + //Input. + args.PARSE.bDataFile = true; + args.PARSE.sDataFile = *it; + + it++; + if ( it == vArgs.end() ) + { + + cout << AT_MSG << "Error, output file not defined (device data file)." << endl; + return false; + } + + //Output. + args.PARSE.bOutputFile = true; + args.PARSE.sOutputFile = *it; + return true; +} + +/** +* Identifies/parses the configuration string when raptor used (-c / --config= ). +*/ +bool parseSbsConfiguration( string& sConfiguration, ARGUMENTS& args ) +{ + CATBase::ChangeToLower( sConfiguration ); + vector tokens = CATBase::ParseStringToVector( sConfiguration, '.' ); + + //we check if winscw/armv5 and udeb/urel is used + //rest of the "." are variants which we all support by default. + + //first we check if some of aliases is used + if ( tokens.at(0).compare("armv5_urel") == 0 ) + { + args.HOOK.sPlatform = "armv5"; + args.HOOK.sBuildType = "urel"; + return true; + } + else if ( tokens.at(0).compare("armv5_udeb") == 0 ) + { + args.HOOK.sPlatform = "armv5"; + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(0).compare("winscw_udeb") == 0) + { + args.HOOK.sPlatform = "winscw"; + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(0).compare("winscw_urel") == 0 ) + { + args.HOOK.sPlatform = "winscw"; + args.HOOK.sBuildType = "urel"; + return true; + } + //if 1st token is not an alias, lets try dot configurations + else if ( tokens.at(0).compare("arm") == 0 ) + { + // check we have atleast 3 tokens. i.e arm v5 debug x ... + if ( tokens.size() >= 3 ) + { + // Next configuration is arm version, we only support v5. + if ( tokens.at(1).compare( "v5" ) == 0) + { + args.HOOK.sPlatform = "armv5"; + + // Check next configuration part is debug or release + if ( tokens.at(2).compare( "udeb" ) == 0) + { + args.HOOK.sBuildType = "udeb"; + return true; + } + else if ( tokens.at(2).compare( "urel" ) == 0 ) + { + args.HOOK.sBuildType = "urel"; + return true; + } + else + { + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(2) << endl; + cout << AT_MSG << "Supported are: udeb,urel." << endl; + return false; + } + } + else + { + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(1) << endl; + cout << AT_MSG << "Supported are: v5." << endl; + return false; + } + } + } + + cout << AT_MSG << "Error in sbs configuration part: " << tokens.at(0) << endl; + cout << AT_MSG << "Supported are: arm, armv5_urel, armv5_udeb, winscw_udeb, winscw_urel." << endl; + return false; + +} + +//EOF