llvm-project/lldb/tools/lldb-mi/MICmdInterpreter.cpp

302 lines
9.1 KiB
C++

//===-- 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]<space>[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;
}