1*0b57cec5SDimitry Andric //===-- OptionValueFormatEntity.cpp -----------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueFormatEntity.h" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include "lldb/Core/Module.h" 12*0b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 13*0b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 14*0b57cec5SDimitry Andric #include "lldb/Utility/StringList.h" 15*0b57cec5SDimitry Andric using namespace lldb; 16*0b57cec5SDimitry Andric using namespace lldb_private; 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) 19*0b57cec5SDimitry Andric : OptionValue(), m_current_format(), m_default_format(), m_current_entry(), 20*0b57cec5SDimitry Andric m_default_entry() { 21*0b57cec5SDimitry Andric if (default_format && default_format[0]) { 22*0b57cec5SDimitry Andric llvm::StringRef default_format_str(default_format); 23*0b57cec5SDimitry Andric Status error = FormatEntity::Parse(default_format_str, m_default_entry); 24*0b57cec5SDimitry Andric if (error.Success()) { 25*0b57cec5SDimitry Andric m_default_format = default_format; 26*0b57cec5SDimitry Andric m_current_format = default_format; 27*0b57cec5SDimitry Andric m_current_entry = m_default_entry; 28*0b57cec5SDimitry Andric } 29*0b57cec5SDimitry Andric } 30*0b57cec5SDimitry Andric } 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric bool OptionValueFormatEntity::Clear() { 33*0b57cec5SDimitry Andric m_current_entry = m_default_entry; 34*0b57cec5SDimitry Andric m_current_format = m_default_format; 35*0b57cec5SDimitry Andric m_value_was_set = false; 36*0b57cec5SDimitry Andric return true; 37*0b57cec5SDimitry Andric } 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric static void EscapeBackticks(llvm::StringRef str, std::string &dst) { 40*0b57cec5SDimitry Andric dst.clear(); 41*0b57cec5SDimitry Andric dst.reserve(str.size()); 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric for (size_t i = 0, e = str.size(); i != e; ++i) { 44*0b57cec5SDimitry Andric char c = str[i]; 45*0b57cec5SDimitry Andric if (c == '`') { 46*0b57cec5SDimitry Andric if (i == 0 || str[i - 1] != '\\') 47*0b57cec5SDimitry Andric dst += '\\'; 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric dst += c; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx, 54*0b57cec5SDimitry Andric Stream &strm, uint32_t dump_mask) { 55*0b57cec5SDimitry Andric if (dump_mask & eDumpOptionType) 56*0b57cec5SDimitry Andric strm.Printf("(%s)", GetTypeAsCString()); 57*0b57cec5SDimitry Andric if (dump_mask & eDumpOptionValue) { 58*0b57cec5SDimitry Andric if (dump_mask & eDumpOptionType) 59*0b57cec5SDimitry Andric strm.PutCString(" = "); 60*0b57cec5SDimitry Andric std::string escaped; 61*0b57cec5SDimitry Andric EscapeBackticks(m_current_format, escaped); 62*0b57cec5SDimitry Andric strm << '"' << escaped << '"'; 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric } 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, 67*0b57cec5SDimitry Andric VarSetOperationType op) { 68*0b57cec5SDimitry Andric Status error; 69*0b57cec5SDimitry Andric switch (op) { 70*0b57cec5SDimitry Andric case eVarSetOperationClear: 71*0b57cec5SDimitry Andric Clear(); 72*0b57cec5SDimitry Andric NotifyValueChanged(); 73*0b57cec5SDimitry Andric break; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric case eVarSetOperationReplace: 76*0b57cec5SDimitry Andric case eVarSetOperationAssign: { 77*0b57cec5SDimitry Andric // Check if the string starts with a quote character after removing leading 78*0b57cec5SDimitry Andric // and trailing spaces. If it does start with a quote character, make sure 79*0b57cec5SDimitry Andric // it ends with the same quote character and remove the quotes before we 80*0b57cec5SDimitry Andric // parse the format string. If the string doesn't start with a quote, leave 81*0b57cec5SDimitry Andric // the string alone and parse as is. 82*0b57cec5SDimitry Andric llvm::StringRef trimmed_value_str = value_str.trim(); 83*0b57cec5SDimitry Andric if (!trimmed_value_str.empty()) { 84*0b57cec5SDimitry Andric const char first_char = trimmed_value_str[0]; 85*0b57cec5SDimitry Andric if (first_char == '"' || first_char == '\'') { 86*0b57cec5SDimitry Andric const size_t trimmed_len = trimmed_value_str.size(); 87*0b57cec5SDimitry Andric if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) { 88*0b57cec5SDimitry Andric error.SetErrorStringWithFormat("mismatched quotes"); 89*0b57cec5SDimitry Andric return error; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric value_str = trimmed_value_str.substr(1, trimmed_len - 2); 92*0b57cec5SDimitry Andric } 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric FormatEntity::Entry entry; 95*0b57cec5SDimitry Andric error = FormatEntity::Parse(value_str, entry); 96*0b57cec5SDimitry Andric if (error.Success()) { 97*0b57cec5SDimitry Andric m_current_entry = std::move(entry); 98*0b57cec5SDimitry Andric m_current_format = value_str; 99*0b57cec5SDimitry Andric m_value_was_set = true; 100*0b57cec5SDimitry Andric NotifyValueChanged(); 101*0b57cec5SDimitry Andric } 102*0b57cec5SDimitry Andric } break; 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric case eVarSetOperationInsertBefore: 105*0b57cec5SDimitry Andric case eVarSetOperationInsertAfter: 106*0b57cec5SDimitry Andric case eVarSetOperationRemove: 107*0b57cec5SDimitry Andric case eVarSetOperationAppend: 108*0b57cec5SDimitry Andric case eVarSetOperationInvalid: 109*0b57cec5SDimitry Andric error = OptionValue::SetValueFromString(value_str, op); 110*0b57cec5SDimitry Andric break; 111*0b57cec5SDimitry Andric } 112*0b57cec5SDimitry Andric return error; 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const { 116*0b57cec5SDimitry Andric return OptionValueSP(new OptionValueFormatEntity(*this)); 117*0b57cec5SDimitry Andric } 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric size_t OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, 120*0b57cec5SDimitry Andric CompletionRequest &request) { 121*0b57cec5SDimitry Andric return FormatEntity::AutoComplete(request); 122*0b57cec5SDimitry Andric } 123