blob: aa0d3cc3369e0883664fbe544361216f1a20e558 [file] [log] [blame]
Greg Clayton84c39662011-04-27 22:04:39 +00001//===-- 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
Johnny Chen4bee32e2011-05-13 20:21:08 +000010#include "lldb/Interpreter/OptionGroupFormat.h"
Greg Clayton84c39662011-04-27 22:04:39 +000011
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Greg Clayton81409632012-12-15 01:44:51 +000016#include "lldb/Core/ArchSpec.h"
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Target/ExecutionContext.h"
19#include "lldb/Target/Target.h"
Johnny Chen7c575b32011-09-10 00:48:33 +000020#include "lldb/Utility/Utils.h"
Greg Clayton84c39662011-04-27 22:04:39 +000021
22using namespace lldb;
23using namespace lldb_private;
24
Kate Stoneb9c1b512016-09-06 20:57:50 +000025OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
26 uint64_t default_byte_size,
27 uint64_t default_count)
28 : m_format(default_format, default_format),
29 m_byte_size(default_byte_size, default_byte_size),
30 m_count(default_count, default_count), m_prev_gdb_format('x'),
31 m_prev_gdb_size('w') {}
Greg Clayton84c39662011-04-27 22:04:39 +000032
Kate Stoneb9c1b512016-09-06 20:57:50 +000033OptionGroupFormat::~OptionGroupFormat() {}
Greg Clayton84c39662011-04-27 22:04:39 +000034
Kate Stoneb9c1b512016-09-06 20:57:50 +000035static OptionDefinition g_option_table[] = {
36 {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
37 nullptr, nullptr, 0, eArgTypeFormat,
38 "Specify a format to be used for display."},
39 {LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
40 nullptr, nullptr, 0, eArgTypeGDBFormat,
41 "Specify a format using a GDB format specifier string."},
42 {LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
43 nullptr, nullptr, 0, eArgTypeByteSize,
44 "The size in bytes to use when displaying with the selected format."},
45 {LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
46 nullptr, nullptr, 0, eArgTypeCount,
47 "The number of total items to display."},
Greg Clayton84c39662011-04-27 22:04:39 +000048};
Greg Clayton84c39662011-04-27 22:04:39 +000049
Kate Stoneb9c1b512016-09-06 20:57:50 +000050uint32_t OptionGroupFormat::GetNumDefinitions() {
51 if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
52 if (m_count.GetDefaultValue() < UINT64_MAX)
53 return 4;
54 else
55 return 3;
56 }
57 return 2;
58}
59
60const OptionDefinition *OptionGroupFormat::GetDefinitions() {
61 return g_option_table;
62}
63
64Error OptionGroupFormat::SetOptionValue(uint32_t option_idx,
65 const char *option_arg,
66 ExecutionContext *execution_context) {
67 Error error;
68 const int short_option = g_option_table[option_idx].short_option;
69
70 switch (short_option) {
71 case 'f':
72 error = m_format.SetValueFromString(option_arg);
73 break;
74
75 case 'c':
76 if (m_count.GetDefaultValue() == 0) {
77 error.SetErrorString("--count option is disabled");
78 } else {
79 error = m_count.SetValueFromString(option_arg);
80 if (m_count.GetCurrentValue() == 0)
81 error.SetErrorStringWithFormat("invalid --count option value '%s'",
82 option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +000083 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 break;
Greg Clayton84c39662011-04-27 22:04:39 +000085
Kate Stoneb9c1b512016-09-06 20:57:50 +000086 case 's':
87 if (m_byte_size.GetDefaultValue() == 0) {
88 error.SetErrorString("--size option is disabled");
89 } else {
90 error = m_byte_size.SetValueFromString(option_arg);
91 if (m_byte_size.GetCurrentValue() == 0)
92 error.SetErrorStringWithFormat("invalid --size option value '%s'",
93 option_arg);
94 }
95 break;
Greg Clayton84c39662011-04-27 22:04:39 +000096
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 case 'G': {
98 char *end = nullptr;
99 const char *gdb_format_cstr = option_arg;
100 uint64_t count = 0;
101 if (::isdigit(gdb_format_cstr[0])) {
102 count = strtoull(gdb_format_cstr, &end, 0);
Greg Clayton84c39662011-04-27 22:04:39 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 if (option_arg != end)
105 gdb_format_cstr =
106 end; // We have a valid count, advance the string position
107 else
108 count = 0;
Greg Clayton84c39662011-04-27 22:04:39 +0000109 }
110
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111 Format format = eFormatDefault;
112 uint32_t byte_size = 0;
Greg Clayton84c39662011-04-27 22:04:39 +0000113
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114 while (ParserGDBFormatLetter(execution_context, gdb_format_cstr[0], format,
115 byte_size)) {
116 ++gdb_format_cstr;
Greg Clayton86edbf42011-10-26 00:56:27 +0000117 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118
119 // We the first character of the "gdb_format_cstr" is not the
120 // NULL terminator, we didn't consume the entire string and
121 // something is wrong. Also, if none of the format, size or count
122 // was specified correctly, then abort.
123 if (gdb_format_cstr[0] ||
124 (format == eFormatInvalid && byte_size == 0 && count == 0)) {
125 // Nothing got set correctly
126 error.SetErrorStringWithFormat("invalid gdb format string '%s'",
127 option_arg);
128 return error;
129 }
130
131 // At least one of the format, size or count was set correctly.
132 // Anything that wasn't set correctly should be set to the
133 // previous default
134 if (format == eFormatInvalid)
135 ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
136 byte_size);
137
138 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
139 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
140 if (byte_size_enabled) {
141 // Byte size is enabled
142 if (byte_size == 0)
143 ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
144 byte_size);
145 } else {
146 // Byte size is disabled, make sure it wasn't specified
147 // but if this is an address, it's actually necessary to
148 // specify one so don't error out
149 if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
150 error.SetErrorString(
151 "this command doesn't support specifying a byte size");
152 return error;
153 }
154 }
155
156 if (count_enabled) {
157 // Count is enabled and was not set, set it to the default for gdb format
158 // statements (which is 1).
159 if (count == 0)
160 count = 1;
161 } else {
162 // Count is disabled, make sure it wasn't specified
163 if (count > 0) {
164 error.SetErrorString("this command doesn't support specifying a count");
165 return error;
166 }
167 }
168
169 m_format.SetCurrentValue(format);
170 m_format.SetOptionWasSet();
171 if (byte_size_enabled) {
172 m_byte_size.SetCurrentValue(byte_size);
173 m_byte_size.SetOptionWasSet();
174 }
175 if (count_enabled) {
176 m_count.SetCurrentValue(count);
177 m_count.SetOptionWasSet();
178 }
179 } break;
180
181 default:
182 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
183 break;
184 }
185
186 return error;
Greg Clayton86edbf42011-10-26 00:56:27 +0000187}
188
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189bool OptionGroupFormat::ParserGDBFormatLetter(
190 ExecutionContext *execution_context, char format_letter, Format &format,
191 uint32_t &byte_size) {
192 m_has_gdb_format = true;
193 switch (format_letter) {
194 case 'o':
195 format = eFormatOctal;
196 m_prev_gdb_format = format_letter;
197 return true;
198 case 'x':
199 format = eFormatHex;
200 m_prev_gdb_format = format_letter;
201 return true;
202 case 'd':
203 format = eFormatDecimal;
204 m_prev_gdb_format = format_letter;
205 return true;
206 case 'u':
207 format = eFormatUnsigned;
208 m_prev_gdb_format = format_letter;
209 return true;
210 case 't':
211 format = eFormatBinary;
212 m_prev_gdb_format = format_letter;
213 return true;
214 case 'f':
215 format = eFormatFloat;
216 m_prev_gdb_format = format_letter;
217 return true;
218 case 'a':
219 format = eFormatAddressInfo;
220 {
221 TargetSP target_sp =
222 execution_context ? execution_context->GetTargetSP() : TargetSP();
223 if (target_sp)
224 byte_size = target_sp->GetArchitecture().GetAddressByteSize();
225 m_prev_gdb_format = format_letter;
226 return true;
227 }
228 case 'i':
229 format = eFormatInstruction;
230 m_prev_gdb_format = format_letter;
231 return true;
232 case 'c':
233 format = eFormatChar;
234 m_prev_gdb_format = format_letter;
235 return true;
236 case 's':
237 format = eFormatCString;
238 m_prev_gdb_format = format_letter;
239 return true;
240 case 'T':
241 format = eFormatOSType;
242 m_prev_gdb_format = format_letter;
243 return true;
244 case 'A':
245 format = eFormatHexFloat;
246 m_prev_gdb_format = format_letter;
247 return true;
248
249 // Size isn't used for printing instructions, so if a size is specified, and
250 // the previous format was
251 // 'i', then we should reset it to the default ('x'). Otherwise we'll
252 // continue to print as instructions,
253 // which isn't expected.
254 case 'b':
255 byte_size = 1;
256 LLVM_FALLTHROUGH;
257 case 'h':
258 byte_size = 2;
259 LLVM_FALLTHROUGH;
260 case 'w':
261 byte_size = 4;
262 LLVM_FALLTHROUGH;
263 case 'g':
264 byte_size = 8;
265
266 m_prev_gdb_size = format_letter;
267 if (m_prev_gdb_format == 'i')
268 m_prev_gdb_format = 'x';
269 return true;
270
271 break;
272 default:
273 break;
274 }
275 return false;
276}
277
278void OptionGroupFormat::OptionParsingStarting(
279 ExecutionContext *execution_context) {
280 m_format.Clear();
281 m_byte_size.Clear();
282 m_count.Clear();
283 m_has_gdb_format = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000284}