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 
15 using namespace lldb;
16 using namespace lldb_private;
17 
OptionValue(const OptionValue & other)18 OptionValue::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 
operator =(const OptionValue & other)27 OptionValue& 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 
SetSubValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef name,llvm::StringRef value)37 Status 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 
GetAsBoolean()45 OptionValueBoolean *OptionValue::GetAsBoolean() {
46   if (GetType() == OptionValue::eTypeBoolean)
47     return static_cast<OptionValueBoolean *>(this);
48   return nullptr;
49 }
50 
GetAsBoolean() const51 const OptionValueBoolean *OptionValue::GetAsBoolean() const {
52   if (GetType() == OptionValue::eTypeBoolean)
53     return static_cast<const OptionValueBoolean *>(this);
54   return nullptr;
55 }
56 
GetAsChar() const57 const OptionValueChar *OptionValue::GetAsChar() const {
58   if (GetType() == OptionValue::eTypeChar)
59     return static_cast<const OptionValueChar *>(this);
60   return nullptr;
61 }
62 
GetAsChar()63 OptionValueChar *OptionValue::GetAsChar() {
64   if (GetType() == OptionValue::eTypeChar)
65     return static_cast<OptionValueChar *>(this);
66   return nullptr;
67 }
68 
GetAsFileSpec()69 OptionValueFileSpec *OptionValue::GetAsFileSpec() {
70   if (GetType() == OptionValue::eTypeFileSpec)
71     return static_cast<OptionValueFileSpec *>(this);
72   return nullptr;
73 }
74 
GetAsFileSpec() const75 const OptionValueFileSpec *OptionValue::GetAsFileSpec() const {
76   if (GetType() == OptionValue::eTypeFileSpec)
77     return static_cast<const OptionValueFileSpec *>(this);
78   return nullptr;
79 }
80 
GetAsFileSpecList()81 OptionValueFileSpecList *OptionValue::GetAsFileSpecList() {
82   if (GetType() == OptionValue::eTypeFileSpecList)
83     return static_cast<OptionValueFileSpecList *>(this);
84   return nullptr;
85 }
86 
GetAsFileSpecList() const87 const OptionValueFileSpecList *OptionValue::GetAsFileSpecList() const {
88   if (GetType() == OptionValue::eTypeFileSpecList)
89     return static_cast<const OptionValueFileSpecList *>(this);
90   return nullptr;
91 }
92 
GetAsArch()93 OptionValueArch *OptionValue::GetAsArch() {
94   if (GetType() == OptionValue::eTypeArch)
95     return static_cast<OptionValueArch *>(this);
96   return nullptr;
97 }
98 
GetAsArch() const99 const OptionValueArch *OptionValue::GetAsArch() const {
100   if (GetType() == OptionValue::eTypeArch)
101     return static_cast<const OptionValueArch *>(this);
102   return nullptr;
103 }
104 
GetAsArray()105 OptionValueArray *OptionValue::GetAsArray() {
106   if (GetType() == OptionValue::eTypeArray)
107     return static_cast<OptionValueArray *>(this);
108   return nullptr;
109 }
110 
GetAsArray() const111 const OptionValueArray *OptionValue::GetAsArray() const {
112   if (GetType() == OptionValue::eTypeArray)
113     return static_cast<const OptionValueArray *>(this);
114   return nullptr;
115 }
116 
GetAsArgs()117 OptionValueArgs *OptionValue::GetAsArgs() {
118   if (GetType() == OptionValue::eTypeArgs)
119     return static_cast<OptionValueArgs *>(this);
120   return nullptr;
121 }
122 
GetAsArgs() const123 const OptionValueArgs *OptionValue::GetAsArgs() const {
124   if (GetType() == OptionValue::eTypeArgs)
125     return static_cast<const OptionValueArgs *>(this);
126   return nullptr;
127 }
128 
GetAsDictionary()129 OptionValueDictionary *OptionValue::GetAsDictionary() {
130   if (GetType() == OptionValue::eTypeDictionary)
131     return static_cast<OptionValueDictionary *>(this);
132   return nullptr;
133 }
134 
GetAsDictionary() const135 const OptionValueDictionary *OptionValue::GetAsDictionary() const {
136   if (GetType() == OptionValue::eTypeDictionary)
137     return static_cast<const OptionValueDictionary *>(this);
138   return nullptr;
139 }
140 
GetAsEnumeration()141 OptionValueEnumeration *OptionValue::GetAsEnumeration() {
142   if (GetType() == OptionValue::eTypeEnum)
143     return static_cast<OptionValueEnumeration *>(this);
144   return nullptr;
145 }
146 
GetAsEnumeration() const147 const OptionValueEnumeration *OptionValue::GetAsEnumeration() const {
148   if (GetType() == OptionValue::eTypeEnum)
149     return static_cast<const OptionValueEnumeration *>(this);
150   return nullptr;
151 }
152 
GetAsFormat()153 OptionValueFormat *OptionValue::GetAsFormat() {
154   if (GetType() == OptionValue::eTypeFormat)
155     return static_cast<OptionValueFormat *>(this);
156   return nullptr;
157 }
158 
GetAsFormat() const159 const OptionValueFormat *OptionValue::GetAsFormat() const {
160   if (GetType() == OptionValue::eTypeFormat)
161     return static_cast<const OptionValueFormat *>(this);
162   return nullptr;
163 }
164 
GetAsLanguage()165 OptionValueLanguage *OptionValue::GetAsLanguage() {
166   if (GetType() == OptionValue::eTypeLanguage)
167     return static_cast<OptionValueLanguage *>(this);
168   return nullptr;
169 }
170 
GetAsLanguage() const171 const OptionValueLanguage *OptionValue::GetAsLanguage() const {
172   if (GetType() == OptionValue::eTypeLanguage)
173     return static_cast<const OptionValueLanguage *>(this);
174   return nullptr;
175 }
176 
GetAsFormatEntity()177 OptionValueFormatEntity *OptionValue::GetAsFormatEntity() {
178   if (GetType() == OptionValue::eTypeFormatEntity)
179     return static_cast<OptionValueFormatEntity *>(this);
180   return nullptr;
181 }
182 
GetAsFormatEntity() const183 const OptionValueFormatEntity *OptionValue::GetAsFormatEntity() const {
184   if (GetType() == OptionValue::eTypeFormatEntity)
185     return static_cast<const OptionValueFormatEntity *>(this);
186   return nullptr;
187 }
188 
GetAsPathMappings()189 OptionValuePathMappings *OptionValue::GetAsPathMappings() {
190   if (GetType() == OptionValue::eTypePathMap)
191     return static_cast<OptionValuePathMappings *>(this);
192   return nullptr;
193 }
194 
GetAsPathMappings() const195 const OptionValuePathMappings *OptionValue::GetAsPathMappings() const {
196   if (GetType() == OptionValue::eTypePathMap)
197     return static_cast<const OptionValuePathMappings *>(this);
198   return nullptr;
199 }
200 
GetAsProperties()201 OptionValueProperties *OptionValue::GetAsProperties() {
202   if (GetType() == OptionValue::eTypeProperties)
203     return static_cast<OptionValueProperties *>(this);
204   return nullptr;
205 }
206 
GetAsProperties() const207 const OptionValueProperties *OptionValue::GetAsProperties() const {
208   if (GetType() == OptionValue::eTypeProperties)
209     return static_cast<const OptionValueProperties *>(this);
210   return nullptr;
211 }
212 
GetAsRegex()213 OptionValueRegex *OptionValue::GetAsRegex() {
214   if (GetType() == OptionValue::eTypeRegex)
215     return static_cast<OptionValueRegex *>(this);
216   return nullptr;
217 }
218 
GetAsRegex() const219 const OptionValueRegex *OptionValue::GetAsRegex() const {
220   if (GetType() == OptionValue::eTypeRegex)
221     return static_cast<const OptionValueRegex *>(this);
222   return nullptr;
223 }
224 
GetAsSInt64()225 OptionValueSInt64 *OptionValue::GetAsSInt64() {
226   if (GetType() == OptionValue::eTypeSInt64)
227     return static_cast<OptionValueSInt64 *>(this);
228   return nullptr;
229 }
230 
GetAsSInt64() const231 const OptionValueSInt64 *OptionValue::GetAsSInt64() const {
232   if (GetType() == OptionValue::eTypeSInt64)
233     return static_cast<const OptionValueSInt64 *>(this);
234   return nullptr;
235 }
236 
GetAsString()237 OptionValueString *OptionValue::GetAsString() {
238   if (GetType() == OptionValue::eTypeString)
239     return static_cast<OptionValueString *>(this);
240   return nullptr;
241 }
242 
GetAsString() const243 const OptionValueString *OptionValue::GetAsString() const {
244   if (GetType() == OptionValue::eTypeString)
245     return static_cast<const OptionValueString *>(this);
246   return nullptr;
247 }
248 
GetAsUInt64()249 OptionValueUInt64 *OptionValue::GetAsUInt64() {
250   if (GetType() == OptionValue::eTypeUInt64)
251     return static_cast<OptionValueUInt64 *>(this);
252   return nullptr;
253 }
254 
GetAsUInt64() const255 const OptionValueUInt64 *OptionValue::GetAsUInt64() const {
256   if (GetType() == OptionValue::eTypeUInt64)
257     return static_cast<const OptionValueUInt64 *>(this);
258   return nullptr;
259 }
260 
GetAsUUID()261 OptionValueUUID *OptionValue::GetAsUUID() {
262   if (GetType() == OptionValue::eTypeUUID)
263     return static_cast<OptionValueUUID *>(this);
264   return nullptr;
265 }
266 
GetAsUUID() const267 const OptionValueUUID *OptionValue::GetAsUUID() const {
268   if (GetType() == OptionValue::eTypeUUID)
269     return static_cast<const OptionValueUUID *>(this);
270   return nullptr;
271 }
272 
GetBooleanValue() const273 std::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 
SetBooleanValue(bool new_value)280 bool 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 
GetCharValue() const289 std::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 
SetCharValue(char new_value)296 bool 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 
GetEnumerationValue() const305 std::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 
SetEnumerationValue(int64_t value)312 bool 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 
GetFileSpecValue() const321 std::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 
SetFileSpecValue(FileSpec file_spec)328 bool OptionValue::SetFileSpecValue(FileSpec file_spec) {
329   std::lock_guard<std::mutex> lock(m_mutex);
330   if (OptionValueFileSpec *option_value = GetAsFileSpec()) {
331     option_value->SetCurrentValue(file_spec, false);
332     return true;
333   }
334   return false;
335 }
336 
AppendFileSpecValue(FileSpec file_spec)337 bool OptionValue::AppendFileSpecValue(FileSpec file_spec) {
338   std::lock_guard<std::mutex> lock(m_mutex);
339   if (OptionValueFileSpecList *option_value = GetAsFileSpecList()) {
340     option_value->AppendCurrentValue(file_spec);
341     return true;
342   }
343   return false;
344 }
345 
GetFileSpecListValue() const346 std::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 
GetFormatValue() const353 std::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 
SetFormatValue(lldb::Format new_value)360 bool 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 
GetLanguageValue() const369 std::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 
SetLanguageValue(lldb::LanguageType new_language)376 bool 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 
GetFormatEntity() const385 const 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 
GetRegexValue() const392 const 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 
GetSInt64Value() const399 std::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 
SetSInt64Value(int64_t new_value)406 bool 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 
GetStringValue() const415 std::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 
SetStringValue(llvm::StringRef new_value)422 bool 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 
GetUInt64Value() const431 std::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 
SetUInt64Value(uint64_t new_value)438 bool 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 
GetUUIDValue() const447 std::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 
SetUUIDValue(const UUID & uuid)454 bool 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 
GetArchSpecValue() const463 std::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 
SetArchSpecValue(ArchSpec arch_spec)470 bool OptionValue::SetArchSpecValue(ArchSpec arch_spec) {
471     std::lock_guard<std::mutex> lock(m_mutex);
472   if (OptionValueArch *option_value = GetAsArch()) {
473     option_value->SetCurrentValue(arch_spec, false);
474     return true;
475   }
476   return false;
477 }
478 
GetBuiltinTypeAsCString(Type t)479 const 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 
CreateValueFromCStringForTypeMask(const char * value_cstr,uint32_t type_mask,Status & error)527 lldb::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>(false);
538     break;
539   case 1u << eTypeChar:
540     value_sp = std::make_shared<OptionValueChar>('\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>(eFormatInvalid);
547     break;
548   case 1u << eTypeFormatEntity:
549     value_sp = std::make_shared<OptionValueFormatEntity>(nullptr);
550     break;
551   case 1u << eTypeLanguage:
552     value_sp = std::make_shared<OptionValueLanguage>(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_cstr, eVarSetOperationAssign);
570   else
571     error.SetErrorString("unsupported type mask");
572   return value_sp;
573 }
574 
DumpQualifiedName(Stream & strm) const575 bool 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('.');
586     else
587       dumped_something = true;
588     strm << name;
589   }
590   return dumped_something;
591 }
592 
DeepCopy(const OptionValueSP & new_parent) const593 OptionValueSP OptionValue::DeepCopy(const OptionValueSP &new_parent) const {
594   auto clone = Clone();
595   clone->SetParent(new_parent);
596   return clone;
597 }
598 
AutoComplete(CommandInterpreter & interpreter,CompletionRequest & request)599 void OptionValue::AutoComplete(CommandInterpreter &interpreter,
600                                CompletionRequest &request) {}
601 
SetValueFromString(llvm::StringRef value,VarSetOperationType op)602 Status 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