blob: b0565b706c5b1e02253c223bebff4c6277ce956d [file] [log] [blame]
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001//===-- OptionArgParser.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/OptionArgParser.h"
11#include "lldb/DataFormatters/FormatManager.h"
12#include "lldb/Target/Target.h"
13#include "lldb/Utility/Status.h"
14#include "lldb/Utility/StreamString.h"
15
16using namespace lldb_private;
17using namespace lldb;
18
19bool OptionArgParser::ToBoolean(llvm::StringRef ref, bool fail_value,
20 bool *success_ptr) {
21 if (success_ptr)
22 *success_ptr = true;
23 ref = ref.trim();
24 if (ref.equals_lower("false") || ref.equals_lower("off") ||
25 ref.equals_lower("no") || ref.equals_lower("0")) {
26 return false;
27 } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
28 ref.equals_lower("yes") || ref.equals_lower("1")) {
29 return true;
30 }
31 if (success_ptr)
32 *success_ptr = false;
33 return fail_value;
34}
35
36char OptionArgParser::ToChar(llvm::StringRef s, char fail_value,
37 bool *success_ptr) {
38 if (success_ptr)
39 *success_ptr = false;
40 if (s.size() != 1)
41 return fail_value;
42
43 if (success_ptr)
44 *success_ptr = true;
45 return s[0];
46}
47
48int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s,
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000049 const OptionEnumValues &enum_values,
Pavel Labath47cbf4a2018-04-10 09:03:59 +000050 int32_t fail_value, Status &error) {
51 error.Clear();
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000052 if (enum_values.empty()) {
Pavel Labath47cbf4a2018-04-10 09:03:59 +000053 error.SetErrorString("invalid enumeration argument");
54 return fail_value;
55 }
56
57 if (s.empty()) {
58 error.SetErrorString("empty enumeration string");
59 return fail_value;
60 }
61
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000062 for (const auto &enum_value : enum_values) {
63 llvm::StringRef this_enum(enum_value.string_value);
Pavel Labath47cbf4a2018-04-10 09:03:59 +000064 if (this_enum.startswith(s))
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000065 return enum_value.value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +000066 }
67
68 StreamString strm;
69 strm.PutCString("invalid enumeration value, valid values are: ");
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000070 bool is_first = true;
71 for (const auto &enum_value : enum_values) {
72 strm.Printf("%s\"%s\"",
73 is_first ? is_first = false,"" : ", ", enum_value.string_value);
Pavel Labath47cbf4a2018-04-10 09:03:59 +000074 }
75 error.SetErrorString(strm.GetString());
76 return fail_value;
77}
78
79Status OptionArgParser::ToFormat(const char *s, lldb::Format &format,
80 size_t *byte_size_ptr) {
81 format = eFormatInvalid;
82 Status error;
83
84 if (s && s[0]) {
85 if (byte_size_ptr) {
86 if (isdigit(s[0])) {
87 char *format_char = nullptr;
88 unsigned long byte_size = ::strtoul(s, &format_char, 0);
89 if (byte_size != ULONG_MAX)
90 *byte_size_ptr = byte_size;
91 s = format_char;
92 } else
93 *byte_size_ptr = 0;
94 }
95
96 const bool partial_match_ok = true;
97 if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
98 StreamString error_strm;
99 error_strm.Printf(
100 "Invalid format character or name '%s'. Valid values are:\n", s);
101 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
102 char format_char = FormatManager::GetFormatAsFormatChar(f);
103 if (format_char)
104 error_strm.Printf("'%c' or ", format_char);
105
106 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
107 error_strm.EOL();
108 }
109
110 if (byte_size_ptr)
111 error_strm.PutCString(
112 "An optional byte size can precede the format character.\n");
113 error.SetErrorString(error_strm.GetString());
114 }
115
116 if (error.Fail())
117 return error;
118 } else {
119 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
120 }
121 return error;
122}
123
124lldb::ScriptLanguage OptionArgParser::ToScriptLanguage(
125 llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr) {
126 if (success_ptr)
127 *success_ptr = true;
128
129 if (s.equals_lower("python"))
130 return eScriptLanguagePython;
131 if (s.equals_lower("default"))
132 return eScriptLanguageDefault;
133 if (s.equals_lower("none"))
134 return eScriptLanguageNone;
135
136 if (success_ptr)
137 *success_ptr = false;
138 return fail_value;
139}
140
141lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx,
142 llvm::StringRef s,
143 lldb::addr_t fail_value,
144 Status *error_ptr) {
145 bool error_set = false;
146 if (s.empty()) {
147 if (error_ptr)
148 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
149 s.str().c_str());
150 return fail_value;
151 }
152
153 llvm::StringRef sref = s;
154
155 lldb::addr_t addr = LLDB_INVALID_ADDRESS;
156 if (!s.getAsInteger(0, addr)) {
157 if (error_ptr)
158 error_ptr->Clear();
159 return addr;
160 }
161
162 // Try base 16 with no prefix...
163 if (!s.getAsInteger(16, addr)) {
164 if (error_ptr)
165 error_ptr->Clear();
166 return addr;
167 }
168
169 Target *target = nullptr;
170 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
171 if (error_ptr)
172 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
173 s.str().c_str());
174 return fail_value;
175 }
176
177 lldb::ValueObjectSP valobj_sp;
178 EvaluateExpressionOptions options;
179 options.SetCoerceToId(false);
180 options.SetUnwindOnError(true);
181 options.SetKeepInMemory(false);
182 options.SetTryAllThreads(true);
183
184 ExpressionResults expr_result =
185 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);
186
187 bool success = false;
188 if (expr_result == eExpressionCompleted) {
189 if (valobj_sp)
190 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
191 valobj_sp->GetDynamicValueType(), true);
192 // Get the address to watch.
193 if (valobj_sp)
194 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
195 if (success) {
196 if (error_ptr)
197 error_ptr->Clear();
198 return addr;
199 } else {
200 if (error_ptr) {
201 error_set = true;
202 error_ptr->SetErrorStringWithFormat(
203 "address expression \"%s\" resulted in a value whose type "
204 "can't be converted to an address: %s",
205 s.str().c_str(), valobj_sp->GetTypeName().GetCString());
206 }
207 }
208
209 } else {
Adrian Prantl05097242018-04-30 16:49:04 +0000210 // Since the compiler can't handle things like "main + 12" we should try to
211 // do this for now. The compiler doesn't like adding offsets to function
212 // pointer types.
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000213 static RegularExpression g_symbol_plus_offset_regex(
214 "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
215 RegularExpression::Match regex_match(3);
216 if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
217 uint64_t offset = 0;
218 bool add = true;
219 std::string name;
220 std::string str;
221 if (regex_match.GetMatchAtIndex(s, 1, name)) {
222 if (regex_match.GetMatchAtIndex(s, 2, str)) {
223 add = str[0] == '+';
224
225 if (regex_match.GetMatchAtIndex(s, 3, str)) {
226 if (!llvm::StringRef(str).getAsInteger(0, offset)) {
227 Status error;
228 addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS,
229 &error);
230 if (addr != LLDB_INVALID_ADDRESS) {
231 if (add)
232 return addr + offset;
233 else
234 return addr - offset;
235 }
236 }
237 }
238 }
239 }
240 }
241
242 if (error_ptr) {
243 error_set = true;
244 error_ptr->SetErrorStringWithFormat(
245 "address expression \"%s\" evaluation failed", s.str().c_str());
246 }
247 }
248
249 if (error_ptr) {
250 if (!error_set)
251 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
252 s.str().c_str());
253 }
254 return fail_value;
255}