blob: c97d16ad9865245678518621733c330dbf4ec753 [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
Zachary Turner1f0f5b52016-09-22 20:22:55 +000050llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {
Zachary Turner70602432016-09-22 21:06:13 +000051 auto result = llvm::makeArrayRef(g_option_table);
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
53 if (m_count.GetDefaultValue() < UINT64_MAX)
Zachary Turner1f0f5b52016-09-22 20:22:55 +000054 return result;
Kate Stoneb9c1b512016-09-06 20:57:50 +000055 else
Zachary Turner1f0f5b52016-09-22 20:22:55 +000056 return result.take_front(3);
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 }
Zachary Turner1f0f5b52016-09-22 20:22:55 +000058 return result.take_front(2);
Kate Stoneb9c1b512016-09-06 20:57:50 +000059}
60
61Error OptionGroupFormat::SetOptionValue(uint32_t option_idx,
Zachary Turner8cef4b02016-09-23 17:48:13 +000062 llvm::StringRef option_arg,
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 ExecutionContext *execution_context) {
64 Error error;
65 const int short_option = g_option_table[option_idx].short_option;
66
67 switch (short_option) {
68 case 'f':
69 error = m_format.SetValueFromString(option_arg);
70 break;
71
72 case 'c':
73 if (m_count.GetDefaultValue() == 0) {
74 error.SetErrorString("--count option is disabled");
75 } else {
76 error = m_count.SetValueFromString(option_arg);
77 if (m_count.GetCurrentValue() == 0)
78 error.SetErrorStringWithFormat("invalid --count option value '%s'",
Zachary Turner8cef4b02016-09-23 17:48:13 +000079 option_arg.str().c_str());
Greg Clayton1deb7962011-10-25 06:44:01 +000080 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 break;
Greg Clayton84c39662011-04-27 22:04:39 +000082
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 case 's':
84 if (m_byte_size.GetDefaultValue() == 0) {
85 error.SetErrorString("--size option is disabled");
86 } else {
87 error = m_byte_size.SetValueFromString(option_arg);
88 if (m_byte_size.GetCurrentValue() == 0)
89 error.SetErrorStringWithFormat("invalid --size option value '%s'",
Zachary Turner8cef4b02016-09-23 17:48:13 +000090 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +000091 }
92 break;
Greg Clayton84c39662011-04-27 22:04:39 +000093
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 case 'G': {
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 uint64_t count = 0;
Zachary Turner8cef4b02016-09-23 17:48:13 +000096 llvm::StringRef gdb_format_str = option_arg;
97 gdb_format_str.consumeInteger(0, count);
Greg Clayton84c39662011-04-27 22:04:39 +000098
Kate Stoneb9c1b512016-09-06 20:57:50 +000099 Format format = eFormatDefault;
100 uint32_t byte_size = 0;
Greg Clayton84c39662011-04-27 22:04:39 +0000101
Zachary Turner8cef4b02016-09-23 17:48:13 +0000102 while (!gdb_format_str.empty() &&
103 ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 byte_size)) {
Zachary Turner8cef4b02016-09-23 17:48:13 +0000105 gdb_format_str = gdb_format_str.drop_front();
Greg Clayton86edbf42011-10-26 00:56:27 +0000106 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107
Zachary Turner8cef4b02016-09-23 17:48:13 +0000108 // We the first character of the "gdb_format_str" is not the
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 // NULL terminator, we didn't consume the entire string and
110 // something is wrong. Also, if none of the format, size or count
111 // was specified correctly, then abort.
Zachary Turner8cef4b02016-09-23 17:48:13 +0000112 if (!gdb_format_str.empty() ||
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113 (format == eFormatInvalid && byte_size == 0 && count == 0)) {
114 // Nothing got set correctly
115 error.SetErrorStringWithFormat("invalid gdb format string '%s'",
Zachary Turner8cef4b02016-09-23 17:48:13 +0000116 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000117 return error;
118 }
119
120 // At least one of the format, size or count was set correctly.
121 // Anything that wasn't set correctly should be set to the
122 // previous default
123 if (format == eFormatInvalid)
124 ParserGDBFormatLetter(execution_context, m_prev_gdb_format, format,
125 byte_size);
126
127 const bool byte_size_enabled = m_byte_size.GetDefaultValue() < UINT64_MAX;
128 const bool count_enabled = m_count.GetDefaultValue() < UINT64_MAX;
129 if (byte_size_enabled) {
130 // Byte size is enabled
131 if (byte_size == 0)
132 ParserGDBFormatLetter(execution_context, m_prev_gdb_size, format,
133 byte_size);
134 } else {
135 // Byte size is disabled, make sure it wasn't specified
136 // but if this is an address, it's actually necessary to
137 // specify one so don't error out
138 if (byte_size > 0 && format != lldb::eFormatAddressInfo) {
139 error.SetErrorString(
140 "this command doesn't support specifying a byte size");
141 return error;
142 }
143 }
144
145 if (count_enabled) {
146 // Count is enabled and was not set, set it to the default for gdb format
147 // statements (which is 1).
148 if (count == 0)
149 count = 1;
150 } else {
151 // Count is disabled, make sure it wasn't specified
152 if (count > 0) {
153 error.SetErrorString("this command doesn't support specifying a count");
154 return error;
155 }
156 }
157
158 m_format.SetCurrentValue(format);
159 m_format.SetOptionWasSet();
160 if (byte_size_enabled) {
161 m_byte_size.SetCurrentValue(byte_size);
162 m_byte_size.SetOptionWasSet();
163 }
164 if (count_enabled) {
165 m_count.SetCurrentValue(count);
166 m_count.SetOptionWasSet();
167 }
168 } break;
169
170 default:
171 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
172 break;
173 }
174
175 return error;
Greg Clayton86edbf42011-10-26 00:56:27 +0000176}
177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178bool OptionGroupFormat::ParserGDBFormatLetter(
179 ExecutionContext *execution_context, char format_letter, Format &format,
180 uint32_t &byte_size) {
181 m_has_gdb_format = true;
182 switch (format_letter) {
183 case 'o':
184 format = eFormatOctal;
185 m_prev_gdb_format = format_letter;
186 return true;
187 case 'x':
188 format = eFormatHex;
189 m_prev_gdb_format = format_letter;
190 return true;
191 case 'd':
192 format = eFormatDecimal;
193 m_prev_gdb_format = format_letter;
194 return true;
195 case 'u':
196 format = eFormatUnsigned;
197 m_prev_gdb_format = format_letter;
198 return true;
199 case 't':
200 format = eFormatBinary;
201 m_prev_gdb_format = format_letter;
202 return true;
203 case 'f':
204 format = eFormatFloat;
205 m_prev_gdb_format = format_letter;
206 return true;
207 case 'a':
208 format = eFormatAddressInfo;
209 {
210 TargetSP target_sp =
211 execution_context ? execution_context->GetTargetSP() : TargetSP();
212 if (target_sp)
213 byte_size = target_sp->GetArchitecture().GetAddressByteSize();
214 m_prev_gdb_format = format_letter;
215 return true;
216 }
217 case 'i':
218 format = eFormatInstruction;
219 m_prev_gdb_format = format_letter;
220 return true;
221 case 'c':
222 format = eFormatChar;
223 m_prev_gdb_format = format_letter;
224 return true;
225 case 's':
226 format = eFormatCString;
227 m_prev_gdb_format = format_letter;
228 return true;
229 case 'T':
230 format = eFormatOSType;
231 m_prev_gdb_format = format_letter;
232 return true;
233 case 'A':
234 format = eFormatHexFloat;
235 m_prev_gdb_format = format_letter;
236 return true;
237
238 // Size isn't used for printing instructions, so if a size is specified, and
239 // the previous format was
240 // 'i', then we should reset it to the default ('x'). Otherwise we'll
241 // continue to print as instructions,
242 // which isn't expected.
243 case 'b':
244 byte_size = 1;
245 LLVM_FALLTHROUGH;
246 case 'h':
247 byte_size = 2;
248 LLVM_FALLTHROUGH;
249 case 'w':
250 byte_size = 4;
251 LLVM_FALLTHROUGH;
252 case 'g':
253 byte_size = 8;
254
255 m_prev_gdb_size = format_letter;
256 if (m_prev_gdb_format == 'i')
257 m_prev_gdb_format = 'x';
258 return true;
259
260 break;
261 default:
262 break;
263 }
264 return false;
265}
266
267void OptionGroupFormat::OptionParsingStarting(
268 ExecutionContext *execution_context) {
269 m_format.Clear();
270 m_byte_size.Clear();
271 m_count.Clear();
272 m_has_gdb_format = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000273}