1dda28197Spatrick //===-- OptionValueFormatEntity.cpp ---------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "lldb/Interpreter/OptionValueFormatEntity.h" 10061da546Spatrick 11061da546Spatrick #include "lldb/Core/Module.h" 12061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h" 13061da546Spatrick #include "lldb/Utility/Stream.h" 14061da546Spatrick #include "lldb/Utility/StringList.h" 15061da546Spatrick using namespace lldb; 16061da546Spatrick using namespace lldb_private; 17061da546Spatrick 18*be691f3bSpatrick OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) { 19061da546Spatrick if (default_format && default_format[0]) { 20061da546Spatrick llvm::StringRef default_format_str(default_format); 21061da546Spatrick Status error = FormatEntity::Parse(default_format_str, m_default_entry); 22061da546Spatrick if (error.Success()) { 23061da546Spatrick m_default_format = default_format; 24061da546Spatrick m_current_format = default_format; 25061da546Spatrick m_current_entry = m_default_entry; 26061da546Spatrick } 27061da546Spatrick } 28061da546Spatrick } 29061da546Spatrick 30*be691f3bSpatrick void OptionValueFormatEntity::Clear() { 31061da546Spatrick m_current_entry = m_default_entry; 32061da546Spatrick m_current_format = m_default_format; 33061da546Spatrick m_value_was_set = false; 34061da546Spatrick } 35061da546Spatrick 36061da546Spatrick static void EscapeBackticks(llvm::StringRef str, std::string &dst) { 37061da546Spatrick dst.clear(); 38061da546Spatrick dst.reserve(str.size()); 39061da546Spatrick 40061da546Spatrick for (size_t i = 0, e = str.size(); i != e; ++i) { 41061da546Spatrick char c = str[i]; 42061da546Spatrick if (c == '`') { 43061da546Spatrick if (i == 0 || str[i - 1] != '\\') 44061da546Spatrick dst += '\\'; 45061da546Spatrick } 46061da546Spatrick dst += c; 47061da546Spatrick } 48061da546Spatrick } 49061da546Spatrick 50061da546Spatrick void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx, 51061da546Spatrick Stream &strm, uint32_t dump_mask) { 52061da546Spatrick if (dump_mask & eDumpOptionType) 53061da546Spatrick strm.Printf("(%s)", GetTypeAsCString()); 54061da546Spatrick if (dump_mask & eDumpOptionValue) { 55061da546Spatrick if (dump_mask & eDumpOptionType) 56061da546Spatrick strm.PutCString(" = "); 57061da546Spatrick std::string escaped; 58061da546Spatrick EscapeBackticks(m_current_format, escaped); 59061da546Spatrick strm << '"' << escaped << '"'; 60061da546Spatrick } 61061da546Spatrick } 62061da546Spatrick 63061da546Spatrick Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str, 64061da546Spatrick VarSetOperationType op) { 65061da546Spatrick Status error; 66061da546Spatrick switch (op) { 67061da546Spatrick case eVarSetOperationClear: 68061da546Spatrick Clear(); 69061da546Spatrick NotifyValueChanged(); 70061da546Spatrick break; 71061da546Spatrick 72061da546Spatrick case eVarSetOperationReplace: 73061da546Spatrick case eVarSetOperationAssign: { 74061da546Spatrick // Check if the string starts with a quote character after removing leading 75061da546Spatrick // and trailing spaces. If it does start with a quote character, make sure 76061da546Spatrick // it ends with the same quote character and remove the quotes before we 77061da546Spatrick // parse the format string. If the string doesn't start with a quote, leave 78061da546Spatrick // the string alone and parse as is. 79061da546Spatrick llvm::StringRef trimmed_value_str = value_str.trim(); 80061da546Spatrick if (!trimmed_value_str.empty()) { 81061da546Spatrick const char first_char = trimmed_value_str[0]; 82061da546Spatrick if (first_char == '"' || first_char == '\'') { 83061da546Spatrick const size_t trimmed_len = trimmed_value_str.size(); 84061da546Spatrick if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) { 85*be691f3bSpatrick error.SetErrorString("mismatched quotes"); 86061da546Spatrick return error; 87061da546Spatrick } 88061da546Spatrick value_str = trimmed_value_str.substr(1, trimmed_len - 2); 89061da546Spatrick } 90061da546Spatrick } 91061da546Spatrick FormatEntity::Entry entry; 92061da546Spatrick error = FormatEntity::Parse(value_str, entry); 93061da546Spatrick if (error.Success()) { 94061da546Spatrick m_current_entry = std::move(entry); 95dda28197Spatrick m_current_format = std::string(value_str); 96061da546Spatrick m_value_was_set = true; 97061da546Spatrick NotifyValueChanged(); 98061da546Spatrick } 99061da546Spatrick } break; 100061da546Spatrick 101061da546Spatrick case eVarSetOperationInsertBefore: 102061da546Spatrick case eVarSetOperationInsertAfter: 103061da546Spatrick case eVarSetOperationRemove: 104061da546Spatrick case eVarSetOperationAppend: 105061da546Spatrick case eVarSetOperationInvalid: 106061da546Spatrick error = OptionValue::SetValueFromString(value_str, op); 107061da546Spatrick break; 108061da546Spatrick } 109061da546Spatrick return error; 110061da546Spatrick } 111061da546Spatrick 112061da546Spatrick void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter, 113061da546Spatrick CompletionRequest &request) { 114061da546Spatrick FormatEntity::AutoComplete(request); 115061da546Spatrick } 116