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).
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@163043 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp
index 63bcb87..bb9ed8d 100644
--- a/source/Interpreter/Args.cpp
+++ b/source/Interpreter/Args.cpp
@@ -1528,3 +1528,137 @@
}
}
+
+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;
+ }
+ }
+ }
+ }
+}
+
diff --git a/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp
index ddb783b..896ad2b 100644
--- a/source/Interpreter/CommandReturnObject.cpp
+++ b/source/Interpreter/CommandReturnObject.cpp
@@ -106,11 +106,12 @@
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
diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp
index 304ce62..607a932 100644
--- a/source/Interpreter/OptionValueProperties.cpp
+++ b/source/Interpreter/OptionValueProperties.cpp
@@ -526,6 +526,16 @@
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
{
diff --git a/source/Interpreter/OptionValueString.cpp b/source/Interpreter/OptionValueString.cpp
index 35ab8c8..696e62b 100644
--- a/source/Interpreter/OptionValueString.cpp
+++ b/source/Interpreter/OptionValueString.cpp
@@ -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 @@
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 @@
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 @@
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;
diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp
index 7e7dc01..d2bf1e1 100644
--- a/source/Interpreter/Property.cpp
+++ b/source/Interpreter/Property.cpp
@@ -154,9 +154,14 @@
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;
}
}
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 97cf7f8..fec70e3 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -376,11 +376,11 @@
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: