1//===-- OptionValue.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/OptionValue.h"
10#include "lldb/Interpreter/OptionValues.h"
11#include "lldb/Utility/StringList.h"
12
13#include <memory>
14
15using namespace lldb;
16using namespace lldb_private;
17
18OptionValue::OptionValue(const OptionValue &other) {
19 std::lock_guard<std::mutex> lock(other.m_mutex);
20
21 m_parent_wp = other.m_parent_wp;
22 m_callback = other.m_callback;
23 m_value_was_set = other.m_value_was_set;
24
25}
26
27OptionValue& OptionValue::operator=(const OptionValue &other) {
28 std::scoped_lock<std::mutex, std::mutex> lock(m_mutex, other.m_mutex);
29
30 m_parent_wp = other.m_parent_wp;
31 m_callback = other.m_callback;
32 m_value_was_set = other.m_value_was_set;
33
34 return *this;
35}
36
37Status OptionValue::SetSubValue(const ExecutionContext *exe_ctx,
38 VarSetOperationType op, llvm::StringRef name,
39 llvm::StringRef value) {
40 Status error;
41 error.SetErrorString("SetSubValue is not supported");
42 return error;
43}
44
45OptionValueBoolean *OptionValue::GetAsBoolean() {
46 if (GetType() == OptionValue::eTypeBoolean)
47 return static_cast<OptionValueBoolean *>(this);
48 return nullptr;
49}
50
51const OptionValueBoolean *OptionValue::GetAsBoolean() const {
52 if (GetType() == OptionValue::eTypeBoolean)
53 return static_cast<const OptionValueBoolean *>(this);
54 return nullptr;
55}
56
57const OptionValueChar *OptionValue::GetAsChar() const {
58 if (GetType() == OptionValue::eTypeChar)
59 return static_cast<const OptionValueChar *>(this);
60 return nullptr;
61}
62
63OptionValueChar *OptionValue::GetAsChar() {
64 if (GetType() == OptionValue::eTypeChar)
65 return static_cast<OptionValueChar *>(this);
66 return nullptr;
67}
68
69OptionValueFileSpec *OptionValue::GetAsFileSpec() {
70 if (GetType() == OptionValue::eTypeFileSpec)
71 return static_cast<OptionValueFileSpec *>(this);
72 return nullptr;
73}
74
75const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {
76 if (GetType() == OptionValue::eTypeFileSpec)
77 return static_cast<const OptionValueFileSpec *>(this);
78 return nullptr;
79}
80
81OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {
82 if (GetType() == OptionValue::eTypeFileSpecList)
83 return static_cast<OptionValueFileSpecList *>(this);
84 return nullptr;
85}
86
87const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {
88 if (GetType() == OptionValue::eTypeFileSpecList)
89 return static_cast<const OptionValueFileSpecList *>(this);
90 return nullptr;
91}
92
93OptionValueArch *OptionValue::GetAsArch() {
94 if (GetType() == OptionValue::eTypeArch)
95 return static_cast<OptionValueArch *>(this);
96 return nullptr;
97}
98
99const OptionValueArch *OptionValue::GetAsArch() const {
100 if (GetType() == OptionValue::eTypeArch)
101 return static_cast<const OptionValueArch *>(this);
102 return nullptr;
103}
104
105OptionValueArray *OptionValue::GetAsArray() {
106 if (GetType() == OptionValue::eTypeArray)
107 return static_cast<OptionValueArray *>(this);
108 return nullptr;
109}
110
111const OptionValueArray *OptionValue::GetAsArray() const {
112 if (GetType() == OptionValue::eTypeArray)
113 return static_cast<const OptionValueArray *>(this);
114 return nullptr;
115}
116
117OptionValueArgs *OptionValue::GetAsArgs() {
118 if (GetType() == OptionValue::eTypeArgs)
119 return static_cast<OptionValueArgs *>(this);
120 return nullptr;
121}
122
123const OptionValueArgs *OptionValue::GetAsArgs() const {
124 if (GetType() == OptionValue::eTypeArgs)
125 return static_cast<const OptionValueArgs *>(this);
126 return nullptr;
127}
128
129OptionValueDictionary *OptionValue::GetAsDictionary() {
130 if (GetType() == OptionValue::eTypeDictionary)
131 return static_cast<OptionValueDictionary *>(this);
132 return nullptr;
133}
134
135const OptionValueDictionary *OptionValue::GetAsDictionary() const {
136 if (GetType() == OptionValue::eTypeDictionary)
137 return static_cast<const OptionValueDictionary *>(this);
138 return nullptr;
139}
140
141OptionValueEnumeration *OptionValue::GetAsEnumeration() {
142 if (GetType() == OptionValue::eTypeEnum)
143 return static_cast<OptionValueEnumeration *>(this);
144 return nullptr;
145}
146
147const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {
148 if (GetType() == OptionValue::eTypeEnum)
149 return static_cast<const OptionValueEnumeration *>(this);
150 return nullptr;
151}
152
153OptionValueFormat *OptionValue::GetAsFormat() {
154 if (GetType() == OptionValue::eTypeFormat)
155 return static_cast<OptionValueFormat *>(this);
156 return nullptr;
157}
158
159const OptionValueFormat *OptionValue::GetAsFormat() const {
160 if (GetType() == OptionValue::eTypeFormat)
161 return static_cast<const OptionValueFormat *>(this);
162 return nullptr;
163}
164
165OptionValueLanguage *OptionValue::GetAsLanguage() {
166 if (GetType() == OptionValue::eTypeLanguage)
167 return static_cast<OptionValueLanguage *>(this);
168 return nullptr;
169}
170
171const OptionValueLanguage *OptionValue::GetAsLanguage() const {
172 if (GetType() == OptionValue::eTypeLanguage)
173 return static_cast<const OptionValueLanguage *>(this);
174 return nullptr;
175}
176
177OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {
178 if (GetType() == OptionValue::eTypeFormatEntity)
179 return static_cast<OptionValueFormatEntity *>(this);
180 return nullptr;
181}
182
183const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {
184 if (GetType() == OptionValue::eTypeFormatEntity)
185 return static_cast<const OptionValueFormatEntity *>(this);
186 return nullptr;
187}
188
189OptionValuePathMappings *OptionValue::GetAsPathMappings() {
190 if (GetType() == OptionValue::eTypePathMap)
191 return static_cast<OptionValuePathMappings *>(this);
192 return nullptr;
193}
194
195const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {
196 if (GetType() == OptionValue::eTypePathMap)
197 return static_cast<const OptionValuePathMappings *>(this);
198 return nullptr;
199}
200
201OptionValueProperties *OptionValue::GetAsProperties() {
202 if (GetType() == OptionValue::eTypeProperties)
203 return static_cast<OptionValueProperties *>(this);
204 return nullptr;
205}
206
207const OptionValueProperties *OptionValue::GetAsProperties() const {
208 if (GetType() == OptionValue::eTypeProperties)
209 return static_cast<const OptionValueProperties *>(this);
210 return nullptr;
211}
212
213OptionValueRegex *OptionValue::GetAsRegex() {
214 if (GetType() == OptionValue::eTypeRegex)
215 return static_cast<OptionValueRegex *>(this);
216 return nullptr;
217}
218
219const OptionValueRegex *OptionValue::GetAsRegex() const {
220 if (GetType() == OptionValue::eTypeRegex)
221 return static_cast<const OptionValueRegex *>(this);
222 return nullptr;
223}
224
225OptionValueSInt64 *OptionValue::GetAsSInt64() {
226 if (GetType() == OptionValue::eTypeSInt64)
227 return static_cast<OptionValueSInt64 *>(this);
228 return nullptr;
229}
230
231const OptionValueSInt64 *OptionValue::GetAsSInt64() const {
232 if (GetType() == OptionValue::eTypeSInt64)
233 return static_cast<const OptionValueSInt64 *>(this);
234 return nullptr;
235}
236
237OptionValueString *OptionValue::GetAsString() {
238 if (GetType() == OptionValue::eTypeString)
239 return static_cast<OptionValueString *>(this);
240 return nullptr;
241}
242
243const OptionValueString *OptionValue::GetAsString() const {
244 if (GetType() == OptionValue::eTypeString)
245 return static_cast<const OptionValueString *>(this);
246 return nullptr;
247}
248
249OptionValueUInt64 *OptionValue::GetAsUInt64() {
250 if (GetType() == OptionValue::eTypeUInt64)
251 return static_cast<OptionValueUInt64 *>(this);
252 return nullptr;
253}
254
255const OptionValueUInt64 *OptionValue::GetAsUInt64() const {
256 if (GetType() == OptionValue::eTypeUInt64)
257 return static_cast<const OptionValueUInt64 *>(this);
258 return nullptr;
259}
260
261OptionValueUUID *OptionValue::GetAsUUID() {
262 if (GetType() == OptionValue::eTypeUUID)
263 return static_cast<OptionValueUUID *>(this);
264 return nullptr;
265}
266
267const OptionValueUUID *OptionValue::GetAsUUID() const {
268 if (GetType() == OptionValue::eTypeUUID)
269 return static_cast<const OptionValueUUID *>(this);
270 return nullptr;
271}
272
273std::optional<bool> OptionValue::GetBooleanValue() const {
274 std::lock_guard<std::mutex> lock(m_mutex);
275 if (const OptionValueBoolean *option_value = GetAsBoolean())
276 return option_value->GetCurrentValue();
277 return {};
278}
279
280bool OptionValue::SetBooleanValue(bool new_value) {
281 std::lock_guard<std::mutex> lock(m_mutex);
282 if (OptionValueBoolean *option_value = GetAsBoolean()) {
283 option_value->SetCurrentValue(new_value);
284 return true;
285 }
286 return false;
287}
288
289std::optional<char> OptionValue::GetCharValue() const {
290 std::lock_guard<std::mutex> lock(m_mutex);
291 if (const OptionValueChar *option_value = GetAsChar())
292 return option_value->GetCurrentValue();
293 return {};
294}
295
296bool OptionValue::SetCharValue(char new_value) {
297 std::lock_guard<std::mutex> lock(m_mutex);
298 if (OptionValueChar *option_value = GetAsChar()) {
299 option_value->SetCurrentValue(new_value);
300 return true;
301 }
302 return false;
303}
304
305std::optional<int64_t> OptionValue::GetEnumerationValue() const {
306 std::lock_guard<std::mutex> lock(m_mutex);
307 if (const OptionValueEnumeration *option_value = GetAsEnumeration())
308 return option_value->GetCurrentValue();
309 return {};
310}
311
312bool OptionValue::SetEnumerationValue(int64_t value) {
313 std::lock_guard<std::mutex> lock(m_mutex);
314 if (OptionValueEnumeration *option_value = GetAsEnumeration()) {
315 option_value->SetCurrentValue(value);
316 return true;
317 }
318 return false;
319}
320
321std::optional<FileSpec> OptionValue::GetFileSpecValue() const {
322 std::lock_guard<std::mutex> lock(m_mutex);
323 if (const OptionValueFileSpec *option_value = GetAsFileSpec())
324 return option_value->GetCurrentValue();
325 return {};
326}
327
328bool OptionValue::SetFileSpecValue(FileSpec file_spec) {
329 std::lock_guard<std::mutex> lock(m_mutex);
330 if (OptionValueFileSpec *option_value = GetAsFileSpec()) {
331 option_value->SetCurrentValue(value: file_spec, set_value_was_set: false);
332 return true;
333 }
334 return false;
335}
336
337bool OptionValue::AppendFileSpecValue(FileSpec file_spec) {
338 std::lock_guard<std::mutex> lock(m_mutex);
339 if (OptionValueFileSpecList *option_value = GetAsFileSpecList()) {
340 option_value->AppendCurrentValue(value: file_spec);
341 return true;
342 }
343 return false;
344}
345
346std::optional<FileSpecList> OptionValue::GetFileSpecListValue() const {
347 std::lock_guard<std::mutex> lock(m_mutex);
348 if (const OptionValueFileSpecList *option_value = GetAsFileSpecList())
349 return option_value->GetCurrentValue();
350 return {};
351}
352
353std::optional<lldb::Format> OptionValue::GetFormatValue() const {
354 std::lock_guard<std::mutex> lock(m_mutex);
355 if (const OptionValueFormat *option_value = GetAsFormat())
356 return option_value->GetCurrentValue();
357 return {};
358}
359
360bool OptionValue::SetFormatValue(lldb::Format new_value) {
361 std::lock_guard<std::mutex> lock(m_mutex);
362 if (OptionValueFormat *option_value = GetAsFormat()) {
363 option_value->SetCurrentValue(new_value);
364 return true;
365 }
366 return false;
367}
368
369std::optional<lldb::LanguageType> OptionValue::GetLanguageValue() const {
370 std::lock_guard<std::mutex> lock(m_mutex);
371 if (const OptionValueLanguage *option_value = GetAsLanguage())
372 return option_value->GetCurrentValue();
373 return {};
374}
375
376bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) {
377 std::lock_guard<std::mutex> lock(m_mutex);
378 if (OptionValueLanguage *option_value = GetAsLanguage()) {
379 option_value->SetCurrentValue(new_language);
380 return true;
381 }
382 return false;
383}
384
385const FormatEntity::Entry *OptionValue::GetFormatEntity() const {
386 std::lock_guard<std::mutex> lock(m_mutex);
387 if (const OptionValueFormatEntity *option_value = GetAsFormatEntity())
388 return &option_value->GetCurrentValue();
389 return nullptr;
390}
391
392const RegularExpression *OptionValue::GetRegexValue() const {
393 std::lock_guard<std::mutex> lock(m_mutex);
394 if (const OptionValueRegex *option_value = GetAsRegex())
395 return option_value->GetCurrentValue();
396 return nullptr;
397}
398
399std::optional<int64_t> OptionValue::GetSInt64Value() const {
400 std::lock_guard<std::mutex> lock(m_mutex);
401 if (const OptionValueSInt64 *option_value = GetAsSInt64())
402 return option_value->GetCurrentValue();
403 return {};
404}
405
406bool OptionValue::SetSInt64Value(int64_t new_value) {
407 std::lock_guard<std::mutex> lock(m_mutex);
408 if (OptionValueSInt64 *option_value = GetAsSInt64()) {
409 option_value->SetCurrentValue(new_value);
410 return true;
411 }
412 return false;
413}
414
415std::optional<llvm::StringRef> OptionValue::GetStringValue() const {
416 std::lock_guard<std::mutex> lock(m_mutex);
417 if (const OptionValueString *option_value = GetAsString())
418 return option_value->GetCurrentValueAsRef();
419 return {};
420}
421
422bool OptionValue::SetStringValue(llvm::StringRef new_value) {
423 std::lock_guard<std::mutex> lock(m_mutex);
424 if (OptionValueString *option_value = GetAsString()) {
425 option_value->SetCurrentValue(new_value);
426 return true;
427 }
428 return false;
429}
430
431std::optional<uint64_t> OptionValue::GetUInt64Value() const {
432 std::lock_guard<std::mutex> lock(m_mutex);
433 if (const OptionValueUInt64 *option_value = GetAsUInt64())
434 return option_value->GetCurrentValue();
435 return {};
436}
437
438bool OptionValue::SetUInt64Value(uint64_t new_value) {
439 std::lock_guard<std::mutex> lock(m_mutex);
440 if (OptionValueUInt64 *option_value = GetAsUInt64()) {
441 option_value->SetCurrentValue(new_value);
442 return true;
443 }
444 return false;
445}
446
447std::optional<UUID> OptionValue::GetUUIDValue() const {
448 std::lock_guard<std::mutex> lock(m_mutex);
449 if (const OptionValueUUID *option_value = GetAsUUID())
450 return option_value->GetCurrentValue();
451 return {};
452}
453
454bool OptionValue::SetUUIDValue(const UUID &uuid) {
455 std::lock_guard<std::mutex> lock(m_mutex);
456 if (OptionValueUUID *option_value = GetAsUUID()) {
457 option_value->SetCurrentValue(uuid);
458 return true;
459 }
460 return false;
461}
462
463std::optional<ArchSpec> OptionValue::GetArchSpecValue() const {
464 std::lock_guard<std::mutex> lock(m_mutex);
465 if (const OptionValueArch *option_value = GetAsArch())
466 return option_value->GetCurrentValue();
467 return {};
468}
469
470bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) {
471 std::lock_guard<std::mutex> lock(m_mutex);
472 if (OptionValueArch *option_value = GetAsArch()) {
473 option_value->SetCurrentValue(value: arch_spec, set_value_was_set: false);
474 return true;
475 }
476 return false;
477}
478
479const char *OptionValue::GetBuiltinTypeAsCString(Type t) {
480 switch (t) {
481 case eTypeInvalid:
482 return "invalid";
483 case eTypeArch:
484 return "arch";
485 case eTypeArgs:
486 return "arguments";
487 case eTypeArray:
488 return "array";
489 case eTypeBoolean:
490 return "boolean";
491 case eTypeChar:
492 return "char";
493 case eTypeDictionary:
494 return "dictionary";
495 case eTypeEnum:
496 return "enum";
497 case eTypeFileLineColumn:
498 return "file:line:column specifier";
499 case eTypeFileSpec:
500 return "file";
501 case eTypeFileSpecList:
502 return "file-list";
503 case eTypeFormat:
504 return "format";
505 case eTypeFormatEntity:
506 return "format-string";
507 case eTypeLanguage:
508 return "language";
509 case eTypePathMap:
510 return "path-map";
511 case eTypeProperties:
512 return "properties";
513 case eTypeRegex:
514 return "regex";
515 case eTypeSInt64:
516 return "int";
517 case eTypeString:
518 return "string";
519 case eTypeUInt64:
520 return "unsigned";
521 case eTypeUUID:
522 return "uuid";
523 }
524 return nullptr;
525}
526
527lldb::OptionValueSP OptionValue::CreateValueFromCStringForTypeMask(
528 const char *value_cstr, uint32_t type_mask, Status &error) {
529 // If only 1 bit is set in the type mask for a dictionary or array then we
530 // know how to decode a value from a cstring
531 lldb::OptionValueSP value_sp;
532 switch (type_mask) {
533 case 1u << eTypeArch:
534 value_sp = std::make_shared<OptionValueArch>();
535 break;
536 case 1u << eTypeBoolean:
537 value_sp = std::make_shared<OptionValueBoolean>(args: false);
538 break;
539 case 1u << eTypeChar:
540 value_sp = std::make_shared<OptionValueChar>(args: '\0');
541 break;
542 case 1u << eTypeFileSpec:
543 value_sp = std::make_shared<OptionValueFileSpec>();
544 break;
545 case 1u << eTypeFormat:
546 value_sp = std::make_shared<OptionValueFormat>(args: eFormatInvalid);
547 break;
548 case 1u << eTypeFormatEntity:
549 value_sp = std::make_shared<OptionValueFormatEntity>(args: nullptr);
550 break;
551 case 1u << eTypeLanguage:
552 value_sp = std::make_shared<OptionValueLanguage>(args: eLanguageTypeUnknown);
553 break;
554 case 1u << eTypeSInt64:
555 value_sp = std::make_shared<OptionValueSInt64>();
556 break;
557 case 1u << eTypeString:
558 value_sp = std::make_shared<OptionValueString>();
559 break;
560 case 1u << eTypeUInt64:
561 value_sp = std::make_shared<OptionValueUInt64>();
562 break;
563 case 1u << eTypeUUID:
564 value_sp = std::make_shared<OptionValueUUID>();
565 break;
566 }
567
568 if (value_sp)
569 error = value_sp->SetValueFromString(value: value_cstr, op: eVarSetOperationAssign);
570 else
571 error.SetErrorString("unsupported type mask");
572 return value_sp;
573}
574
575bool OptionValue::DumpQualifiedName(Stream &strm) const {
576 bool dumped_something = false;
577 lldb::OptionValueSP m_parent_sp(m_parent_wp.lock());
578 if (m_parent_sp) {
579 if (m_parent_sp->DumpQualifiedName(strm))
580 dumped_something = true;
581 }
582 llvm::StringRef name(GetName());
583 if (!name.empty()) {
584 if (dumped_something)
585 strm.PutChar(ch: '.');
586 else
587 dumped_something = true;
588 strm << name;
589 }
590 return dumped_something;
591}
592
593OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const {
594 auto clone = Clone();
595 clone->SetParent(new_parent);
596 return clone;
597}
598
599void OptionValue::AutoComplete(CommandInterpreter &interpreter,
600 CompletionRequest &request) {}
601
602Status OptionValue::SetValueFromString(llvm::StringRef value,
603 VarSetOperationType op) {
604 Status error;
605 switch (op) {
606 case eVarSetOperationReplace:
607 error.SetErrorStringWithFormat(
608 "%s objects do not support the 'replace' operation",
609 GetTypeAsCString());
610 break;
611 case eVarSetOperationInsertBefore:
612 error.SetErrorStringWithFormat(
613 "%s objects do not support the 'insert-before' operation",
614 GetTypeAsCString());
615 break;
616 case eVarSetOperationInsertAfter:
617 error.SetErrorStringWithFormat(
618 "%s objects do not support the 'insert-after' operation",
619 GetTypeAsCString());
620 break;
621 case eVarSetOperationRemove:
622 error.SetErrorStringWithFormat(
623 "%s objects do not support the 'remove' operation", GetTypeAsCString());
624 break;
625 case eVarSetOperationAppend:
626 error.SetErrorStringWithFormat(
627 "%s objects do not support the 'append' operation", GetTypeAsCString());
628 break;
629 case eVarSetOperationClear:
630 error.SetErrorStringWithFormat(
631 "%s objects do not support the 'clear' operation", GetTypeAsCString());
632 break;
633 case eVarSetOperationAssign:
634 error.SetErrorStringWithFormat(
635 "%s objects do not support the 'assign' operation", GetTypeAsCString());
636 break;
637 case eVarSetOperationInvalid:
638 error.SetErrorStringWithFormat("invalid operation performed on a %s object",
639 GetTypeAsCString());
640 break;
641 }
642 return error;
643}
644

source code of lldb/source/Interpreter/OptionValue.cpp