]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Interpreter/OptionGroupFormat.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Interpreter / OptionGroupFormat.cpp
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 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/ArchSpec.h"
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Target/ExecutionContext.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/Utils.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25 OptionGroupFormat::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') {}
32
33 OptionGroupFormat::~OptionGroupFormat() {}
34
35 static 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."},
48 };
49
50 llvm::ArrayRef<OptionDefinition> OptionGroupFormat::GetDefinitions() {
51   auto result = llvm::makeArrayRef(g_option_table);
52   if (m_byte_size.GetDefaultValue() < UINT64_MAX) {
53     if (m_count.GetDefaultValue() < UINT64_MAX)
54       return result;
55     else
56       return result.take_front(3);
57   }
58   return result.take_front(2);
59 }
60
61 Error OptionGroupFormat::SetOptionValue(uint32_t option_idx,
62                                         llvm::StringRef option_arg,
63                                         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'",
79                                        option_arg.str().c_str());
80     }
81     break;
82
83   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'",
90                                        option_arg.str().c_str());
91     }
92     break;
93
94   case 'G': {
95     uint64_t count = 0;
96     llvm::StringRef gdb_format_str = option_arg;
97     gdb_format_str.consumeInteger(0, count);
98
99     Format format = eFormatDefault;
100     uint32_t byte_size = 0;
101
102     while (!gdb_format_str.empty() &&
103            ParserGDBFormatLetter(execution_context, gdb_format_str[0], format,
104                                  byte_size)) {
105       gdb_format_str = gdb_format_str.drop_front();
106     }
107
108     // We the first character of the "gdb_format_str" is not the
109     // 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.
112     if (!gdb_format_str.empty() ||
113         (format == eFormatInvalid && byte_size == 0 && count == 0)) {
114       // Nothing got set correctly
115       error.SetErrorStringWithFormat("invalid gdb format string '%s'",
116                                      option_arg.str().c_str());
117       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;
176 }
177
178 bool 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
267 void 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;
273 }