//===-- MICmdInterpreter.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MICmdInterpreter.cpp // // Overview: CMICmdInterpreter implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 // Libraries: See MIReadmetxt. // // Copyright: None. //-- // In-house headers: #include "MICmdInterpreter.h" #include "MICmdFactory.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmdInterpreter constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdInterpreter::CMICmdInterpreter( void ) : m_rCmdFactory( CMICmdFactory::Instance() ) { } //++ ------------------------------------------------------------------------------------ // Details: CMICmdInterpreter destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- CMICmdInterpreter::~CMICmdInterpreter( void ) { Shutdown(); } //++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Command Interpreter. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdInterpreter::Initialize( void ) { m_clientUsageRefCnt++; if( m_bInitialized ) return MIstatus::success; m_bInitialized = true; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Release resources for *this Command Interpreter. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdInterpreter::Shutdown( void ) { if( --m_clientUsageRefCnt > 0 ) return MIstatus::success; if( !m_bInitialized ) return MIstatus::success; m_bInitialized = false; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Establish whether the text data is an MI format type command. // Type: Method. // Args: vTextLine - (R) Text data to interpret. // vwbYesValid - (W) True = MI type command, false = not recognised. // vwbCmdNotInCmdFactor - (W) True = MI command not found in the command factory, false = recognised. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdInterpreter::ValidateIsMi( const CMIUtilString & vTextLine, bool & vwbYesValid, bool & vwbCmdNotInCmdFactor, SMICmdData & rwCmdData ) { vwbYesValid = false; vwbCmdNotInCmdFactor = false; rwCmdData.Clear(); if( vTextLine.empty() ) return MIstatus::success; // MI format is [cmd #]-[command name][command arg(s)] // i.e. 1-file-exec-and-symbols --thread-group i1 DEVICE_EXECUTABLE // 5-data-evaluate-expression --thread 1 --frame 0 *(argv) m_miCmdData.Clear(); m_miCmdData.strMiCmd = vTextLine; // The following change m_miCmdData as valid parts are indentified vwbYesValid = (MiHasCmdTokenEndingHypthen( vTextLine ) || MiHasCmdTokenEndingAlpha( vTextLine )); vwbYesValid = vwbYesValid && MiHasCmd( vTextLine ); if( vwbYesValid ) { vwbCmdNotInCmdFactor = !HasCmdFactoryGotMiCmd( MiGetCmdData() ); vwbYesValid = !vwbCmdNotInCmdFactor; } // Update command's meta data valid state m_miCmdData.bCmdValid = vwbYesValid; // Ok to return new updated command information rwCmdData = MiGetCmdData(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Establish whether the command name entered on the stdin stream is recognised by // the MI driver. // Type: Method. // Args: vCmd - (R) Command information structure. // Return: bool - True = yes command is recognised, false = command not recognised. // Throws: None. //-- bool CMICmdInterpreter::HasCmdFactoryGotMiCmd( const SMICmdData & vCmd ) const { return m_rCmdFactory.CmdExist( vCmd.strMiCmd ); } //++ ------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. // The format to validate against is 'nn-' where there can be 1 to n digits. // I.e. '2-gdb-exit'. // Is the execution token present? The command token is entered into the // command meta data structure whether correct or not for reporting or later // command execution purposes. // Type: Method. // Args: vTextLine - (R) Text data to interpret. // Return: bool - True = yes command token present, false = command not recognised. // Throws: None. //-- bool CMICmdInterpreter::MiHasCmdTokenEndingHypthen( const CMIUtilString & vTextLine ) { // The hythen is mandatory const MIint nPos = vTextLine.find( "-", 0 ); if( (nPos == (MIint) std::string::npos) ) return false; if( MiHasCmdTokenPresent( vTextLine ) ) { const std::string strNum = vTextLine.substr( 0, nPos ); if( !CMIUtilString( strNum.c_str() ).IsNumber() ) return false; m_miCmdData.strMiCmdToken = strNum.c_str(); } m_miCmdData.bMIOldStyle = false; return true; } //++ ------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. // The format to validate against is 'nnA' where there can be 1 to n digits. // 'A' represents any non numeric token. I.e. '1source .gdbinit'. // Is the execution token present? The command token is entered into the // command meta data structure whether correct or not for reporting or later // command execution purposes. // Type: Method. // Args: vTextLine - (R) Text data to interpret. // Return: bool - True = yes command token present, false = command not recognised. // Throws: None. //-- bool CMICmdInterpreter::MiHasCmdTokenEndingAlpha( const CMIUtilString & vTextLine ) { MIchar cChar = vTextLine[ 0 ]; MIuint i = 0; while( ::isdigit( cChar ) != 0 ) { cChar = vTextLine[ ++i ]; } if( ::isalpha( cChar ) == 0 ) return false; if( i == 0 ) return false; const std::string strNum = vTextLine.substr( 0, i ); m_miCmdData.strMiCmdToken = strNum.c_str(); m_miCmdData.bMIOldStyle = true; return true; } //++ ------------------------------------------------------------------------------------ // Details: Does the command entered match the criteria for a MI command format. // Is the command token present before the hypen? // Type: Method. // Args: vTextLine - (R) Text data to interpret. // Return: bool - True = yes command token present, false = token not present. // Throws: None. //-- bool CMICmdInterpreter::MiHasCmdTokenPresent( const CMIUtilString & vTextLine ) { const MIint nPos = vTextLine.find( "-", 0 ); return (nPos > 0); } //++ ------------------------------------------------------------------------------------ // Details: Does the command name entered match the criteria for a MI command format. // Is a recogised command present? The command name is entered into the // command meta data structure whether correct or not for reporting or later // command execution purposes. Command options is present are also put into the // command meta data structure. // Type: Method. // Args: vTextLine - (R) Command information structure. // Return: bool - True = yes command name present, false = command not recognised. // Throws: None. //-- bool CMICmdInterpreter::MiHasCmd( const CMIUtilString & vTextLine ) { MIint nPos = 0; if( m_miCmdData.bMIOldStyle ) { char cChar = vTextLine[ 0 ]; MIuint i = 0; while( ::isdigit( cChar ) != 0 ) { cChar = vTextLine[ ++i ]; } nPos = --i; } else { nPos = vTextLine.find( "-", 0 ); } bool bFoundCmd = false; const MIint nLen = vTextLine.length(); const MIint nPos2 = vTextLine.find( " ", nPos ); if( nPos2 != (MIint) std::string::npos ) { if( nPos2 == nLen ) return false; const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nPos2 - nPos - 1 ).c_str() ); if( cmd.empty() ) return false; m_miCmdData.strMiCmd = cmd; if( nPos2 < nLen ) m_miCmdData.strMiCmdOption = CMIUtilString( vTextLine.substr( nPos2 + 1, nLen - nPos2 - 1 ).c_str() ); bFoundCmd = true; } else { const CMIUtilString cmd = CMIUtilString( vTextLine.substr( nPos + 1, nLen - nPos - 1 ).c_str() ); if( cmd.empty() ) return false; m_miCmdData.strMiCmd = cmd; bFoundCmd = true; } if( bFoundCmd ) m_miCmdData.strMiCmdAll = vTextLine; return bFoundCmd; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve the just entered new command from stdin. It contains the command // name, number and any options. // Type: Method. // Args: vTextLine - (R) Command information structure. // Return: SMICmdData & - Command meta data information/result/status. // Throws: None. //-- const SMICmdData & CMICmdInterpreter::MiGetCmdData( void ) const { return m_miCmdData; }