2011-06-24 01:59:56 +08:00
|
|
|
//===-- FormatManager.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/Core/FormatManager.h"
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
// Project includes
|
|
|
|
|
2011-07-15 10:26:42 +08:00
|
|
|
#include "lldb/Core/Debugger.h"
|
|
|
|
|
2011-06-24 01:59:56 +08:00
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
2011-06-24 05:22:24 +08:00
|
|
|
|
|
|
|
struct FormatInfo
|
|
|
|
{
|
|
|
|
Format format;
|
|
|
|
const char format_char; // One or more format characters that can be used for this format.
|
|
|
|
const char *format_name; // Long format name that can be used to specify the current format
|
|
|
|
};
|
|
|
|
|
|
|
|
static FormatInfo
|
|
|
|
g_format_infos[] =
|
|
|
|
{
|
|
|
|
{ eFormatDefault , '\0' , "default" },
|
|
|
|
{ eFormatBoolean , 'B' , "boolean" },
|
|
|
|
{ eFormatBinary , 'b' , "binary" },
|
|
|
|
{ eFormatBytes , 'y' , "bytes" },
|
|
|
|
{ eFormatBytesWithASCII , 'Y' , "bytes with ASCII" },
|
|
|
|
{ eFormatChar , 'c' , "character" },
|
|
|
|
{ eFormatCharPrintable , 'C' , "printable character" },
|
|
|
|
{ eFormatComplexFloat , 'F' , "complex float" },
|
|
|
|
{ eFormatCString , 's' , "c-string" },
|
|
|
|
{ eFormatDecimal , 'i' , "signed decimal" },
|
|
|
|
{ eFormatEnum , 'E' , "enumeration" },
|
|
|
|
{ eFormatHex , 'x' , "hex" },
|
|
|
|
{ eFormatFloat , 'f' , "float" },
|
|
|
|
{ eFormatOctal , 'o' , "octal" },
|
|
|
|
{ eFormatOSType , 'O' , "OSType" },
|
|
|
|
{ eFormatUnicode16 , 'U' , "unicode16" },
|
|
|
|
{ eFormatUnicode32 , '\0' , "unicode32" },
|
|
|
|
{ eFormatUnsigned , 'u' , "unsigned decimal" },
|
|
|
|
{ eFormatPointer , 'p' , "pointer" },
|
|
|
|
{ eFormatVectorOfChar , '\0' , "char[]" },
|
|
|
|
{ eFormatVectorOfSInt8 , '\0' , "int8_t[]" },
|
|
|
|
{ eFormatVectorOfUInt8 , '\0' , "uint8_t[]" },
|
|
|
|
{ eFormatVectorOfSInt16 , '\0' , "int16_t[]" },
|
|
|
|
{ eFormatVectorOfUInt16 , '\0' , "uint16_t[]" },
|
2011-07-06 23:56:06 +08:00
|
|
|
{ eFormatVectorOfSInt32 , '\0' , "int32_t[]" },
|
|
|
|
{ eFormatVectorOfUInt32 , '\0' , "uint32_t[]" },
|
|
|
|
{ eFormatVectorOfSInt64 , '\0' , "int64_t[]" },
|
|
|
|
{ eFormatVectorOfUInt64 , '\0' , "uint64_t[]" },
|
2011-06-24 05:22:24 +08:00
|
|
|
{ eFormatVectorOfFloat32, '\0' , "float32[]" },
|
|
|
|
{ eFormatVectorOfFloat64, '\0' , "float64[]" },
|
|
|
|
{ eFormatVectorOfUInt128, '\0' , "uint128_t[]" },
|
|
|
|
{ eFormatComplexInteger , 'I' , "complex integer" },
|
|
|
|
{ eFormatCharArray , 'a' , "character array" }
|
|
|
|
};
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
g_num_format_infos = sizeof(g_format_infos)/sizeof(FormatInfo);
|
|
|
|
|
|
|
|
static bool
|
|
|
|
GetFormatFromFormatChar (char format_char, Format &format)
|
|
|
|
{
|
|
|
|
for (uint32_t i=0; i<g_num_format_infos; ++i)
|
|
|
|
{
|
|
|
|
if (g_format_infos[i].format_char == format_char)
|
|
|
|
{
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
format = eFormatInvalid;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
GetFormatFromFormatName (const char *format_name, bool partial_match_ok, Format &format)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
for (i=0; i<g_num_format_infos; ++i)
|
|
|
|
{
|
|
|
|
if (strcasecmp (g_format_infos[i].format_name, format_name) == 0)
|
|
|
|
{
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (partial_match_ok)
|
|
|
|
{
|
|
|
|
for (i=0; i<g_num_format_infos; ++i)
|
|
|
|
{
|
|
|
|
if (strcasestr (g_format_infos[i].format_name, format_name) == g_format_infos[i].format_name)
|
|
|
|
{
|
|
|
|
format = g_format_infos[i].format;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
format = eFormatInvalid;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
FormatManager::GetFormatFromCString (const char *format_cstr,
|
|
|
|
bool partial_match_ok,
|
|
|
|
lldb::Format &format)
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
if (format_cstr && format_cstr[0])
|
|
|
|
{
|
|
|
|
if (format_cstr[1] == '\0')
|
|
|
|
{
|
|
|
|
success = GetFormatFromFormatChar (format_cstr[0], format);
|
|
|
|
if (success)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
success = GetFormatFromFormatName (format_cstr, partial_match_ok, format);
|
|
|
|
}
|
|
|
|
if (!success)
|
|
|
|
format = eFormatInvalid;
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
char
|
|
|
|
FormatManager::GetFormatAsFormatChar (lldb::Format format)
|
|
|
|
{
|
|
|
|
for (uint32_t i=0; i<g_num_format_infos; ++i)
|
|
|
|
{
|
|
|
|
if (g_format_infos[i].format == format)
|
|
|
|
return g_format_infos[i].format_char;
|
|
|
|
}
|
|
|
|
return '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
FormatManager::GetFormatAsCString (Format format)
|
|
|
|
{
|
|
|
|
if (format >= eFormatDefault && format < kNumFormats)
|
|
|
|
return g_format_infos[format].format_name;
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-07-02 08:25:22 +08:00
|
|
|
|
|
|
|
template<>
|
|
|
|
bool
|
2011-07-12 08:18:11 +08:00
|
|
|
FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Get(const char* key, SummaryFormat::SharedPointer& value)
|
2011-07-02 08:25:22 +08:00
|
|
|
{
|
2011-07-12 08:18:11 +08:00
|
|
|
Mutex::Locker(m_format_map.mutex());
|
|
|
|
MapIterator pos, end = m_format_map.map().end();
|
|
|
|
for (pos = m_format_map.map().begin(); pos != end; pos++)
|
2011-07-02 08:25:22 +08:00
|
|
|
{
|
|
|
|
lldb::RegularExpressionSP regex = pos->first;
|
|
|
|
if (regex->Execute(key))
|
|
|
|
{
|
|
|
|
value = pos->second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<>
|
|
|
|
bool
|
2011-07-12 08:18:11 +08:00
|
|
|
FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Delete(const char* type)
|
2011-07-02 08:25:22 +08:00
|
|
|
{
|
2011-07-12 08:18:11 +08:00
|
|
|
Mutex::Locker(m_format_map.mutex());
|
|
|
|
MapIterator pos, end = m_format_map.map().end();
|
|
|
|
for (pos = m_format_map.map().begin(); pos != end; pos++)
|
2011-07-02 08:25:22 +08:00
|
|
|
{
|
|
|
|
lldb::RegularExpressionSP regex = pos->first;
|
|
|
|
if ( ::strcmp(type,regex->GetText()) == 0)
|
|
|
|
{
|
2011-07-12 08:18:11 +08:00
|
|
|
m_format_map.map().erase(pos);
|
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
2011-07-20 02:03:25 +08:00
|
|
|
if (m_format_map.listener)
|
Fixed a bug where deleting a regex summary would not immediately reflect in the variables display
The "systemwide summaries" feature has been removed and replaced with a more general and
powerful mechanism.
Categories:
- summaries can now be grouped into buckets, called "categories" (it is expected that categories
correspond to libraries and/or runtime environments)
- to add a summary to a category, you can use the -w option to type summary add and give
a category name (e.g. type summary add -f "foo" foo_t -w foo_category)
- categories are by default disabled, which means LLDB will not look into them for summaries,
to enable a category use "type category enable". once a category is enabled, LLDB will
look into that category for summaries. the rules are quite trivial: every enabled category
is searched for an exact match. if an exact match is nowhere to be found, any match is
searched for in every enabled category (whether it involves cascading, going to base classes,
...). categories are searched into the order in which they were enabled (the most recently
enabled category first, then the second most and so on..)
- by default, most commands that deal with summaries, use a category named "default" if no
explicit -w parameter is given (the observable behavior of LLDB should not change when
categories are not explicitly used)
- the systemwide summaries are now part of a "system" category
llvm-svn: 135463
2011-07-19 10:34:21 +08:00
|
|
|
m_format_map.listener->Changed();
|
2011-07-02 08:25:22 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2011-07-13 06:56:10 +08:00
|
|
|
|
|
|
|
lldb::Format
|
|
|
|
FormatManager::GetSingleItemFormat(lldb::Format vector_format)
|
|
|
|
{
|
|
|
|
switch(vector_format)
|
|
|
|
{
|
|
|
|
case eFormatVectorOfChar:
|
|
|
|
return eFormatCharArray;
|
|
|
|
|
|
|
|
case eFormatVectorOfSInt8:
|
|
|
|
case eFormatVectorOfSInt16:
|
|
|
|
case eFormatVectorOfSInt32:
|
|
|
|
case eFormatVectorOfSInt64:
|
|
|
|
return eFormatDecimal;
|
|
|
|
|
|
|
|
case eFormatVectorOfUInt8:
|
|
|
|
case eFormatVectorOfUInt16:
|
|
|
|
case eFormatVectorOfUInt32:
|
|
|
|
case eFormatVectorOfUInt64:
|
|
|
|
case eFormatVectorOfUInt128:
|
|
|
|
return eFormatHex;
|
|
|
|
|
|
|
|
case eFormatVectorOfFloat32:
|
|
|
|
case eFormatVectorOfFloat64:
|
|
|
|
return eFormatFloat;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return lldb::eFormatInvalid;
|
|
|
|
}
|
The implementation of categories is now synchronization safe
Code cleanup:
- The Format Manager implementation is now split between two files: FormatClasses.{h|cpp} where the
actual formatter classes (ValueFormat, SummaryFormat, ...) are implemented and
FormatManager.{h|cpp} where the infrastructure classes (FormatNavigator, FormatManager, ...)
are contained. The wrapper code always remains in Debugger.{h|cpp}
- Several leftover fields, methods and comments from previous design choices have been removed
type category subcommands (enable, disable, delete) now can take a list of category names as input
- for type category enable, saying "enable A B C" is the same as saying
enable C
enable B
enable A
(the ordering is relevant in enabling categories, and it is expected that a user typing
enable A B C wants to look into category A, then into B, then into C and not the other
way round)
- for the other two commands, the order is not really relevant (however, the same inverted ordering
is used for consistency)
llvm-svn: 135494
2011-07-20 02:03:25 +08:00
|
|
|
}
|