xref: /freebsd/contrib/llvm-project/lldb/source/Interpreter/OptionValueFormatEntity.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry 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 
320b57cec5SDimitry Andric bool 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   return true;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric static void EscapeBackticks(llvm::StringRef str, std::string &dst) {
400b57cec5SDimitry Andric   dst.clear();
410b57cec5SDimitry Andric   dst.reserve(str.size());
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   for (size_t i = 0, e = str.size(); i != e; ++i) {
440b57cec5SDimitry Andric     char c = str[i];
450b57cec5SDimitry Andric     if (c == '`') {
460b57cec5SDimitry Andric       if (i == 0 || str[i - 1] != '\\')
470b57cec5SDimitry Andric         dst += '\\';
480b57cec5SDimitry Andric     }
490b57cec5SDimitry Andric     dst += c;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx,
540b57cec5SDimitry Andric                                         Stream &strm, uint32_t dump_mask) {
550b57cec5SDimitry Andric   if (dump_mask & eDumpOptionType)
560b57cec5SDimitry Andric     strm.Printf("(%s)", GetTypeAsCString());
570b57cec5SDimitry Andric   if (dump_mask & eDumpOptionValue) {
580b57cec5SDimitry Andric     if (dump_mask & eDumpOptionType)
590b57cec5SDimitry Andric       strm.PutCString(" = ");
600b57cec5SDimitry Andric     std::string escaped;
610b57cec5SDimitry Andric     EscapeBackticks(m_current_format, escaped);
620b57cec5SDimitry Andric     strm << '"' << escaped << '"';
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
670b57cec5SDimitry Andric                                                    VarSetOperationType op) {
680b57cec5SDimitry Andric   Status error;
690b57cec5SDimitry Andric   switch (op) {
700b57cec5SDimitry Andric   case eVarSetOperationClear:
710b57cec5SDimitry Andric     Clear();
720b57cec5SDimitry Andric     NotifyValueChanged();
730b57cec5SDimitry Andric     break;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   case eVarSetOperationReplace:
760b57cec5SDimitry Andric   case eVarSetOperationAssign: {
770b57cec5SDimitry Andric     // Check if the string starts with a quote character after removing leading
780b57cec5SDimitry Andric     // and trailing spaces. If it does start with a quote character, make sure
790b57cec5SDimitry Andric     // it ends with the same quote character and remove the quotes before we
800b57cec5SDimitry Andric     // parse the format string. If the string doesn't start with a quote, leave
810b57cec5SDimitry Andric     // the string alone and parse as is.
820b57cec5SDimitry Andric     llvm::StringRef trimmed_value_str = value_str.trim();
830b57cec5SDimitry Andric     if (!trimmed_value_str.empty()) {
840b57cec5SDimitry Andric       const char first_char = trimmed_value_str[0];
850b57cec5SDimitry Andric       if (first_char == '"' || first_char == '\'') {
860b57cec5SDimitry Andric         const size_t trimmed_len = trimmed_value_str.size();
870b57cec5SDimitry Andric         if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) {
880b57cec5SDimitry Andric           error.SetErrorStringWithFormat("mismatched quotes");
890b57cec5SDimitry Andric           return error;
900b57cec5SDimitry Andric         }
910b57cec5SDimitry Andric         value_str = trimmed_value_str.substr(1, trimmed_len - 2);
920b57cec5SDimitry Andric       }
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric     FormatEntity::Entry entry;
950b57cec5SDimitry Andric     error = FormatEntity::Parse(value_str, entry);
960b57cec5SDimitry Andric     if (error.Success()) {
970b57cec5SDimitry Andric       m_current_entry = std::move(entry);
98*5ffd83dbSDimitry Andric       m_current_format = std::string(value_str);
990b57cec5SDimitry Andric       m_value_was_set = true;
1000b57cec5SDimitry Andric       NotifyValueChanged();
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric   } break;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   case eVarSetOperationInsertBefore:
1050b57cec5SDimitry Andric   case eVarSetOperationInsertAfter:
1060b57cec5SDimitry Andric   case eVarSetOperationRemove:
1070b57cec5SDimitry Andric   case eVarSetOperationAppend:
1080b57cec5SDimitry Andric   case eVarSetOperationInvalid:
1090b57cec5SDimitry Andric     error = OptionValue::SetValueFromString(value_str, op);
1100b57cec5SDimitry Andric     break;
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric   return error;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric lldb::OptionValueSP OptionValueFormatEntity::DeepCopy() const {
1160b57cec5SDimitry Andric   return OptionValueSP(new OptionValueFormatEntity(*this));
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1199dba64beSDimitry Andric void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
1200b57cec5SDimitry Andric                                            CompletionRequest &request) {
1219dba64beSDimitry Andric   FormatEntity::AutoComplete(request);
1220b57cec5SDimitry Andric }
123