15ffd83dbSDimitry Andric //===-- OptionValueFormatEntity.cpp ---------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueFormatEntity.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Module.h" 120b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h" 130b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 140b57cec5SDimitry Andric #include "lldb/Utility/StringList.h" 150b57cec5SDimitry Andric using namespace lldb; 160b57cec5SDimitry Andric using namespace lldb_private; 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) 190b57cec5SDimitry Andric : OptionValue(), m_current_format(), m_default_format(), m_current_entry(), 200b57cec5SDimitry Andric m_default_entry() { 210b57cec5SDimitry Andric if (default_format && default_format[0]) { 220b57cec5SDimitry Andric llvm::StringRef default_format_str(default_format); 230b57cec5SDimitry Andric Status error = FormatEntity::Parse(default_format_str, m_default_entry); 240b57cec5SDimitry Andric if (error.Success()) { 250b57cec5SDimitry Andric m_default_format = default_format; 260b57cec5SDimitry Andric m_current_format = default_format; 270b57cec5SDimitry Andric m_current_entry = m_default_entry; 280b57cec5SDimitry Andric } 290b57cec5SDimitry Andric } 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 32*e8d8bef9SDimitry Andric void OptionValueFormatEntity::Clear() { 330b57cec5SDimitry Andric m_current_entry = m_default_entry; 340b57cec5SDimitry Andric m_current_format = m_default_format; 350b57cec5SDimitry Andric m_value_was_set = false; 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric static void EscapeBackticks(llvm::StringRef str, std::string &dst) { 390b57cec5SDimitry Andric dst.clear(); 400b57cec5SDimitry Andric dst.reserve(str.size()); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric for (size_t i = 0, e = str.size(); i != e; ++i) { 430b57cec5SDimitry Andric char c = str[i]; 440b57cec5SDimitry Andric if (c == '`') { 450b57cec5SDimitry Andric if (i == 0 || str[i - 1] != '\\') 460b57cec5SDimitry Andric dst += '\\'; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric dst += c; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx, 530b57cec5SDimitry Andric Stream &strm, uint32_t dump_mask) { 540b57cec5SDimitry Andric if (dump_mask & eDumpOptionType) 550b57cec5SDimitry Andric strm.Printf("(%s)", GetTypeAsCString()); 560b57cec5SDimitry Andric if (dump_mask & eDumpOptionValue) { 570b57cec5SDimitry Andric if (dump_mask & eDumpOptionType) 580b57cec5SDimitry Andric strm.PutCString(" = "); 590b57cec5SDimitry Andric std::string escaped; 600b57cec5SDimitry Andric EscapeBackticks(m_current_format, escaped); 610b57cec5SDimitry Andric strm << '"' << escaped << '"'; 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, 660b57cec5SDimitry Andric VarSetOperationType op) { 670b57cec5SDimitry Andric Status error; 680b57cec5SDimitry Andric switch (op) { 690b57cec5SDimitry Andric case eVarSetOperationClear: 700b57cec5SDimitry Andric Clear(); 710b57cec5SDimitry Andric NotifyValueChanged(); 720b57cec5SDimitry Andric break; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric case eVarSetOperationReplace: 750b57cec5SDimitry Andric case eVarSetOperationAssign: { 760b57cec5SDimitry Andric // Check if the string starts with a quote character after removing leading 770b57cec5SDimitry Andric // and trailing spaces. If it does start with a quote character, make sure 780b57cec5SDimitry Andric // it ends with the same quote character and remove the quotes before we 790b57cec5SDimitry Andric // parse the format string. If the string doesn't start with a quote, leave 800b57cec5SDimitry Andric // the string alone and parse as is. 810b57cec5SDimitry Andric llvm::StringRef trimmed_value_str = value_str.trim(); 820b57cec5SDimitry Andric if (!trimmed_value_str.empty()) { 830b57cec5SDimitry Andric const char first_char = trimmed_value_str[0]; 840b57cec5SDimitry Andric if (first_char == '"' || first_char == '\'') { 850b57cec5SDimitry Andric const size_t trimmed_len = trimmed_value_str.size(); 860b57cec5SDimitry Andric if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) { 87*e8d8bef9SDimitry Andric error.SetErrorString("mismatched quotes"); 880b57cec5SDimitry Andric return error; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric value_str = trimmed_value_str.substr(1, trimmed_len - 2); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric FormatEntity::Entry entry; 940b57cec5SDimitry Andric error = FormatEntity::Parse(value_str, entry); 950b57cec5SDimitry Andric if (error.Success()) { 960b57cec5SDimitry Andric m_current_entry = std::move(entry); 975ffd83dbSDimitry Andric m_current_format = std::string(value_str); 980b57cec5SDimitry Andric m_value_was_set = true; 990b57cec5SDimitry Andric NotifyValueChanged(); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric } break; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric case eVarSetOperationInsertBefore: 1040b57cec5SDimitry Andric case eVarSetOperationInsertAfter: 1050b57cec5SDimitry Andric case eVarSetOperationRemove: 1060b57cec5SDimitry Andric case eVarSetOperationAppend: 1070b57cec5SDimitry Andric case eVarSetOperationInvalid: 1080b57cec5SDimitry Andric error = OptionValue::SetValueFromString(value_str, op); 1090b57cec5SDimitry Andric break; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric return error; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const { 1150b57cec5SDimitry Andric return OptionValueSP(new OptionValueFormatEntity(*this)); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1189dba64beSDimitry Andric void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, 1190b57cec5SDimitry Andric CompletionRequest &request) { 1209dba64beSDimitry Andric FormatEntity::AutoComplete(request); 1210b57cec5SDimitry Andric } 122