2013-08-23 13:46:38 -04:00
//===-- OptionGroupFormat.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/Interpreter/OptionGroupFormat.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
# include "lldb/Core/ArchSpec.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Target.h"
# include "lldb/Utility/Utils.h"
using namespace lldb ;
using namespace lldb_private ;
OptionGroupFormat : : OptionGroupFormat ( lldb : : Format default_format ,
uint64_t default_byte_size ,
uint64_t default_count ) :
m_format ( default_format , default_format ) ,
m_byte_size ( default_byte_size , default_byte_size ) ,
m_count ( default_count , default_count ) ,
m_prev_gdb_format ( ' x ' ) ,
m_prev_gdb_size ( ' w ' )
{
}
OptionGroupFormat : : ~ OptionGroupFormat ( )
{
}
static OptionDefinition
g_option_table [ ] =
{
2014-11-25 16:00:58 -05:00
{ LLDB_OPT_SET_1 , false , " format " , ' f ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeFormat , " Specify a format to be used for display. " } ,
{ LLDB_OPT_SET_2 , false , " gdb-format " , ' G ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeGDBFormat , " Specify a format using a GDB format specifier string. " } ,
{ LLDB_OPT_SET_3 , false , " size " , ' s ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeByteSize , " The size in bytes to use when displaying with the selected format. " } ,
{ LLDB_OPT_SET_4 , false , " count " , ' c ' , OptionParser : : eRequiredArgument , nullptr , nullptr , 0 , eArgTypeCount , " The number of total items to display. " } ,
2013-08-23 13:46:38 -04:00
} ;
uint32_t
OptionGroupFormat : : GetNumDefinitions ( )
{
if ( m_byte_size . GetDefaultValue ( ) < UINT64_MAX )
{
if ( m_count . GetDefaultValue ( ) < UINT64_MAX )
return 4 ;
else
return 3 ;
}
return 2 ;
}
const OptionDefinition *
OptionGroupFormat : : GetDefinitions ( )
{
return g_option_table ;
}
Error
OptionGroupFormat : : SetOptionValue ( CommandInterpreter & interpreter ,
uint32_t option_idx ,
const char * option_arg )
{
Error error ;
const int short_option = g_option_table [ option_idx ] . short_option ;
switch ( short_option )
{
case ' f ' :
2015-07-03 12:57:06 -04:00
error = m_format . SetValueFromString ( option_arg ) ;
2013-08-23 13:46:38 -04:00
break ;
case ' c ' :
if ( m_count . GetDefaultValue ( ) = = 0 )
{
error . SetErrorString ( " --count option is disabled " ) ;
}
else
{
2015-07-03 12:57:06 -04:00
error = m_count . SetValueFromString ( option_arg ) ;
2013-08-23 13:46:38 -04:00
if ( m_count . GetCurrentValue ( ) = = 0 )
error . SetErrorStringWithFormat ( " invalid --count option value '%s' " , option_arg ) ;
}
break ;
case ' s ' :
if ( m_byte_size . GetDefaultValue ( ) = = 0 )
{
error . SetErrorString ( " --size option is disabled " ) ;
}
else
{
2015-07-03 12:57:06 -04:00
error = m_byte_size . SetValueFromString ( option_arg ) ;
2013-08-23 13:46:38 -04:00
if ( m_byte_size . GetCurrentValue ( ) = = 0 )
error . SetErrorStringWithFormat ( " invalid --size option value '%s' " , option_arg ) ;
}
break ;
case ' G ' :
{
2014-11-25 16:00:58 -05:00
char * end = nullptr ;
2013-08-23 13:46:38 -04:00
const char * gdb_format_cstr = option_arg ;
uint64_t count = 0 ;
if ( : : isdigit ( gdb_format_cstr [ 0 ] ) )
{
count = strtoull ( gdb_format_cstr , & end , 0 ) ;
if ( option_arg ! = end )
gdb_format_cstr = end ; // We have a valid count, advance the string position
else
count = 0 ;
}
Format format = eFormatDefault ;
uint32_t byte_size = 0 ;
while ( ParserGDBFormatLetter ( interpreter , gdb_format_cstr [ 0 ] , format , byte_size ) )
{
+ + gdb_format_cstr ;
}
// We the first character of the "gdb_format_cstr" is not the
// NULL terminator, we didn't consume the entire string and
// something is wrong. Also, if none of the format, size or count
// was specified correctly, then abort.
if ( gdb_format_cstr [ 0 ] | | ( format = = eFormatInvalid & & byte_size = = 0 & & count = = 0 ) )
{
// Nothing got set correctly
error . SetErrorStringWithFormat ( " invalid gdb format string '%s' " , option_arg ) ;
return error ;
}
// At least one of the format, size or count was set correctly.
// Anything that wasn't set correctly should be set to the
// previous default
if ( format = = eFormatInvalid )
ParserGDBFormatLetter ( interpreter , m_prev_gdb_format , format , byte_size ) ;
const bool byte_size_enabled = m_byte_size . GetDefaultValue ( ) < UINT64_MAX ;
const bool count_enabled = m_count . GetDefaultValue ( ) < UINT64_MAX ;
if ( byte_size_enabled )
{
// Byte size is enabled
if ( byte_size = = 0 )
ParserGDBFormatLetter ( interpreter , m_prev_gdb_size , format , byte_size ) ;
}
else
{
// Byte size is disabled, make sure it wasn't specified
2013-11-06 11:48:53 -05:00
// but if this is an address, it's actually necessary to
// specify one so don't error out
if ( byte_size > 0 & & format ! = lldb : : eFormatAddressInfo )
2013-08-23 13:46:38 -04:00
{
error . SetErrorString ( " this command doesn't support specifying a byte size " ) ;
return error ;
}
}
if ( count_enabled )
{
// Count is enabled and was not set, set it to the default for gdb format statements (which is 1).
if ( count = = 0 )
count = 1 ;
}
else
{
// Count is disabled, make sure it wasn't specified
if ( count > 0 )
{
error . SetErrorString ( " this command doesn't support specifying a count " ) ;
return error ;
}
}
m_format . SetCurrentValue ( format ) ;
m_format . SetOptionWasSet ( ) ;
if ( byte_size_enabled )
{
m_byte_size . SetCurrentValue ( byte_size ) ;
m_byte_size . SetOptionWasSet ( ) ;
}
if ( count_enabled )
{
m_count . SetCurrentValue ( count ) ;
m_count . SetOptionWasSet ( ) ;
}
}
break ;
default :
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
break ;
}
return error ;
}
bool
OptionGroupFormat : : ParserGDBFormatLetter ( CommandInterpreter & interpreter , char format_letter , Format & format , uint32_t & byte_size )
{
m_has_gdb_format = true ;
switch ( format_letter )
{
case ' o ' : format = eFormatOctal ; m_prev_gdb_format = format_letter ; return true ;
case ' x ' : format = eFormatHex ; m_prev_gdb_format = format_letter ; return true ;
case ' d ' : format = eFormatDecimal ; m_prev_gdb_format = format_letter ; return true ;
case ' u ' : format = eFormatUnsigned ; m_prev_gdb_format = format_letter ; return true ;
case ' t ' : format = eFormatBinary ; m_prev_gdb_format = format_letter ; return true ;
case ' f ' : format = eFormatFloat ; m_prev_gdb_format = format_letter ; return true ;
case ' a ' : format = eFormatAddressInfo ;
{
ExecutionContext exe_ctx ( interpreter . GetExecutionContext ( ) ) ;
Target * target = exe_ctx . GetTargetPtr ( ) ;
if ( target )
byte_size = target - > GetArchitecture ( ) . GetAddressByteSize ( ) ;
m_prev_gdb_format = format_letter ;
return true ;
}
case ' i ' : format = eFormatInstruction ; m_prev_gdb_format = format_letter ; return true ;
case ' c ' : format = eFormatChar ; m_prev_gdb_format = format_letter ; return true ;
case ' s ' : format = eFormatCString ; m_prev_gdb_format = format_letter ; return true ;
case ' T ' : format = eFormatOSType ; m_prev_gdb_format = format_letter ; return true ;
case ' A ' : format = eFormatHexFloat ; m_prev_gdb_format = format_letter ; return true ;
case ' b ' : byte_size = 1 ; m_prev_gdb_size = format_letter ; return true ;
case ' h ' : byte_size = 2 ; m_prev_gdb_size = format_letter ; return true ;
case ' w ' : byte_size = 4 ; m_prev_gdb_size = format_letter ; return true ;
case ' g ' : byte_size = 8 ; m_prev_gdb_size = format_letter ; return true ;
default : break ;
}
return false ;
}
void
OptionGroupFormat : : OptionParsingStarting ( CommandInterpreter & interpreter )
{
m_format . Clear ( ) ;
m_byte_size . Clear ( ) ;
m_count . Clear ( ) ;
m_has_gdb_format = false ;
}