Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp
39587 views
1
//===-- OptionValueProperties.cpp -----------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "lldb/Interpreter/OptionValueProperties.h"
10
11
#include "lldb/Utility/Flags.h"
12
13
#include "lldb/Core/UserSettingsController.h"
14
#include "lldb/Interpreter/OptionValues.h"
15
#include "lldb/Interpreter/Property.h"
16
#include "lldb/Utility/Args.h"
17
#include "lldb/Utility/Stream.h"
18
#include "lldb/Utility/StringList.h"
19
20
using namespace lldb;
21
using namespace lldb_private;
22
23
OptionValueProperties::OptionValueProperties(llvm::StringRef name)
24
: m_name(name.str()) {}
25
26
void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
27
for (const auto &definition : defs) {
28
Property property(definition);
29
assert(property.IsValid());
30
m_name_to_index.insert({property.GetName(), m_properties.size()});
31
property.GetValue()->SetParent(shared_from_this());
32
m_properties.push_back(property);
33
}
34
}
35
36
void OptionValueProperties::SetValueChangedCallback(
37
size_t property_idx, std::function<void()> callback) {
38
Property *property = ProtectedGetPropertyAtIndex(property_idx);
39
if (property)
40
property->SetValueChangedCallback(std::move(callback));
41
}
42
43
void OptionValueProperties::AppendProperty(llvm::StringRef name,
44
llvm::StringRef desc, bool is_global,
45
const OptionValueSP &value_sp) {
46
Property property(name, desc, is_global, value_sp);
47
m_name_to_index.insert({name, m_properties.size()});
48
m_properties.push_back(property);
49
value_sp->SetParent(shared_from_this());
50
}
51
52
lldb::OptionValueSP
53
OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
54
llvm::StringRef key) const {
55
auto iter = m_name_to_index.find(key);
56
if (iter == m_name_to_index.end())
57
return OptionValueSP();
58
const size_t idx = iter->second;
59
if (idx >= m_properties.size())
60
return OptionValueSP();
61
return GetPropertyAtIndex(idx, exe_ctx)->GetValue();
62
}
63
64
lldb::OptionValueSP
65
OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
66
llvm::StringRef name, Status &error) const {
67
lldb::OptionValueSP value_sp;
68
if (name.empty())
69
return OptionValueSP();
70
71
llvm::StringRef sub_name;
72
llvm::StringRef key;
73
size_t key_len = name.find_first_of(".[{");
74
if (key_len != llvm::StringRef::npos) {
75
key = name.take_front(key_len);
76
sub_name = name.drop_front(key_len);
77
} else
78
key = name;
79
80
value_sp = GetValueForKey(exe_ctx, key);
81
if (sub_name.empty() || !value_sp)
82
return value_sp;
83
84
switch (sub_name[0]) {
85
case '.': {
86
lldb::OptionValueSP return_val_sp;
87
return_val_sp =
88
value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), error);
89
if (!return_val_sp) {
90
if (Properties::IsSettingExperimental(sub_name.drop_front())) {
91
const size_t experimental_len =
92
Properties::GetExperimentalSettingsName().size();
93
if (sub_name[experimental_len + 1] == '.')
94
return_val_sp = value_sp->GetSubValue(
95
exe_ctx, sub_name.drop_front(experimental_len + 2), error);
96
// It isn't an error if an experimental setting is not present.
97
if (!return_val_sp)
98
error.Clear();
99
}
100
}
101
return return_val_sp;
102
}
103
case '[':
104
// Array or dictionary access for subvalues like: "[12]" -- access
105
// 12th array element "['hello']" -- dictionary access of key named hello
106
return value_sp->GetSubValue(exe_ctx, sub_name, error);
107
108
default:
109
value_sp.reset();
110
break;
111
}
112
return value_sp;
113
}
114
115
Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
116
VarSetOperationType op,
117
llvm::StringRef name,
118
llvm::StringRef value) {
119
Status error;
120
llvm::SmallVector<llvm::StringRef, 8> components;
121
name.split(components, '.');
122
bool name_contains_experimental = false;
123
for (const auto &part : components)
124
if (Properties::IsSettingExperimental(part))
125
name_contains_experimental = true;
126
127
lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, error));
128
if (value_sp)
129
error = value_sp->SetValueFromString(value, op);
130
else {
131
// Don't set an error if the path contained .experimental. - those are
132
// allowed to be missing and should silently fail.
133
if (!name_contains_experimental && error.AsCString() == nullptr) {
134
error.SetErrorStringWithFormat("invalid value path '%s'",
135
name.str().c_str());
136
}
137
}
138
return error;
139
}
140
141
size_t OptionValueProperties::GetPropertyIndex(llvm::StringRef name) const {
142
auto iter = m_name_to_index.find(name);
143
if (iter == m_name_to_index.end())
144
return SIZE_MAX;
145
return iter->second;
146
}
147
148
const Property *
149
OptionValueProperties::GetProperty(llvm::StringRef name,
150
const ExecutionContext *exe_ctx) const {
151
auto iter = m_name_to_index.find(name);
152
if (iter == m_name_to_index.end())
153
return nullptr;
154
return GetPropertyAtIndex(iter->second, exe_ctx);
155
}
156
157
lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
158
size_t idx, const ExecutionContext *exe_ctx) const {
159
const Property *setting = GetPropertyAtIndex(idx, exe_ctx);
160
if (setting)
161
return setting->GetValue();
162
return OptionValueSP();
163
}
164
165
OptionValuePathMappings *
166
OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
167
size_t idx, const ExecutionContext *exe_ctx) const {
168
OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
169
if (value_sp)
170
return value_sp->GetAsPathMappings();
171
return nullptr;
172
}
173
174
OptionValueFileSpecList *
175
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
176
size_t idx, const ExecutionContext *exe_ctx) const {
177
OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
178
if (value_sp)
179
return value_sp->GetAsFileSpecList();
180
return nullptr;
181
}
182
183
bool OptionValueProperties::GetPropertyAtIndexAsArgs(
184
size_t idx, Args &args, const ExecutionContext *exe_ctx) const {
185
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
186
if (!property)
187
return false;
188
189
OptionValue *value = property->GetValue().get();
190
if (!value)
191
return false;
192
193
const OptionValueArgs *arguments = value->GetAsArgs();
194
if (arguments) {
195
arguments->GetArgs(args);
196
return true;
197
}
198
199
const OptionValueArray *array = value->GetAsArray();
200
if (array) {
201
array->GetArgs(args);
202
return true;
203
}
204
205
const OptionValueDictionary *dict = value->GetAsDictionary();
206
if (dict) {
207
dict->GetArgs(args);
208
return true;
209
}
210
211
return false;
212
}
213
214
bool OptionValueProperties::SetPropertyAtIndexFromArgs(
215
size_t idx, const Args &args, const ExecutionContext *exe_ctx) {
216
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
217
if (!property)
218
return false;
219
220
OptionValue *value = property->GetValue().get();
221
if (!value)
222
return false;
223
224
OptionValueArgs *arguments = value->GetAsArgs();
225
if (arguments)
226
return arguments->SetArgs(args, eVarSetOperationAssign).Success();
227
228
OptionValueArray *array = value->GetAsArray();
229
if (array)
230
return array->SetArgs(args, eVarSetOperationAssign).Success();
231
232
OptionValueDictionary *dict = value->GetAsDictionary();
233
if (dict)
234
return dict->SetArgs(args, eVarSetOperationAssign).Success();
235
236
return false;
237
}
238
239
OptionValueDictionary *
240
OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
241
size_t idx, const ExecutionContext *exe_ctx) const {
242
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
243
if (property)
244
return property->GetValue()->GetAsDictionary();
245
return nullptr;
246
}
247
248
OptionValueFileSpec *
249
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
250
size_t idx, const ExecutionContext *exe_ctx) const {
251
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
252
if (property) {
253
OptionValue *value = property->GetValue().get();
254
if (value)
255
return value->GetAsFileSpec();
256
}
257
return nullptr;
258
}
259
260
OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
261
size_t idx, const ExecutionContext *exe_ctx) const {
262
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
263
if (property) {
264
OptionValue *value = property->GetValue().get();
265
if (value)
266
return value->GetAsSInt64();
267
}
268
return nullptr;
269
}
270
271
OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(
272
size_t idx, const ExecutionContext *exe_ctx) const {
273
const Property *property = GetPropertyAtIndex(idx, exe_ctx);
274
if (property) {
275
OptionValue *value = property->GetValue().get();
276
if (value)
277
return value->GetAsUInt64();
278
}
279
return nullptr;
280
}
281
282
OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
283
size_t idx, const ExecutionContext *exe_ctx) const {
284
OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
285
if (value_sp)
286
return value_sp->GetAsString();
287
return nullptr;
288
}
289
290
void OptionValueProperties::Clear() {
291
const size_t num_properties = m_properties.size();
292
for (size_t i = 0; i < num_properties; ++i)
293
m_properties[i].GetValue()->Clear();
294
}
295
296
Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
297
VarSetOperationType op) {
298
Status error;
299
300
// Args args(value_cstr);
301
// const size_t argc = args.GetArgumentCount();
302
switch (op) {
303
case eVarSetOperationClear:
304
Clear();
305
break;
306
307
case eVarSetOperationReplace:
308
case eVarSetOperationAssign:
309
case eVarSetOperationRemove:
310
case eVarSetOperationInsertBefore:
311
case eVarSetOperationInsertAfter:
312
case eVarSetOperationAppend:
313
case eVarSetOperationInvalid:
314
error = OptionValue::SetValueFromString(value, op);
315
break;
316
}
317
318
return error;
319
}
320
321
void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
322
Stream &strm, uint32_t dump_mask) {
323
const size_t num_properties = m_properties.size();
324
for (size_t i = 0; i < num_properties; ++i) {
325
const Property *property = GetPropertyAtIndex(i, exe_ctx);
326
if (property) {
327
OptionValue *option_value = property->GetValue().get();
328
assert(option_value);
329
const bool transparent_value = option_value->ValueIsTransparent();
330
property->Dump(exe_ctx, strm, dump_mask);
331
if (!transparent_value)
332
strm.EOL();
333
}
334
}
335
}
336
337
llvm::json::Value
338
OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) {
339
llvm::json::Object json_properties;
340
const size_t num_properties = m_properties.size();
341
for (size_t i = 0; i < num_properties; ++i) {
342
const Property *property = GetPropertyAtIndex(i, exe_ctx);
343
if (property) {
344
OptionValue *option_value = property->GetValue().get();
345
assert(option_value);
346
json_properties.try_emplace(property->GetName(),
347
option_value->ToJSON(exe_ctx));
348
}
349
}
350
return json_properties;
351
}
352
353
Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
354
Stream &strm,
355
llvm::StringRef property_path,
356
uint32_t dump_mask,
357
bool is_json) {
358
Status error;
359
lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, property_path, error));
360
if (value_sp) {
361
if (!value_sp->ValueIsTransparent()) {
362
if (dump_mask & eDumpOptionName)
363
strm.PutCString(property_path);
364
if (dump_mask & ~eDumpOptionName)
365
strm.PutChar(' ');
366
}
367
if (is_json) {
368
strm.Printf(
369
"%s",
370
llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
371
} else
372
value_sp->DumpValue(exe_ctx, strm, dump_mask);
373
}
374
return error;
375
}
376
377
OptionValuePropertiesSP
378
OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
379
auto global_props_sp = global_properties.GetValueProperties();
380
lldbassert(global_props_sp);
381
382
auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
383
return std::static_pointer_cast<OptionValueProperties>(copy_sp);
384
}
385
386
OptionValueSP
387
OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
388
auto copy_sp = OptionValue::DeepCopy(new_parent);
389
// copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
390
// types that override GetType returning a different value.
391
auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
392
lldbassert(props_value_ptr);
393
394
for (auto &property : props_value_ptr->m_properties) {
395
// Duplicate any values that are not global when constructing properties
396
// from a global copy.
397
if (!property.IsGlobal()) {
398
auto value_sp = property.GetValue()->DeepCopy(copy_sp);
399
property.SetOptionValue(value_sp);
400
}
401
}
402
return copy_sp;
403
}
404
405
const Property *
406
OptionValueProperties::GetPropertyAtPath(const ExecutionContext *exe_ctx,
407
llvm::StringRef name) const {
408
if (name.empty())
409
return nullptr;
410
411
const Property *property = nullptr;
412
llvm::StringRef sub_name;
413
llvm::StringRef key;
414
size_t key_len = name.find_first_of(".[{");
415
416
if (key_len != llvm::StringRef::npos) {
417
key = name.take_front(key_len);
418
sub_name = name.drop_front(key_len);
419
} else
420
key = name;
421
422
property = GetProperty(key, exe_ctx);
423
if (sub_name.empty() || !property)
424
return property;
425
426
if (sub_name[0] == '.') {
427
OptionValueProperties *sub_properties =
428
property->GetValue()->GetAsProperties();
429
if (sub_properties)
430
return sub_properties->GetPropertyAtPath(exe_ctx, sub_name.drop_front());
431
}
432
return nullptr;
433
}
434
435
void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
436
Stream &strm) const {
437
size_t max_name_len = 0;
438
const size_t num_properties = m_properties.size();
439
for (size_t i = 0; i < num_properties; ++i) {
440
const Property *property = ProtectedGetPropertyAtIndex(i);
441
if (property)
442
max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
443
}
444
for (size_t i = 0; i < num_properties; ++i) {
445
const Property *property = ProtectedGetPropertyAtIndex(i);
446
if (property)
447
property->DumpDescription(interpreter, strm, max_name_len, false);
448
}
449
}
450
451
void OptionValueProperties::Apropos(
452
llvm::StringRef keyword,
453
std::vector<const Property *> &matching_properties) const {
454
const size_t num_properties = m_properties.size();
455
StreamString strm;
456
for (size_t i = 0; i < num_properties; ++i) {
457
const Property *property = ProtectedGetPropertyAtIndex(i);
458
if (property) {
459
const OptionValueProperties *properties =
460
property->GetValue()->GetAsProperties();
461
if (properties) {
462
properties->Apropos(keyword, matching_properties);
463
} else {
464
bool match = false;
465
llvm::StringRef name = property->GetName();
466
if (name.contains_insensitive(keyword))
467
match = true;
468
else {
469
llvm::StringRef desc = property->GetDescription();
470
if (desc.contains_insensitive(keyword))
471
match = true;
472
}
473
if (match) {
474
matching_properties.push_back(property);
475
}
476
}
477
}
478
}
479
}
480
481
lldb::OptionValuePropertiesSP
482
OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
483
llvm::StringRef name) {
484
lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name));
485
if (option_value_sp) {
486
OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
487
if (ov_properties)
488
return ov_properties->shared_from_this();
489
}
490
return lldb::OptionValuePropertiesSP();
491
}
492
493