1 //===-- OptionGroupFormat.cpp -----------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Interpreter/OptionGroupFormat.h"
11
12 #include "lldb/Host/OptionParser.h"
13 #include "lldb/Interpreter/CommandInterpreter.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/Target.h"
16
17 using namespace lldb;
18 using namespace lldb_private;
19
OptionGroupFormat(lldb::Format default_format,uint64_t default_byte_size,uint64_t default_count)20 OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
21 uint64_t default_byte_size,
22 uint64_t default_count)
23 : m_format(default_format, default_format),
24 m_byte_size(default_byte_size, default_byte_size),
25 m_count(default_count, default_count), m_prev_gdb_format('x'),
26 m_prev_gdb_size('w') {}
27
~OptionGroupFormat()28 OptionGroupFormat::~OptionGroupFormat() {}
29
30 static constexpr OptionDefinition g_option_table[] = {
31 {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
32 nullptr, {}, 0, eArgTypeFormat,
33 "Specify a format to be used for display."},
34 {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
35 nullptr, {}, 0, eArgTypeGDBFormat,
36 "Specify a format using a GDB format specifier string."},
37 {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
38 nullptr, {}, 0, eArgTypeByteSize,
39 "The size in bytes to use when displaying with the selected format."},
40 {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
41 nullptr, {}, 0, eArgTypeCount,
42 "The number of total items to display."},
43 };
44
GetDefinitions()45 llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {
46 auto result = llvm::makeArrayRef(g_option_table);
47 if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
48 if (m_count.GetDefaultValue() < UINT64_MAX)
49 return result;
50 else
51 return result.take_front(3);
52 }
53 return result.take_front(2);
54 }
55
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)56 Status OptionGroupFormat::SetOptionValue(uint32_t option_idx,
57 llvm::StringRef option_arg,
58 ExecutionContext *execution_context) {
59 Status error;
60 const int short_option = g_option_table[option_idx].short_option;
61
62 switch (short_option) {
63 case 'f':
64 error = m_format.SetValueFromString(option_arg);
65 break;
66
67 case 'c':
68 if (m_count.GetDefaultValue() == 0) {
69 error.SetErrorString("--count option is disabled");
70 } else {
71 error = m_count.SetValueFromString(option_arg);
72 if (m_count.GetCurrentValue() == 0)
73 error.SetErrorStringWithFormat("invalid --count option value '%s'",
74 option_arg.str().c_str());
75 }
76 break;
77
78 case 's':
79 if (m_byte_size.GetDefaultValue() == 0) {
80 error.SetErrorString("--size option is disabled");
81 } else {
82 error = m_byte_size.SetValueFromString(option_arg);
83 if (m_byte_size.GetCurrentValue() == 0)
84 error.SetErrorStringWithFormat("invalid --size option value '%s'",
85 option_arg.str().c_str());
86 }
87 break;
88
89 case 'G': {
90 uint64_t count = 0;
91 llvm::StringRef gdb_format_str = option_arg;
92 gdb_format_str.consumeInteger(0, count);
93
94 Format format = eFormatDefault;
95 uint32_t byte_size = 0;
96
97 while (!gdb_format_str.empty() &&
98 ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,
99 byte_size)) {
100 gdb_format_str = gdb_format_str.drop_front();
101 }
102
103 // We the first character of the "gdb_format_str" is not the
104 // NULL terminator, we didn't consume the entire string and
105 // something is wrong. Also, if none of the format, size or count was
106 // specified correctly, then abort.
107 if (!gdb_format_str.empty() ||
108 (format == eFormatInvalid && byte_size == 0 && count == 0)) {
109 // Nothing got set correctly
110 error.SetErrorStringWithFormat("invalid gdb format string '%s'",
111 option_arg.str().c_str());
112 return error;
113 }
114
115 // At least one of the format, size or count was set correctly. Anything
116 // that wasn't set correctly should be set to the previous default
117 if (format == eFormatInvalid)
118 ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
119 byte_size);
120
121 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
122 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
123 if (byte_size_enabled) {
124 // Byte size is enabled
125 if (byte_size == 0)
126 ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
127 byte_size);
128 } else {
129 // Byte size is disabled, make sure it wasn't specified but if this is an
130 // address, it's actually necessary to specify one so don't error out
131 if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
132 error.SetErrorString(
133 "this command doesn't support specifying a byte size");
134 return error;
135 }
136 }
137
138 if (count_enabled) {
139 // Count is enabled and was not set, set it to the default for gdb format
140 // statements (which is 1).
141 if (count == 0)
142 count = 1;
143 } else {
144 // Count is disabled, make sure it wasn't specified
145 if (count > 0) {
146 error.SetErrorString("this command doesn't support specifying a count");
147 return error;
148 }
149 }
150
151 m_format.SetCurrentValue(format);
152 m_format.SetOptionWasSet();
153 if (byte_size_enabled) {
154 m_byte_size.SetCurrentValue(byte_size);
155 m_byte_size.SetOptionWasSet();
156 }
157 if (count_enabled) {
158 m_count.SetCurrentValue(count);
159 m_count.SetOptionWasSet();
160 }
161 } break;
162
163 default:
164 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
165 break;
166 }
167
168 return error;
169 }
170
ParserGDBFormatLetter(ExecutionContext * execution_context,char format_letter,Format & format,uint32_t & byte_size)171 bool OptionGroupFormat::ParserGDBFormatLetter(
172 ExecutionContext *execution_context, char format_letter, Format &format,
173 uint32_t &byte_size) {
174 m_has_gdb_format = true;
175 switch (format_letter) {
176 case 'o':
177 format = eFormatOctal;
178 m_prev_gdb_format = format_letter;
179 return true;
180 case 'x':
181 format = eFormatHex;
182 m_prev_gdb_format = format_letter;
183 return true;
184 case 'd':
185 format = eFormatDecimal;
186 m_prev_gdb_format = format_letter;
187 return true;
188 case 'u':
189 format = eFormatUnsigned;
190 m_prev_gdb_format = format_letter;
191 return true;
192 case 't':
193 format = eFormatBinary;
194 m_prev_gdb_format = format_letter;
195 return true;
196 case 'f':
197 format = eFormatFloat;
198 m_prev_gdb_format = format_letter;
199 return true;
200 case 'a':
201 format = eFormatAddressInfo;
202 {
203 TargetSP target_sp =
204 execution_context ? execution_context->GetTargetSP() : TargetSP();
205 if (target_sp)
206 byte_size = target_sp->GetArchitecture().GetAddressByteSize();
207 m_prev_gdb_format = format_letter;
208 return true;
209 }
210 case 'i':
211 format = eFormatInstruction;
212 m_prev_gdb_format = format_letter;
213 return true;
214 case 'c':
215 format = eFormatChar;
216 m_prev_gdb_format = format_letter;
217 return true;
218 case 's':
219 format = eFormatCString;
220 m_prev_gdb_format = format_letter;
221 return true;
222 case 'T':
223 format = eFormatOSType;
224 m_prev_gdb_format = format_letter;
225 return true;
226 case 'A':
227 format = eFormatHexFloat;
228 m_prev_gdb_format = format_letter;
229 return true;
230
231 case 'b':
232 case 'h':
233 case 'w':
234 case 'g':
235 {
236 // Size isn't used for printing instructions, so if a size is specified,
237 // and the previous format was 'i', then we should reset it to the
238 // default ('x'). Otherwise we'll continue to print as instructions,
239 // which isn't expected.
240 if (format_letter == 'b')
241 byte_size = 1;
242 else if (format_letter == 'h')
243 byte_size = 2;
244 else if (format_letter == 'w')
245 byte_size = 4;
246 else if (format_letter == 'g')
247 byte_size = 8;
248
249 m_prev_gdb_size = format_letter;
250 if (m_prev_gdb_format == 'i')
251 m_prev_gdb_format = 'x';
252 return true;
253 }
254 break;
255 default:
256 break;
257 }
258
259
260 return false;
261 }
262
OptionParsingStarting(ExecutionContext * execution_context)263 void OptionGroupFormat::OptionParsingStarting(
264 ExecutionContext *execution_context) {
265 m_format.Clear();
266 m_byte_size.Clear();
267 m_count.Clear();
268 m_has_gdb_format = false;
269 }
270