Made it so changes to the prompt via "settings set prompt" get noticed by the command line.
Added the ability for OptionValueString objects to take flags. The only flag is currently for parsing escape sequences. Not the prompt string can have escape characters translate which will allow colors in the prompt. Added functions to Args that will parse the escape sequences in a string, and also re-encode the escape sequences for display. This was looted from other parts of LLDB (the Debugger::FormatString() function). llvm-svn: 163043
This commit is contained in:
parent
c373ca5c74
commit
4c05410f8f
|
@ -262,6 +262,12 @@ public:
|
|||
eStopDisassemblyTypeAlways
|
||||
};
|
||||
|
||||
virtual Error
|
||||
SetPropertyValue (const ExecutionContext *exe_ctx,
|
||||
VarSetOperationType op,
|
||||
const char *property_path,
|
||||
const char *value);
|
||||
|
||||
bool
|
||||
GetAutoConfirm () const;
|
||||
|
||||
|
|
|
@ -411,6 +411,25 @@ public:
|
|||
static const char *
|
||||
GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg);
|
||||
|
||||
// EncodeEscapeSequences will change the textual representation of common
|
||||
// escape sequences like "\n" (two characters) into a single '\n'. It does
|
||||
// this for all of the supported escaped sequences and for the \0ooo (octal)
|
||||
// and \xXX (hex). The resulting "dst" string will contain the character
|
||||
// versions of all supported escape sequences. The common supported escape
|
||||
// sequences are: "\a", "\b", "\f", "\n", "\r", "\t", "\v", "\'", "\"", "\\".
|
||||
|
||||
static void
|
||||
EncodeEscapeSequences (const char *src, std::string &dst);
|
||||
|
||||
// ExpandEscapeSequences will change a string of possibly non-printable
|
||||
// characters and expand them into text. So '\n' will turn into two chracters
|
||||
// like "\n" which is suitable for human reading. When a character is not
|
||||
// printable and isn't one of the common in escape sequences listed in the
|
||||
// help for EncodeEscapeSequences, then it will be encoded as octal. Printable
|
||||
// characters are left alone.
|
||||
static void
|
||||
ExpandEscapedCharacters (const char *src, std::string &dst);
|
||||
|
||||
// This one isn't really relevant to Arguments per se, but we're using the Args as a
|
||||
// general strings container, so...
|
||||
void
|
||||
|
|
|
@ -210,7 +210,10 @@ public:
|
|||
|
||||
bool
|
||||
SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value);
|
||||
|
||||
|
||||
OptionValueString *
|
||||
GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const;
|
||||
|
||||
OptionValueFileSpec *
|
||||
GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Core/Flags.h"
|
||||
#include "lldb/Interpreter/OptionValue.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
@ -23,17 +24,24 @@ namespace lldb_private {
|
|||
class OptionValueString : public OptionValue
|
||||
{
|
||||
public:
|
||||
enum Options
|
||||
{
|
||||
eOptionEncodeCharacterEscapeSequences = (1u << 0)
|
||||
};
|
||||
|
||||
OptionValueString () :
|
||||
OptionValue(),
|
||||
m_current_value (),
|
||||
m_default_value ()
|
||||
m_default_value (),
|
||||
m_options()
|
||||
{
|
||||
}
|
||||
|
||||
OptionValueString (const char *value) :
|
||||
OptionValue(),
|
||||
m_current_value (),
|
||||
m_default_value ()
|
||||
m_default_value (),
|
||||
m_options()
|
||||
{
|
||||
if (value && value[0])
|
||||
{
|
||||
|
@ -46,7 +54,8 @@ public:
|
|||
const char *default_value) :
|
||||
OptionValue(),
|
||||
m_current_value (),
|
||||
m_default_value ()
|
||||
m_default_value (),
|
||||
m_options()
|
||||
{
|
||||
if (current_value && current_value[0])
|
||||
m_current_value.assign (current_value);
|
||||
|
@ -90,6 +99,18 @@ public:
|
|||
//---------------------------------------------------------------------
|
||||
// Subclass specific functions
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
Flags &
|
||||
GetOptions ()
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
const Flags &
|
||||
GetOptions () const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
const char *
|
||||
operator = (const char *value)
|
||||
|
@ -154,6 +175,7 @@ public:
|
|||
protected:
|
||||
std::string m_current_value;
|
||||
std::string m_default_value;
|
||||
Flags m_options;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -112,7 +112,7 @@ g_properties[] =
|
|||
{ "auto-confirm", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true all confirmation prompts will receive their default reply." },
|
||||
{ "frame-format", OptionValue::eTypeString , true, 0 , DEFAULT_FRAME_FORMAT, NULL, "The default frame format string to use when displaying stack frame information for threads." },
|
||||
{ "notify-void", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Notify the user explicitly if an expression returns void (default: false)." },
|
||||
{ "prompt", OptionValue::eTypeString , true, 0 , "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
|
||||
{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", NULL, "The debugger command line prompt displayed for the user." },
|
||||
{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, NULL, g_language_enumerators, "The script language to be used for evaluating user-written scripts." },
|
||||
{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , NULL, NULL, "The number of disassembly lines to show when displaying a stopped context." },
|
||||
{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoSource, NULL, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." },
|
||||
|
@ -152,6 +152,27 @@ enum
|
|||
// return m_properties_sp->GetThreadFormat();
|
||||
//}
|
||||
//
|
||||
|
||||
|
||||
Error
|
||||
Debugger::SetPropertyValue (const ExecutionContext *exe_ctx,
|
||||
VarSetOperationType op,
|
||||
const char *property_path,
|
||||
const char *value)
|
||||
{
|
||||
Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value));
|
||||
if (error.Success())
|
||||
{
|
||||
if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0)
|
||||
{
|
||||
const char *new_prompt = GetPrompt();
|
||||
EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));
|
||||
GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::GetAutoConfirm () const
|
||||
{
|
||||
|
|
|
@ -1528,3 +1528,137 @@ Args::ParseArgsForCompletion
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Args::EncodeEscapeSequences (const char *src, std::string &dst)
|
||||
{
|
||||
dst.clear();
|
||||
if (src)
|
||||
{
|
||||
for (const char *p = src; *p != '\0'; ++p)
|
||||
{
|
||||
size_t non_special_chars = ::strcspn (p, "\\");
|
||||
if (non_special_chars > 0)
|
||||
{
|
||||
dst.append(p, non_special_chars);
|
||||
p += non_special_chars;
|
||||
if (*p == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '\\')
|
||||
{
|
||||
++p; // skip the slash
|
||||
switch (*p)
|
||||
{
|
||||
case 'a' : dst.append(1, '\a'); break;
|
||||
case 'b' : dst.append(1, '\b'); break;
|
||||
case 'f' : dst.append(1, '\f'); break;
|
||||
case 'n' : dst.append(1, '\n'); break;
|
||||
case 'r' : dst.append(1, '\r'); break;
|
||||
case 't' : dst.append(1, '\t'); break;
|
||||
case 'v' : dst.append(1, '\v'); break;
|
||||
case '\\': dst.append(1, '\\'); break;
|
||||
case '\'': dst.append(1, '\''); break;
|
||||
case '"' : dst.append(1, '"'); break;
|
||||
case '0' :
|
||||
// 1 to 3 octal chars
|
||||
{
|
||||
// Make a string that can hold onto the initial zero char,
|
||||
// up to 3 octal digits, and a terminating NULL.
|
||||
char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
|
||||
|
||||
int i;
|
||||
for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
|
||||
oct_str[i] = p[i];
|
||||
|
||||
// We don't want to consume the last octal character since
|
||||
// the main for loop will do this for us, so we advance p by
|
||||
// one less than i (even if i is zero)
|
||||
p += i - 1;
|
||||
unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
|
||||
if (octal_value <= UINT8_MAX)
|
||||
{
|
||||
const char octal_char = octal_value;
|
||||
dst.append(1, octal_char);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
// hex number in the format
|
||||
if (isxdigit(p[1]))
|
||||
{
|
||||
++p; // Skip the 'x'
|
||||
|
||||
// Make a string that can hold onto two hex chars plus a
|
||||
// NULL terminator
|
||||
char hex_str[3] = { *p, '\0', '\0' };
|
||||
if (isxdigit(p[1]))
|
||||
{
|
||||
++p; // Skip the first of the two hex chars
|
||||
hex_str[1] = *p;
|
||||
}
|
||||
|
||||
unsigned long hex_value = strtoul (hex_str, NULL, 16);
|
||||
if (hex_value <= UINT8_MAX)
|
||||
dst.append (1, (char)hex_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.append(1, 'x');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Just desensitize any other character by just printing what
|
||||
// came after the '\'
|
||||
dst.append(1, *p);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Args::ExpandEscapedCharacters (const char *src, std::string &dst)
|
||||
{
|
||||
dst.clear();
|
||||
if (src)
|
||||
{
|
||||
for (const char *p = src; *p != '\0'; ++p)
|
||||
{
|
||||
if (isprint(*p))
|
||||
dst.append(1, *p);
|
||||
else
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '\a': dst.append("\\a"); break;
|
||||
case '\b': dst.append("\\b"); break;
|
||||
case '\f': dst.append("\\f"); break;
|
||||
case '\n': dst.append("\\n"); break;
|
||||
case '\r': dst.append("\\r"); break;
|
||||
case '\t': dst.append("\\t"); break;
|
||||
case '\v': dst.append("\\v"); break;
|
||||
case '\'': dst.append("\\'"); break;
|
||||
case '"': dst.append("\\\""); break;
|
||||
case '\\': dst.append("\\\\"); break;
|
||||
default:
|
||||
{
|
||||
// Just encode as octal
|
||||
dst.append("\\0");
|
||||
char octal_str[32];
|
||||
snprintf(octal_str, sizeof(octal_str), "%o", *p);
|
||||
dst.append(octal_str);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,11 +106,12 @@ CommandReturnObject::AppendWarningWithFormat (const char *format, ...)
|
|||
void
|
||||
CommandReturnObject::AppendMessage (const char *in_string, int len)
|
||||
{
|
||||
if (!in_string)
|
||||
if (!in_string || len == 0)
|
||||
return;
|
||||
if (len < 0)
|
||||
len = ::strlen (in_string);
|
||||
GetOutputStream().Printf("%*.*s\n", len, len, in_string);
|
||||
GetOutputStream().Printf("%s\n", in_string);
|
||||
else
|
||||
GetOutputStream().Printf("%*.*s\n", len, len, in_string);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -526,6 +526,16 @@ OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_c
|
|||
return false;
|
||||
}
|
||||
|
||||
OptionValueString *
|
||||
OptionValueProperties::GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
|
||||
{
|
||||
OptionValueSP value_sp(GetPropertyValueAtIndex (exe_ctx, will_modify, idx));
|
||||
if (value_sp)
|
||||
return value_sp->GetAsString();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
OptionValueProperties::GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
@ -29,10 +30,22 @@ OptionValueString::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uin
|
|||
strm.PutCString (" = ");
|
||||
if (!m_current_value.empty() || m_value_was_set)
|
||||
{
|
||||
if (dump_mask & eDumpOptionRaw)
|
||||
strm.Printf ("%s", m_current_value.c_str());
|
||||
if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
|
||||
{
|
||||
std::string expanded_escape_value;
|
||||
Args::ExpandEscapedCharacters(m_current_value.c_str(), expanded_escape_value);
|
||||
if (dump_mask & eDumpOptionRaw)
|
||||
strm.Printf ("%s", expanded_escape_value.c_str());
|
||||
else
|
||||
strm.Printf ("\"%s\"", expanded_escape_value.c_str());
|
||||
}
|
||||
else
|
||||
strm.Printf ("\"%s\"", m_current_value.c_str());
|
||||
{
|
||||
if (dump_mask & eDumpOptionRaw)
|
||||
strm.Printf ("%s", m_current_value.c_str());
|
||||
else
|
||||
strm.Printf ("\"%s\"", m_current_value.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +66,16 @@ OptionValueString::SetValueFromCString (const char *value_cstr,
|
|||
|
||||
case eVarSetOperationAppend:
|
||||
if (value_cstr && value_cstr[0])
|
||||
m_current_value += value_cstr;
|
||||
{
|
||||
if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
|
||||
{
|
||||
std::string str;
|
||||
Args::EncodeEscapeSequences (value_cstr, str);
|
||||
m_current_value += str;
|
||||
}
|
||||
else
|
||||
m_current_value += value_cstr;
|
||||
}
|
||||
break;
|
||||
|
||||
case eVarSetOperationClear:
|
||||
|
@ -63,7 +85,14 @@ OptionValueString::SetValueFromCString (const char *value_cstr,
|
|||
case eVarSetOperationReplace:
|
||||
case eVarSetOperationAssign:
|
||||
m_value_was_set = true;
|
||||
SetCurrentValue (value_cstr);
|
||||
if (m_options.Test (eOptionEncodeCharacterEscapeSequences))
|
||||
{
|
||||
Args::EncodeEscapeSequences (value_cstr, m_current_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCurrentValue (value_cstr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
|
|
|
@ -154,9 +154,14 @@ Property::Property (const PropertyDefinition &definition) :
|
|||
break;
|
||||
|
||||
case OptionValue::eTypeString:
|
||||
// "definition.default_uint_value" is not used for a OptionValueFileSpecList
|
||||
// "definition.default_uint_value" can contain the string option flags OR'ed together
|
||||
// "definition.default_cstr_value" can contain a default string value
|
||||
m_value_sp.reset (new OptionValueString(definition.default_cstr_value));
|
||||
{
|
||||
OptionValueString *string_value = new OptionValueString(definition.default_cstr_value);
|
||||
if (definition.default_uint_value != 0)
|
||||
string_value->GetOptions().Reset(definition.default_uint_value);
|
||||
m_value_sp.reset (string_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -376,11 +376,11 @@ ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback
|
|||
break;
|
||||
|
||||
case eInputReaderReactivate:
|
||||
{
|
||||
ScriptInterpreterPython::Locker locker(script_interpreter,
|
||||
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
|
||||
ScriptInterpreterPython::Locker::FreeAcquiredLock);
|
||||
}
|
||||
// {
|
||||
// ScriptInterpreterPython::Locker locker(script_interpreter,
|
||||
// ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
|
||||
// ScriptInterpreterPython::Locker::FreeAcquiredLock);
|
||||
// }
|
||||
break;
|
||||
|
||||
case eInputReaderAsynchronousOutputWritten:
|
||||
|
|
Loading…
Reference in New Issue