2011-04-28 06:04:39 +08: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.
//
//===----------------------------------------------------------------------===//
2013-02-22 07:55:31 +08:00
# include "lldb/lldb-python.h"
2011-05-14 04:21:08 +08:00
# include "lldb/Interpreter/OptionGroupFormat.h"
2011-04-28 06:04:39 +08:00
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
2012-12-15 09:44:51 +08:00
# include "lldb/Core/ArchSpec.h"
# include "lldb/Interpreter/CommandInterpreter.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Target.h"
2011-09-10 08:48:33 +08:00
# include "lldb/Utility/Utils.h"
2011-04-28 06:04:39 +08:00
using namespace lldb ;
using namespace lldb_private ;
2011-10-25 14:44:01 +08:00
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 ) ,
2011-10-26 08:56:27 +08:00
m_count ( default_count , default_count ) ,
m_prev_gdb_format ( ' x ' ) ,
m_prev_gdb_size ( ' w ' )
2011-04-28 06:04:39 +08:00
{
}
OptionGroupFormat : : ~ OptionGroupFormat ( )
{
}
static OptionDefinition
g_option_table [ ] =
{
2014-07-10 00:31:49 +08: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. " } ,
2011-04-28 06:04:39 +08:00
} ;
uint32_t
OptionGroupFormat : : GetNumDefinitions ( )
{
2011-10-25 14:44:01 +08:00
if ( m_byte_size . GetDefaultValue ( ) < UINT64_MAX )
{
if ( m_count . GetDefaultValue ( ) < UINT64_MAX )
2011-10-26 08:56:27 +08:00
return 4 ;
2011-10-25 14:44:01 +08:00
else
2011-10-26 08:56:27 +08:00
return 3 ;
2011-10-25 14:44:01 +08:00
}
2011-10-26 08:56:27 +08:00
return 2 ;
2011-04-28 06:04:39 +08:00
}
const OptionDefinition *
OptionGroupFormat : : GetDefinitions ( )
{
return g_option_table ;
}
Error
OptionGroupFormat : : SetOptionValue ( CommandInterpreter & interpreter ,
2011-04-29 04:55:26 +08:00
uint32_t option_idx ,
const char * option_arg )
2011-04-28 06:04:39 +08:00
{
Error error ;
2012-12-04 08:32:51 +08:00
const int short_option = g_option_table [ option_idx ] . short_option ;
2011-04-28 06:04:39 +08:00
switch ( short_option )
{
case ' f ' :
error = m_format . SetValueFromCString ( option_arg ) ;
break ;
2011-10-25 14:44:01 +08:00
case ' c ' :
if ( m_count . GetDefaultValue ( ) = = 0 )
{
error . SetErrorString ( " --count option is disabled " ) ;
}
else
{
error = m_count . SetValueFromCString ( option_arg ) ;
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
{
error = m_byte_size . SetValueFromCString ( option_arg ) ;
if ( m_byte_size . GetCurrentValue ( ) = = 0 )
error . SetErrorStringWithFormat ( " invalid --size option value '%s' " , option_arg ) ;
}
break ;
2011-10-26 08:56:27 +08:00
case ' G ' :
{
2014-04-20 08:31:37 +08:00
char * end = nullptr ;
2011-10-26 08:56:27 +08: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 ;
}
2011-10-29 07:27:55 +08:00
Format format = eFormatDefault ;
uint32_t byte_size = 0 ;
2012-12-15 09:44:51 +08:00
while ( ParserGDBFormatLetter ( interpreter , gdb_format_cstr [ 0 ] , format , byte_size ) )
2011-10-29 07:27:55 +08:00
{
2011-10-26 08:56:27 +08:00
+ + gdb_format_cstr ;
2011-10-29 07:27:55 +08:00
}
2011-10-26 08:56:27 +08:00
// 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 )
2012-12-15 09:44:51 +08:00
ParserGDBFormatLetter ( interpreter , m_prev_gdb_format , format , byte_size ) ;
2011-10-26 08:56:27 +08:00
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 )
2012-12-15 09:44:51 +08:00
ParserGDBFormatLetter ( interpreter , m_prev_gdb_size , format , byte_size ) ;
2011-10-26 08:56:27 +08:00
}
else
{
// Byte size is disabled, make sure it wasn't specified
2013-10-12 06:09:26 +08: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 )
2011-10-26 08:56:27 +08:00
{
error . SetErrorString ( " this command doesn't support specifying a byte size " ) ;
return error ;
}
}
if ( count_enabled )
{
2012-08-24 05:16:25 +08:00
// Count is enabled and was not set, set it to the default for gdb format statements (which is 1).
2011-10-26 08:56:27 +08:00
if ( count = = 0 )
2012-08-24 05:16:25 +08:00
count = 1 ;
2011-10-26 08:56:27 +08:00
}
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 ;
2011-04-28 06:04:39 +08:00
default :
2011-10-26 08:56:27 +08:00
error . SetErrorStringWithFormat ( " unrecognized option '%c' " , short_option ) ;
2011-04-28 06:04:39 +08:00
break ;
}
return error ;
}
2011-10-29 07:27:55 +08:00
bool
2012-12-15 09:44:51 +08:00
OptionGroupFormat : : ParserGDBFormatLetter ( CommandInterpreter & interpreter , char format_letter , Format & format , uint32_t & byte_size )
2011-10-26 08:56:27 +08:00
{
2013-01-22 03:20:50 +08:00
m_has_gdb_format = true ;
2011-10-26 08:56:27 +08:00
switch ( format_letter )
{
2011-10-29 07:27:55 +08:00
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 ;
2012-12-15 09:44:51 +08:00
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 ;
}
2011-10-29 07:27:55 +08:00
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 ;
2011-10-26 08:56:27 +08:00
default : break ;
}
2011-10-29 07:27:55 +08:00
return false ;
2011-10-26 08:56:27 +08:00
}
2011-04-28 06:04:39 +08:00
void
OptionGroupFormat : : OptionParsingStarting ( CommandInterpreter & interpreter )
{
m_format . Clear ( ) ;
2011-10-25 14:44:01 +08:00
m_byte_size . Clear ( ) ;
m_count . Clear ( ) ;
2013-01-22 03:20:50 +08:00
m_has_gdb_format = false ;
2011-04-28 06:04:39 +08:00
}