llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp
Greg Clayton 4c05410f8f 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
2012-09-01 00:38:36 +00:00

744 lines
23 KiB
C++

//===-- OptionValueProperties.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/OptionValueProperties.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Flags.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Interpreter/Property.h"
using namespace lldb;
using namespace lldb_private;
OptionValueProperties::OptionValueProperties (const ConstString &name) :
m_name (name)
{
}
OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) :
m_name (global_properties.m_name),
m_properties (global_properties.m_properties),
m_name_to_index (global_properties.m_name_to_index)
{
// We now have an exact copy of "global_properties". We need to now
// find all non-global settings and copy the property values so that
// all non-global settings get new OptionValue instances created for
// them.
const size_t num_properties = m_properties.size();
for (size_t i=0; i<num_properties; ++i)
{
// Duplicate any values that are not global when contructing properties from
// a global copy
if (m_properties[i].IsGlobal() == false)
{
lldb::OptionValueSP new_value_sp (m_properties[i].GetValue()->DeepCopy());
m_properties[i].SetOptionValue(new_value_sp);
}
}
}
size_t
OptionValueProperties::GetNumProperties() const
{
return m_properties.size();
}
void
OptionValueProperties::Initialize (const PropertyDefinition *defs)
{
for (size_t i=0; defs[i].name; ++i)
{
Property property(defs[i]);
assert(property.IsValid());
m_name_to_index.Append(property.GetName().GetCString(),m_properties.size());
property.GetValue()->SetParent(shared_from_this());
m_properties.push_back(property);
}
m_name_to_index.Sort();
}
void
OptionValueProperties::AppendProperty(const ConstString &name,
const ConstString &desc,
bool is_global,
const OptionValueSP &value_sp)
{
Property property(name, desc, is_global, value_sp);
m_name_to_index.Append(name.GetCString(),m_properties.size());
m_properties.push_back(property);
value_sp->SetParent (shared_from_this());
m_name_to_index.Sort();
}
//bool
//OptionValueProperties::GetQualifiedName (Stream &strm)
//{
// bool dumped_something = false;
//// lldb::OptionValuePropertiesSP parent_sp(GetParent ());
//// if (parent_sp)
//// {
//// parent_sp->GetQualifiedName (strm);
//// strm.PutChar('.');
//// dumped_something = true;
//// }
// if (m_name)
// {
// strm << m_name;
// dumped_something = true;
// }
// return dumped_something;
//}
//
lldb::OptionValueSP
OptionValueProperties::GetValueForKey (const ExecutionContext *exe_ctx,
const ConstString &key,
bool will_modify) const
{
lldb::OptionValueSP value_sp;
size_t idx = m_name_to_index.Find (key.GetCString(), SIZE_MAX);
if (idx < m_properties.size())
value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
return value_sp;
}
lldb::OptionValueSP
OptionValueProperties::GetSubValue (const ExecutionContext *exe_ctx,
const char *name,
bool will_modify,
Error &error) const
{
lldb::OptionValueSP value_sp;
if (name && name[0])
{
const char *sub_name = NULL;
ConstString key;
size_t key_len = ::strcspn (name, ".[{");
if (name[key_len])
{
key.SetCStringWithLength (name, key_len);
sub_name = name + key_len;
}
else
key.SetCString (name);
value_sp = GetValueForKey (exe_ctx, key, will_modify);
if (sub_name && value_sp)
{
switch (sub_name[0])
{
case '.':
return value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error);
case '{':
// Predicate matching for predicates like
// "<setting-name>{<predicate>}"
// strings are parsed by the current OptionValueProperties subclass
// to mean whatever they want to. For instance a subclass of
// OptionValueProperties for a lldb_private::Target might implement:
// "target.run-args{arch==i386}" -- only set run args if the arch is i386
// "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches
// "target.run-args{basename==test&&arch==x86_64}" -- only set run args if exectable basename is "test" and arch is "x86_64"
if (sub_name[1])
{
const char *predicate_start = sub_name + 1;
const char *predicate_end = strchr(predicate_start, '}');
if (predicate_end)
{
std::string predicate(predicate_start, predicate_end);
if (PredicateMatches(exe_ctx, predicate.c_str()))
{
if (predicate_end[1])
{
// Still more subvalue string to evaluate
return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error);
}
else
{
// We have a match!
break;
}
}
}
}
// Predicate didn't match or wasn't correctly formed
value_sp.reset();
break;
case '[':
// Array or dictionary access for subvalues like:
// "[12]" -- access 12th array element
// "['hello']" -- dictionary access of key named hello
return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
default:
value_sp.reset();
break;
}
}
}
return value_sp;
}
Error
OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx,
VarSetOperationType op,
const char *name,
const char *value)
{
Error error;
const bool will_modify = true;
lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
if (value_sp)
error = value_sp->SetValueFromCString(value, op);
else
{
if (error.AsCString() == NULL)
error.SetErrorStringWithFormat("invalid value path '%s'", name);
}
return error;
}
ConstString
OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const
{
const Property *property = GetPropertyAtIndex(NULL, false, idx);
if (property)
return property->GetName();
return ConstString();
}
const char *
OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const
{
const Property *property = GetPropertyAtIndex(NULL, false, idx);
if (property)
return property->GetDescription();
return NULL;
}
uint32_t
OptionValueProperties::GetPropertyIndex (const ConstString &name) const
{
return m_name_to_index.Find (name.GetCString(), SIZE_MAX);
}
const Property *
OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const
{
return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), SIZE_MAX));
}
const Property *
OptionValueProperties::GetPropertyAtIndex (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
{
return ProtectedGetPropertyAtIndex (idx);
}
lldb::OptionValueSP
OptionValueProperties::GetPropertyValueAtIndex (const ExecutionContext *exe_ctx,
bool will_modify,
uint32_t idx) const
{
const Property *setting = GetPropertyAtIndex (exe_ctx, will_modify, idx);
if (setting)
return setting->GetValue();
return OptionValueSP();
}
OptionValuePathMappings *
OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings (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->GetAsPathMappings();
return NULL;
}
OptionValueFileSpecList *
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList (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->GetAsFileSpecList();
return NULL;
}
OptionValueArch *
OptionValueProperties::GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
return property->GetValue()->GetAsArch();
return NULL;
}
bool
OptionValueProperties::GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
{
const OptionValueArray *array = value->GetAsArray();
if (array)
return array->GetArgs(args);
else
{
const OptionValueDictionary *dict = value->GetAsDictionary();
if (dict)
return dict->GetArgs(args);
}
}
}
return false;
}
bool
OptionValueProperties::SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
{
OptionValueArray *array = value->GetAsArray();
if (array)
return array->SetArgs(args, eVarSetOperationAssign).Success();
else
{
OptionValueDictionary *dict = value->GetAsDictionary();
if (dict)
return dict->SetArgs(args, eVarSetOperationAssign).Success();
}
}
}
return false;
}
bool
OptionValueProperties::GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetBooleanValue(fail_value);
}
return fail_value;
}
bool
OptionValueProperties::SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
{
value->SetBooleanValue(new_value);
return true;
}
}
return false;
}
OptionValueDictionary *
OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
return property->GetValue()->GetAsDictionary();
return NULL;
}
int64_t
OptionValueProperties::GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetEnumerationValue(fail_value);
}
return fail_value;
}
bool
OptionValueProperties::SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->SetEnumerationValue(new_value);
}
return false;
}
OptionValueFileSpec *
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetAsFileSpec();
}
return NULL;
}
FileSpec
OptionValueProperties::GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetFileSpecValue();
}
return FileSpec();
}
bool
OptionValueProperties::SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &new_file_spec)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->SetFileSpecValue(new_file_spec);
}
return false;
}
const RegularExpression *
OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetRegexValue();
}
return NULL;
}
OptionValueSInt64 *
OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetAsSInt64();
}
return NULL;
}
int64_t
OptionValueProperties::GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetSInt64Value(fail_value);
}
return fail_value;
}
bool
OptionValueProperties::SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->SetSInt64Value(new_value);
}
return false;
}
const char *
OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetStringValue(fail_value);
}
return fail_value;
}
bool
OptionValueProperties::SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->SetStringValue(new_value);
}
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
{
const Property *property = GetPropertyAtIndex (exe_ctx, false, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->GetUInt64Value(fail_value);
}
return fail_value;
}
bool
OptionValueProperties::SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value)
{
const Property *property = GetPropertyAtIndex (exe_ctx, true, idx);
if (property)
{
OptionValue *value = property->GetValue().get();
if (value)
return value->SetUInt64Value(new_value);
}
return false;
}
bool
OptionValueProperties::Clear ()
{
const size_t num_properties = m_properties.size();
for (size_t i=0; i<num_properties; ++i)
m_properties[i].GetValue()->Clear();
return true;
}
Error
OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationType op)
{
Error error;
// Args args(value_cstr);
// const size_t argc = args.GetArgumentCount();
switch (op)
{
case eVarSetOperationClear:
Clear ();
break;
case eVarSetOperationReplace:
case eVarSetOperationAssign:
case eVarSetOperationRemove:
case eVarSetOperationInsertBefore:
case eVarSetOperationInsertAfter:
case eVarSetOperationAppend:
case eVarSetOperationInvalid:
error = OptionValue::SetValueFromCString (value, op);
break;
}
return error;
}
void
OptionValueProperties::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
const size_t num_properties = m_properties.size();
for (size_t i=0; i<num_properties; ++i)
{
const Property *property = GetPropertyAtIndex(exe_ctx, false, i);
if (property)
{
OptionValue *option_value = property->GetValue().get();
assert (option_value);
const bool transparent_value = option_value->ValueIsTransparent ();
property->Dump (exe_ctx,
strm,
dump_mask);
if (!transparent_value)
strm.EOL();
}
}
}
Error
OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx,
Stream &strm,
const char *property_path,
uint32_t dump_mask)
{
Error error;
const bool will_modify = false;
lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, property_path, will_modify, error));
if (value_sp)
{
if (!value_sp->ValueIsTransparent ())
{
if (dump_mask & eDumpOptionName)
strm.PutCString (property_path);
if (dump_mask & ~eDumpOptionName)
strm.PutChar (' ');
}
value_sp->DumpValue (exe_ctx, strm, dump_mask);
}
return error;
}
lldb::OptionValueSP
OptionValueProperties::DeepCopy () const
{
assert(!"this shouldn't happen");
}
const Property *
OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx,
bool will_modify,
const char *name) const
{
const Property *property = NULL;
if (name && name[0])
{
const char *sub_name = NULL;
ConstString key;
size_t key_len = ::strcspn (name, ".[{");
if (name[key_len])
{
key.SetCStringWithLength (name, key_len);
sub_name = name + key_len;
}
else
key.SetCString (name);
property = GetProperty (exe_ctx, will_modify, key);
if (sub_name && property)
{
if (sub_name[0] == '.')
{
OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties();
if (sub_properties)
return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1);
}
property = NULL;
}
}
return property;
}
void
OptionValueProperties::DumpAllDescriptions (CommandInterpreter &interpreter,
Stream &strm) const
{
size_t max_name_len = 0;
const size_t num_properties = m_properties.size();
for (size_t i=0; i<num_properties; ++i)
{
const Property *property = ProtectedGetPropertyAtIndex(i);
if (property)
max_name_len = std::max<size_t>(property->GetName().GetLength(), max_name_len);
}
for (size_t i=0; i<num_properties; ++i)
{
const Property *property = ProtectedGetPropertyAtIndex(i);
if (property)
property->DumpDescription (interpreter, strm, max_name_len, false);
}
}
void
OptionValueProperties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const
{
const size_t num_properties = m_properties.size();
StreamString strm;
for (size_t i=0; i<num_properties; ++i)
{
const Property *property = ProtectedGetPropertyAtIndex(i);
if (property)
{
const OptionValueProperties *properties = property->GetValue()->GetAsProperties();
if (properties)
{
properties->Apropos (keyword, matching_properties);
}
else
{
bool match = false;
const char *name = property->GetName().GetCString();
if (name && ::strcasestr(name, keyword))
match = true;
else
{
const char *desc = property->GetDescription();
if (desc && ::strcasestr(desc, keyword))
match = true;
}
if (match)
{
matching_properties.push_back (property);
}
}
}
}
}