11c3bbb01SEd Maste //===-- OptionValueFormatEntity.cpp -----------------------------*- C++ -*-===//
21c3bbb01SEd Maste //
31c3bbb01SEd Maste //                     The LLVM Compiler Infrastructure
41c3bbb01SEd Maste //
51c3bbb01SEd Maste // This file is distributed under the University of Illinois Open Source
61c3bbb01SEd Maste // License. See LICENSE.TXT for details.
71c3bbb01SEd Maste //
81c3bbb01SEd Maste //===----------------------------------------------------------------------===//
91c3bbb01SEd Maste 
101c3bbb01SEd Maste #include "lldb/Interpreter/OptionValueFormatEntity.h"
111c3bbb01SEd Maste 
121c3bbb01SEd Maste #include "lldb/Core/Module.h"
131c3bbb01SEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
14f678e45dSDimitry Andric #include "lldb/Utility/Stream.h"
15f678e45dSDimitry Andric #include "lldb/Utility/StringList.h"
161c3bbb01SEd Maste using namespace lldb;
171c3bbb01SEd Maste using namespace lldb_private;
181c3bbb01SEd Maste 
OptionValueFormatEntity(const char * default_format)19435933ddSDimitry Andric OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format)
20435933ddSDimitry Andric     : OptionValue(), m_current_format(), m_default_format(), m_current_entry(),
21435933ddSDimitry Andric       m_default_entry() {
22435933ddSDimitry Andric   if (default_format && default_format[0]) {
231c3bbb01SEd Maste     llvm::StringRef default_format_str(default_format);
245517e702SDimitry Andric     Status error = FormatEntity::Parse(default_format_str, m_default_entry);
25435933ddSDimitry Andric     if (error.Success()) {
261c3bbb01SEd Maste       m_default_format = default_format;
271c3bbb01SEd Maste       m_current_format = default_format;
281c3bbb01SEd Maste       m_current_entry = m_default_entry;
291c3bbb01SEd Maste     }
301c3bbb01SEd Maste   }
311c3bbb01SEd Maste }
321c3bbb01SEd Maste 
Clear()33435933ddSDimitry Andric bool OptionValueFormatEntity::Clear() {
341c3bbb01SEd Maste   m_current_entry = m_default_entry;
351c3bbb01SEd Maste   m_current_format = m_default_format;
361c3bbb01SEd Maste   m_value_was_set = false;
371c3bbb01SEd Maste   return true;
381c3bbb01SEd Maste }
391c3bbb01SEd Maste 
EscapeBackticks(llvm::StringRef str,std::string & dst)40*b5893f02SDimitry Andric static void EscapeBackticks(llvm::StringRef str, std::string &dst) {
41*b5893f02SDimitry Andric   dst.clear();
42*b5893f02SDimitry Andric   dst.reserve(str.size());
43*b5893f02SDimitry Andric 
44*b5893f02SDimitry Andric   for (size_t i = 0, e = str.size(); i != e; ++i) {
45*b5893f02SDimitry Andric     char c = str[i];
46*b5893f02SDimitry Andric     if (c == '`') {
47*b5893f02SDimitry Andric       if (i == 0 || str[i - 1] != '\\')
48*b5893f02SDimitry Andric         dst += '\\';
49*b5893f02SDimitry Andric     }
50*b5893f02SDimitry Andric     dst += c;
51*b5893f02SDimitry Andric   }
52*b5893f02SDimitry Andric }
53*b5893f02SDimitry Andric 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)54435933ddSDimitry Andric void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx,
55435933ddSDimitry Andric                                         Stream &strm, uint32_t dump_mask) {
561c3bbb01SEd Maste   if (dump_mask & eDumpOptionType)
571c3bbb01SEd Maste     strm.Printf("(%s)", GetTypeAsCString());
58435933ddSDimitry Andric   if (dump_mask & eDumpOptionValue) {
591c3bbb01SEd Maste     if (dump_mask & eDumpOptionType)
60*b5893f02SDimitry Andric       strm.PutCString(" = ");
61*b5893f02SDimitry Andric     std::string escaped;
62*b5893f02SDimitry Andric     EscapeBackticks(m_current_format, escaped);
63*b5893f02SDimitry Andric     strm << '"' << escaped << '"';
641c3bbb01SEd Maste   }
651c3bbb01SEd Maste }
661c3bbb01SEd Maste 
SetValueFromString(llvm::StringRef value_str,VarSetOperationType op)675517e702SDimitry Andric Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
68435933ddSDimitry Andric                                                    VarSetOperationType op) {
695517e702SDimitry Andric   Status error;
70435933ddSDimitry Andric   switch (op) {
711c3bbb01SEd Maste   case eVarSetOperationClear:
721c3bbb01SEd Maste     Clear();
731c3bbb01SEd Maste     NotifyValueChanged();
741c3bbb01SEd Maste     break;
751c3bbb01SEd Maste 
761c3bbb01SEd Maste   case eVarSetOperationReplace:
77435933ddSDimitry Andric   case eVarSetOperationAssign: {
78435933ddSDimitry Andric     // Check if the string starts with a quote character after removing leading
794ba319b5SDimitry Andric     // and trailing spaces. If it does start with a quote character, make sure
804ba319b5SDimitry Andric     // it ends with the same quote character and remove the quotes before we
814ba319b5SDimitry Andric     // parse the format string. If the string doesn't start with a quote, leave
824ba319b5SDimitry Andric     // the string alone and parse as is.
831c3bbb01SEd Maste     llvm::StringRef trimmed_value_str = value_str.trim();
84435933ddSDimitry Andric     if (!trimmed_value_str.empty()) {
851c3bbb01SEd Maste       const char first_char = trimmed_value_str[0];
86435933ddSDimitry Andric       if (first_char == '"' || first_char == '\'') {
871c3bbb01SEd Maste         const size_t trimmed_len = trimmed_value_str.size();
88435933ddSDimitry Andric         if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) {
891c3bbb01SEd Maste           error.SetErrorStringWithFormat("mismatched quotes");
901c3bbb01SEd Maste           return error;
911c3bbb01SEd Maste         }
921c3bbb01SEd Maste         value_str = trimmed_value_str.substr(1, trimmed_len - 2);
931c3bbb01SEd Maste       }
941c3bbb01SEd Maste     }
951c3bbb01SEd Maste     FormatEntity::Entry entry;
961c3bbb01SEd Maste     error = FormatEntity::Parse(value_str, entry);
97435933ddSDimitry Andric     if (error.Success()) {
981c3bbb01SEd Maste       m_current_entry = std::move(entry);
991c3bbb01SEd Maste       m_current_format = value_str;
1001c3bbb01SEd Maste       m_value_was_set = true;
1011c3bbb01SEd Maste       NotifyValueChanged();
1021c3bbb01SEd Maste     }
103435933ddSDimitry Andric   } break;
1041c3bbb01SEd Maste 
1051c3bbb01SEd Maste   case eVarSetOperationInsertBefore:
1061c3bbb01SEd Maste   case eVarSetOperationInsertAfter:
1071c3bbb01SEd Maste   case eVarSetOperationRemove:
1081c3bbb01SEd Maste   case eVarSetOperationAppend:
1091c3bbb01SEd Maste   case eVarSetOperationInvalid:
1101c3bbb01SEd Maste     error = OptionValue::SetValueFromString(value_str, op);
1111c3bbb01SEd Maste     break;
1121c3bbb01SEd Maste   }
1131c3bbb01SEd Maste   return error;
1141c3bbb01SEd Maste }
1151c3bbb01SEd Maste 
DeepCopy() const116435933ddSDimitry Andric lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const {
1171c3bbb01SEd Maste   return OptionValueSP(new OptionValueFormatEntity(*this));
1181c3bbb01SEd Maste }
1191c3bbb01SEd Maste 
AutoComplete(CommandInterpreter & interpreter,CompletionRequest & request)1204ba319b5SDimitry Andric size_t OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
1214ba319b5SDimitry Andric                                              CompletionRequest &request) {
1224ba319b5SDimitry Andric   return FormatEntity::AutoComplete(request);
1231c3bbb01SEd Maste }
124