180814287SRaphael Isemann //===-- OptionGroupFormat.cpp ---------------------------------------------===//
284c39663SGreg 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
684c39663SGreg Clayton //
784c39663SGreg Clayton //===----------------------------------------------------------------------===//
884c39663SGreg Clayton
94bee32e5SJohnny Chen #include "lldb/Interpreter/OptionGroupFormat.h"
1084c39663SGreg Clayton
113eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
1281409635SGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
1381409635SGreg Clayton #include "lldb/Target/ExecutionContext.h"
1481409635SGreg Clayton #include "lldb/Target/Target.h"
1584c39663SGreg Clayton
1684c39663SGreg Clayton using namespace lldb;
1784c39663SGreg Clayton using namespace lldb_private;
1884c39663SGreg Clayton
19*7f05ff8bSVenkata Ramanaiah Nalamothu static constexpr OptionDefinition g_default_option_definitions[] = {
20b9c1b51eSKate Stone {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
218fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeFormat,
22b9c1b51eSKate Stone "Specify a format to be used for display."},
23b9c1b51eSKate Stone {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
248fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeGDBFormat,
25b9c1b51eSKate Stone "Specify a format using a GDB format specifier string."},
26b9c1b51eSKate Stone {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
278fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeByteSize,
28b9c1b51eSKate Stone "The size in bytes to use when displaying with the selected format."},
29b9c1b51eSKate Stone {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
308fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeCount,
31b9c1b51eSKate Stone "The number of total items to display."},
3284c39663SGreg Clayton };
3384c39663SGreg Clayton
OptionGroupFormat(lldb::Format default_format,uint64_t default_byte_size,uint64_t default_count,OptionGroupFormatUsageTextVector usage_text_vector)34*7f05ff8bSVenkata Ramanaiah Nalamothu OptionGroupFormat::OptionGroupFormat(
35*7f05ff8bSVenkata Ramanaiah Nalamothu lldb::Format default_format, uint64_t default_byte_size,
36*7f05ff8bSVenkata Ramanaiah Nalamothu uint64_t default_count, OptionGroupFormatUsageTextVector usage_text_vector)
37*7f05ff8bSVenkata Ramanaiah Nalamothu : m_format(default_format, default_format),
38*7f05ff8bSVenkata Ramanaiah Nalamothu m_byte_size(default_byte_size, default_byte_size),
39*7f05ff8bSVenkata Ramanaiah Nalamothu m_count(default_count, default_count), m_prev_gdb_format('x'),
40*7f05ff8bSVenkata Ramanaiah Nalamothu m_prev_gdb_size('w') {
41*7f05ff8bSVenkata Ramanaiah Nalamothu // Copy the default option definitions.
42*7f05ff8bSVenkata Ramanaiah Nalamothu std::copy(std::begin(g_default_option_definitions),
43*7f05ff8bSVenkata Ramanaiah Nalamothu std::end(g_default_option_definitions),
44*7f05ff8bSVenkata Ramanaiah Nalamothu std::begin(m_option_definitions));
45*7f05ff8bSVenkata Ramanaiah Nalamothu
46*7f05ff8bSVenkata Ramanaiah Nalamothu for (auto usage_text_tuple : usage_text_vector) {
47*7f05ff8bSVenkata Ramanaiah Nalamothu switch (std::get<0>(usage_text_tuple)) {
48*7f05ff8bSVenkata Ramanaiah Nalamothu case eArgTypeFormat:
49*7f05ff8bSVenkata Ramanaiah Nalamothu m_option_definitions[0].usage_text = std::get<1>(usage_text_tuple);
50*7f05ff8bSVenkata Ramanaiah Nalamothu break;
51*7f05ff8bSVenkata Ramanaiah Nalamothu case eArgTypeByteSize:
52*7f05ff8bSVenkata Ramanaiah Nalamothu m_option_definitions[2].usage_text = std::get<1>(usage_text_tuple);
53*7f05ff8bSVenkata Ramanaiah Nalamothu break;
54*7f05ff8bSVenkata Ramanaiah Nalamothu default:
55*7f05ff8bSVenkata Ramanaiah Nalamothu llvm_unreachable("Unimplemented option");
56*7f05ff8bSVenkata Ramanaiah Nalamothu }
57*7f05ff8bSVenkata Ramanaiah Nalamothu }
58*7f05ff8bSVenkata Ramanaiah Nalamothu }
59*7f05ff8bSVenkata Ramanaiah Nalamothu
GetDefinitions()601f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {
61*7f05ff8bSVenkata Ramanaiah Nalamothu auto result = llvm::makeArrayRef(m_option_definitions);
62b9c1b51eSKate Stone if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
631deb7962SGreg Clayton if (m_count.GetDefaultValue() < UINT64_MAX)
641f0f5b5bSZachary Turner return result;
651deb7962SGreg Clayton else
661f0f5b5bSZachary Turner return result.take_front(3);
671deb7962SGreg Clayton }
681f0f5b5bSZachary Turner return result.take_front(2);
6984c39663SGreg Clayton }
7084c39663SGreg Clayton
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7197206d57SZachary Turner Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
728cef4b0bSZachary Turner llvm::StringRef option_arg,
73b9c1b51eSKate Stone ExecutionContext *execution_context) {
7497206d57SZachary Turner Status error;
75*7f05ff8bSVenkata Ramanaiah Nalamothu const int short_option = m_option_definitions[option_idx].short_option;
7684c39663SGreg Clayton
77b9c1b51eSKate Stone switch (short_option) {
7884c39663SGreg Clayton case 'f':
79c95f7e2aSPavel Labath error = m_format.SetValueFromString(option_arg);
8084c39663SGreg Clayton break;
8184c39663SGreg Clayton
821deb7962SGreg Clayton case 'c':
83b9c1b51eSKate Stone if (m_count.GetDefaultValue() == 0) {
841deb7962SGreg Clayton error.SetErrorString("--count option is disabled");
85b9c1b51eSKate Stone } else {
86c95f7e2aSPavel Labath error = m_count.SetValueFromString(option_arg);
871deb7962SGreg Clayton if (m_count.GetCurrentValue() == 0)
88b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid --count option value '%s'",
898cef4b0bSZachary Turner option_arg.str().c_str());
901deb7962SGreg Clayton }
911deb7962SGreg Clayton break;
921deb7962SGreg Clayton
931deb7962SGreg Clayton case 's':
94b9c1b51eSKate Stone if (m_byte_size.GetDefaultValue() == 0) {
951deb7962SGreg Clayton error.SetErrorString("--size option is disabled");
96b9c1b51eSKate Stone } else {
97c95f7e2aSPavel Labath error = m_byte_size.SetValueFromString(option_arg);
981deb7962SGreg Clayton if (m_byte_size.GetCurrentValue() == 0)
99b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid --size option value '%s'",
1008cef4b0bSZachary Turner option_arg.str().c_str());
1011deb7962SGreg Clayton }
1021deb7962SGreg Clayton break;
1031deb7962SGreg Clayton
104b9c1b51eSKate Stone case 'G': {
10586edbf41SGreg Clayton uint64_t count = 0;
1068cef4b0bSZachary Turner llvm::StringRef gdb_format_str = option_arg;
1078cef4b0bSZachary Turner gdb_format_str.consumeInteger(0, count);
10886edbf41SGreg Clayton
1097c533b24SGreg Clayton Format format = eFormatDefault;
1107c533b24SGreg Clayton uint32_t byte_size = 0;
11186edbf41SGreg Clayton
1128cef4b0bSZachary Turner while (!gdb_format_str.empty() &&
1138cef4b0bSZachary Turner ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,
114b9c1b51eSKate Stone byte_size)) {
1158cef4b0bSZachary Turner gdb_format_str = gdb_format_str.drop_front();
1167c533b24SGreg Clayton }
11786edbf41SGreg Clayton
1188cef4b0bSZachary Turner // We the first character of the "gdb_format_str" is not the
11986edbf41SGreg Clayton // NULL terminator, we didn't consume the entire string and
12005097246SAdrian Prantl // something is wrong. Also, if none of the format, size or count was
12105097246SAdrian Prantl // specified correctly, then abort.
1228cef4b0bSZachary Turner if (!gdb_format_str.empty() ||
123b9c1b51eSKate Stone (format == eFormatInvalid && byte_size == 0 && count == 0)) {
12486edbf41SGreg Clayton // Nothing got set correctly
125b9c1b51eSKate Stone error.SetErrorStringWithFormat("invalid gdb format string '%s'",
1268cef4b0bSZachary Turner option_arg.str().c_str());
12786edbf41SGreg Clayton return error;
12886edbf41SGreg Clayton }
12986edbf41SGreg Clayton
13005097246SAdrian Prantl // At least one of the format, size or count was set correctly. Anything
13105097246SAdrian Prantl // that wasn't set correctly should be set to the previous default
13286edbf41SGreg Clayton if (format == eFormatInvalid)
133b9c1b51eSKate Stone ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
134b9c1b51eSKate Stone byte_size);
13586edbf41SGreg Clayton
13686edbf41SGreg Clayton const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
13786edbf41SGreg Clayton const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
138b9c1b51eSKate Stone if (byte_size_enabled) {
13986edbf41SGreg Clayton // Byte size is enabled
14086edbf41SGreg Clayton if (byte_size == 0)
141b9c1b51eSKate Stone ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
142b9c1b51eSKate Stone byte_size);
143b9c1b51eSKate Stone } else {
14405097246SAdrian Prantl // Byte size is disabled, make sure it wasn't specified but if this is an
14505097246SAdrian Prantl // address, it's actually necessary to specify one so don't error out
146b9c1b51eSKate Stone if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
147b9c1b51eSKate Stone error.SetErrorString(
148b9c1b51eSKate Stone "this command doesn't support specifying a byte size");
14986edbf41SGreg Clayton return error;
15086edbf41SGreg Clayton }
15186edbf41SGreg Clayton }
15286edbf41SGreg Clayton
153b9c1b51eSKate Stone if (count_enabled) {
154b9c1b51eSKate Stone // Count is enabled and was not set, set it to the default for gdb format
155b9c1b51eSKate Stone // statements (which is 1).
15686edbf41SGreg Clayton if (count == 0)
157608036aeSJim Ingham count = 1;
158b9c1b51eSKate Stone } else {
15986edbf41SGreg Clayton // Count is disabled, make sure it wasn't specified
160b9c1b51eSKate Stone if (count > 0) {
16186edbf41SGreg Clayton error.SetErrorString("this command doesn't support specifying a count");
16286edbf41SGreg Clayton return error;
16386edbf41SGreg Clayton }
16486edbf41SGreg Clayton }
16586edbf41SGreg Clayton
16686edbf41SGreg Clayton m_format.SetCurrentValue(format);
16786edbf41SGreg Clayton m_format.SetOptionWasSet();
168b9c1b51eSKate Stone if (byte_size_enabled) {
16986edbf41SGreg Clayton m_byte_size.SetCurrentValue(byte_size);
17086edbf41SGreg Clayton m_byte_size.SetOptionWasSet();
17186edbf41SGreg Clayton }
172b9c1b51eSKate Stone if (count_enabled) {
17386edbf41SGreg Clayton m_count.SetCurrentValue(count);
17486edbf41SGreg Clayton m_count.SetOptionWasSet();
17586edbf41SGreg Clayton }
176b9c1b51eSKate Stone } break;
17786edbf41SGreg Clayton
17884c39663SGreg Clayton default:
17936162014SRaphael Isemann llvm_unreachable("Unimplemented option");
18084c39663SGreg Clayton }
18184c39663SGreg Clayton
18284c39663SGreg Clayton return error;
18384c39663SGreg Clayton }
18484c39663SGreg Clayton
ParserGDBFormatLetter(ExecutionContext * execution_context,char format_letter,Format & format,uint32_t & byte_size)185b9c1b51eSKate Stone bool OptionGroupFormat::ParserGDBFormatLetter(
186b9c1b51eSKate Stone ExecutionContext *execution_context, char format_letter, Format &format,
187b9c1b51eSKate Stone uint32_t &byte_size) {
1886b4ddc65SEnrico Granata m_has_gdb_format = true;
189b9c1b51eSKate Stone switch (format_letter) {
190b9c1b51eSKate Stone case 'o':
191b9c1b51eSKate Stone format = eFormatOctal;
192b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
193b9c1b51eSKate Stone return true;
194b9c1b51eSKate Stone case 'x':
195b9c1b51eSKate Stone format = eFormatHex;
196b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
197b9c1b51eSKate Stone return true;
198b9c1b51eSKate Stone case 'd':
199b9c1b51eSKate Stone format = eFormatDecimal;
200b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
201b9c1b51eSKate Stone return true;
202b9c1b51eSKate Stone case 'u':
203b9c1b51eSKate Stone format = eFormatUnsigned;
204b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
205b9c1b51eSKate Stone return true;
206b9c1b51eSKate Stone case 't':
207b9c1b51eSKate Stone format = eFormatBinary;
208b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
209b9c1b51eSKate Stone return true;
210b9c1b51eSKate Stone case 'f':
211b9c1b51eSKate Stone format = eFormatFloat;
212b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
213b9c1b51eSKate Stone return true;
214b9c1b51eSKate Stone case 'a':
215b9c1b51eSKate Stone format = eFormatAddressInfo;
21686edbf41SGreg Clayton {
217b9c1b51eSKate Stone TargetSP target_sp =
218b9c1b51eSKate Stone execution_context ? execution_context->GetTargetSP() : TargetSP();
219e1cfbc79STodd Fiala if (target_sp)
220e1cfbc79STodd Fiala byte_size = target_sp->GetArchitecture().GetAddressByteSize();
22181409635SGreg Clayton m_prev_gdb_format = format_letter;
22281409635SGreg Clayton return true;
22381409635SGreg Clayton }
224b9c1b51eSKate Stone case 'i':
225b9c1b51eSKate Stone format = eFormatInstruction;
226b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
227b9c1b51eSKate Stone return true;
228b9c1b51eSKate Stone case 'c':
229b9c1b51eSKate Stone format = eFormatChar;
230b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
231b9c1b51eSKate Stone return true;
232b9c1b51eSKate Stone case 's':
233b9c1b51eSKate Stone format = eFormatCString;
234b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
235b9c1b51eSKate Stone return true;
236b9c1b51eSKate Stone case 'T':
237b9c1b51eSKate Stone format = eFormatOSType;
238b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
239b9c1b51eSKate Stone return true;
240b9c1b51eSKate Stone case 'A':
241b9c1b51eSKate Stone format = eFormatHexFloat;
242b9c1b51eSKate Stone m_prev_gdb_format = format_letter;
243b9c1b51eSKate Stone return true;
24422c9e7b2SJim Ingham
245a1609ff6SJason Molenda case 'b':
246a1609ff6SJason Molenda case 'h':
247a1609ff6SJason Molenda case 'w':
248a1609ff6SJason Molenda case 'g':
249a1609ff6SJason Molenda {
25005097246SAdrian Prantl // Size isn't used for printing instructions, so if a size is specified,
25105097246SAdrian Prantl // and the previous format was 'i', then we should reset it to the
25205097246SAdrian Prantl // default ('x'). Otherwise we'll continue to print as instructions,
25322c9e7b2SJim Ingham // which isn't expected.
254a1609ff6SJason Molenda if (format_letter == 'b')
25522c9e7b2SJim Ingham byte_size = 1;
256a1609ff6SJason Molenda else if (format_letter == 'h')
25722c9e7b2SJim Ingham byte_size = 2;
258a1609ff6SJason Molenda else if (format_letter == 'w')
25922c9e7b2SJim Ingham byte_size = 4;
260a1609ff6SJason Molenda else if (format_letter == 'g')
26122c9e7b2SJim Ingham byte_size = 8;
26222c9e7b2SJim Ingham
26322c9e7b2SJim Ingham m_prev_gdb_size = format_letter;
26422c9e7b2SJim Ingham if (m_prev_gdb_format == 'i')
26522c9e7b2SJim Ingham m_prev_gdb_format = 'x';
26622c9e7b2SJim Ingham return true;
267a1609ff6SJason Molenda }
26822c9e7b2SJim Ingham break;
269b9c1b51eSKate Stone default:
270b9c1b51eSKate Stone break;
27186edbf41SGreg Clayton }
272a1609ff6SJason Molenda
273a1609ff6SJason Molenda
2747c533b24SGreg Clayton return false;
27586edbf41SGreg Clayton }
27686edbf41SGreg Clayton
OptionParsingStarting(ExecutionContext * execution_context)277b9c1b51eSKate Stone void OptionGroupFormat::OptionParsingStarting(
278b9c1b51eSKate Stone ExecutionContext *execution_context) {
27984c39663SGreg Clayton m_format.Clear();
2801deb7962SGreg Clayton m_byte_size.Clear();
2811deb7962SGreg Clayton m_count.Clear();
2826b4ddc65SEnrico Granata m_has_gdb_format = false;
28384c39663SGreg Clayton }
284