180814287SRaphael Isemann //===-- OptionValueFormatEntity.cpp ---------------------------------------===//
2554f68d3SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6554f68d3SGreg Clayton //
7554f68d3SGreg Clayton //===----------------------------------------------------------------------===//
8554f68d3SGreg Clayton 
9554f68d3SGreg Clayton #include "lldb/Interpreter/OptionValueFormatEntity.h"
10554f68d3SGreg Clayton 
11554f68d3SGreg Clayton #include "lldb/Core/Module.h"
12554f68d3SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
13bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
14573ab909SZachary Turner #include "lldb/Utility/StringList.h"
15554f68d3SGreg Clayton using namespace lldb;
16554f68d3SGreg Clayton using namespace lldb_private;
17554f68d3SGreg Clayton 
OptionValueFormatEntity(const char * default_format)18*8cdcd41eSTatyana Krasnukha OptionValueFormatEntity::OptionValueFormatEntity(const char *default_format) {
19b9c1b51eSKate Stone   if (default_format && default_format[0]) {
20554f68d3SGreg Clayton     llvm::StringRef default_format_str(default_format);
2197206d57SZachary Turner     Status error = FormatEntity::Parse(default_format_str, m_default_entry);
22b9c1b51eSKate Stone     if (error.Success()) {
23554f68d3SGreg Clayton       m_default_format = default_format;
24554f68d3SGreg Clayton       m_current_format = default_format;
25554f68d3SGreg Clayton       m_current_entry = m_default_entry;
26554f68d3SGreg Clayton     }
27554f68d3SGreg Clayton   }
28554f68d3SGreg Clayton }
29554f68d3SGreg Clayton 
Clear()308d6aa688SJim Ingham void OptionValueFormatEntity::Clear() {
31554f68d3SGreg Clayton   m_current_entry = m_default_entry;
32554f68d3SGreg Clayton   m_current_format = m_default_format;
33554f68d3SGreg Clayton   m_value_was_set = false;
34554f68d3SGreg Clayton }
35554f68d3SGreg Clayton 
EscapeBackticks(llvm::StringRef str,std::string & dst)3664011593SJonas Devlieghere static void EscapeBackticks(llvm::StringRef str, std::string &dst) {
3764011593SJonas Devlieghere   dst.clear();
3864011593SJonas Devlieghere   dst.reserve(str.size());
3964011593SJonas Devlieghere 
4064011593SJonas Devlieghere   for (size_t i = 0, e = str.size(); i != e; ++i) {
4164011593SJonas Devlieghere     char c = str[i];
4264011593SJonas Devlieghere     if (c == '`') {
4364011593SJonas Devlieghere       if (i == 0 || str[i - 1] != '\\')
4464011593SJonas Devlieghere         dst += '\\';
4564011593SJonas Devlieghere     }
4664011593SJonas Devlieghere     dst += c;
4764011593SJonas Devlieghere   }
4864011593SJonas Devlieghere }
4964011593SJonas Devlieghere 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)50b9c1b51eSKate Stone void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx,
51b9c1b51eSKate Stone                                         Stream &strm, uint32_t dump_mask) {
52554f68d3SGreg Clayton   if (dump_mask & eDumpOptionType)
53554f68d3SGreg Clayton     strm.Printf("(%s)", GetTypeAsCString());
54b9c1b51eSKate Stone   if (dump_mask & eDumpOptionValue) {
55554f68d3SGreg Clayton     if (dump_mask & eDumpOptionType)
56b76e25a2SJonas Devlieghere       strm.PutCString(" = ");
5764011593SJonas Devlieghere     std::string escaped;
5864011593SJonas Devlieghere     EscapeBackticks(m_current_format, escaped);
59b76e25a2SJonas Devlieghere     strm << '"' << escaped << '"';
60554f68d3SGreg Clayton   }
61554f68d3SGreg Clayton }
62554f68d3SGreg Clayton 
SetValueFromString(llvm::StringRef value_str,VarSetOperationType op)6397206d57SZachary Turner Status OptionValueFormatEntity::SetValueFromString(llvm::StringRef value_str,
64b9c1b51eSKate Stone                                                    VarSetOperationType op) {
6597206d57SZachary Turner   Status error;
66b9c1b51eSKate Stone   switch (op) {
67554f68d3SGreg Clayton   case eVarSetOperationClear:
68554f68d3SGreg Clayton     Clear();
69554f68d3SGreg Clayton     NotifyValueChanged();
70554f68d3SGreg Clayton     break;
71554f68d3SGreg Clayton 
72554f68d3SGreg Clayton   case eVarSetOperationReplace:
73b9c1b51eSKate Stone   case eVarSetOperationAssign: {
74b9c1b51eSKate Stone     // Check if the string starts with a quote character after removing leading
7505097246SAdrian Prantl     // and trailing spaces. If it does start with a quote character, make sure
7605097246SAdrian Prantl     // it ends with the same quote character and remove the quotes before we
7705097246SAdrian Prantl     // parse the format string. If the string doesn't start with a quote, leave
7805097246SAdrian Prantl     // the string alone and parse as is.
79b2e0c119SGreg Clayton     llvm::StringRef trimmed_value_str = value_str.trim();
80b9c1b51eSKate Stone     if (!trimmed_value_str.empty()) {
81b2e0c119SGreg Clayton       const char first_char = trimmed_value_str[0];
82b9c1b51eSKate Stone       if (first_char == '"' || first_char == '\'') {
83b2e0c119SGreg Clayton         const size_t trimmed_len = trimmed_value_str.size();
84b9c1b51eSKate Stone         if (trimmed_len == 1 || value_str[trimmed_len - 1] != first_char) {
8589533764SJonas Devlieghere           error.SetErrorString("mismatched quotes");
86b2e0c119SGreg Clayton           return error;
87b2e0c119SGreg Clayton         }
88b2e0c119SGreg Clayton         value_str = trimmed_value_str.substr(1, trimmed_len - 2);
89b2e0c119SGreg Clayton       }
90b2e0c119SGreg Clayton     }
91554f68d3SGreg Clayton     FormatEntity::Entry entry;
92554f68d3SGreg Clayton     error = FormatEntity::Parse(value_str, entry);
93b9c1b51eSKate Stone     if (error.Success()) {
94554f68d3SGreg Clayton       m_current_entry = std::move(entry);
95adcd0268SBenjamin Kramer       m_current_format = std::string(value_str);
96554f68d3SGreg Clayton       m_value_was_set = true;
97554f68d3SGreg Clayton       NotifyValueChanged();
98554f68d3SGreg Clayton     }
99b9c1b51eSKate Stone   } break;
100554f68d3SGreg Clayton 
101554f68d3SGreg Clayton   case eVarSetOperationInsertBefore:
102554f68d3SGreg Clayton   case eVarSetOperationInsertAfter:
103554f68d3SGreg Clayton   case eVarSetOperationRemove:
104554f68d3SGreg Clayton   case eVarSetOperationAppend:
105554f68d3SGreg Clayton   case eVarSetOperationInvalid:
106c95f7e2aSPavel Labath     error = OptionValue::SetValueFromString(value_str, op);
107554f68d3SGreg Clayton     break;
108554f68d3SGreg Clayton   }
109554f68d3SGreg Clayton   return error;
110554f68d3SGreg Clayton }
111554f68d3SGreg Clayton 
AutoComplete(CommandInterpreter & interpreter,CompletionRequest & request)112ae34ed2cSRaphael Isemann void OptionValueFormatEntity::AutoComplete(CommandInterpreter &interpreter,
113a2e76c0bSRaphael Isemann                                            CompletionRequest &request) {
114ae34ed2cSRaphael Isemann   FormatEntity::AutoComplete(request);
115554f68d3SGreg Clayton }
116