/*
* 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<string>& vArgs, ARGUMENTS& args );
bool parseHookArguments( vector<string>& vArgs, ARGUMENTS& args );
bool parseAnalyzeArguments( vector<string>& vArgs, ARGUMENTS& args );
bool parseParseArguments( vector<string>& 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<string>& vArgs, ARGUMENTS& args )
{
	// Iterator used in this function.
	vector<string>::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<string>& 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<string>::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<string>& vArgs, ARGUMENTS& args )
{
	bool bRet = true;
	try {
		// Iterator used in this function.
		vector<string>::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<string>::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<string>::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<string>::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<string>::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<string>& vArgs, ARGUMENTS& args )
{
	// Iterator used in this function.
	vector<string>::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<string> 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
