blob: 9fd0c5c211ccc9dda07ce79d6681f1cab2436487 [file] [log] [blame]
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001//====-- UserSettingsController.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 <string.h>
11#include <algorithm>
12
13#include "lldb/Core/UserSettingsController.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Stream.h"
16#include "lldb/Core/StreamString.h"
17#include "lldb/Interpreter/CommandInterpreter.h"
18
19using namespace lldb_private;
20
21UserSettingsController::UserSettingsController (const char *level_name,
22 const lldb::UserSettingsControllerSP &parent) :
23 m_default_settings (),
24 m_settings (),
25 m_children (),
26 m_pending_settings (),
27 m_live_settings (),
28 m_children_mutex (Mutex::eMutexTypeNormal),
29 m_pending_settings_mutex (Mutex::eMutexTypeNormal),
30 m_live_settings_mutex (Mutex::eMutexTypeNormal)
31{
32 m_settings.parent = parent;
33 m_settings.level_name.SetCString (level_name);
34}
35
36UserSettingsController::~UserSettingsController ()
37{
38 m_live_settings.clear();
39}
40
41void
42UserSettingsController::InitializeGlobalVariables ()
43{
44 static bool global_initialized = false;
45 int num_entries;
46 const char *prefix = GetLevelName().AsCString();
47
48 if (! global_initialized)
49 {
50 num_entries = m_settings.global_settings.size();
51 for (int i = 0; i < num_entries; ++i)
52 {
53 SettingEntry &entry = m_settings.global_settings[i];
54 if (entry.default_value != NULL)
55 {
56 StreamString full_name;
57 if (prefix[0] != '\0')
58 full_name.Printf ("%s.%s", prefix, entry.var_name);
59 else
60 full_name.Printf ("%s", entry.var_name);
61 SetVariable (full_name.GetData(), entry.default_value, lldb::eVarSetOperationAssign, false);
62 }
63 else if ((entry.var_type == lldb::eSetVarTypeEnum)
64 && (entry.enum_values != NULL))
65 {
66 StreamString full_name;
67 if (prefix[0] != '\0')
68 full_name.Printf ("%s.%s", prefix, entry.var_name);
69 else
70 full_name.Printf ("%s", entry.var_name);
71 SetVariable (full_name.GetData(), entry.enum_values[0].string_value, lldb::eVarSetOperationAssign,
72 false);
73 }
74 }
75 global_initialized = true;
76 }
77}
78
79const lldb::UserSettingsControllerSP &
80UserSettingsController::GetParent ()
81{
82 return m_settings.parent;
83}
84
85void
86UserSettingsController::RegisterChild (const lldb::UserSettingsControllerSP &child)
87{
88 Mutex::Locker locker (m_children_mutex);
89
90 // Verify child is not already in m_children.
91 size_t num_children = m_children.size();
92 bool found = false;
93 for (size_t i = 0; i < num_children; ++i)
94 {
95 if (m_children[i].get() == child.get())
96 found = true;
97 }
98
99 // Add child to m_children.
100 if (! found)
101 m_children.push_back (child);
102}
103
104const ConstString &
105UserSettingsController::GetLevelName ()
106{
107 return m_settings.level_name;
108}
109
110size_t
111UserSettingsController::GetNumChildren ()
112{
113 return m_children.size();
114}
115
116const lldb::UserSettingsControllerSP
117UserSettingsController::GetChildAtIndex (size_t index)
118{
119 if (index < m_children.size())
120 return m_children[index];
121
122 lldb::UserSettingsControllerSP dummy_value;
123
124 return dummy_value;
125}
126
127const SettingEntry *
128UserSettingsController::GetGlobalEntry (const ConstString &var_name)
129{
130
131 for (int i = 0; i < m_settings.global_settings.size(); ++i)
132 {
133 SettingEntry &entry = m_settings.global_settings[i];
134 ConstString entry_name (entry.var_name);
135 if (entry_name == var_name)
136 return &entry;
137 }
138
139 return NULL;
140}
141
142const SettingEntry *
143UserSettingsController::GetInstanceEntry (const ConstString &const_var_name)
144{
145
146 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
147 {
148 SettingEntry &entry = m_settings.instance_settings[i];
149 ConstString entry_name (entry.var_name);
150 if (entry_name == const_var_name)
151 return &entry;
152 }
153
154 return NULL;
155}
156
157void
158UserSettingsController::BuildParentPrefix (std::string &parent_prefix)
159{
160 lldb::UserSettingsControllerSP parent = GetParent();
161 if (parent.get() != NULL)
162 {
163 parent->BuildParentPrefix (parent_prefix);
164 if (parent_prefix.length() > 0)
165 parent_prefix.append (".");
166 }
167 parent_prefix.append (GetLevelName().AsCString());
168}
169
170void
171UserSettingsController::RemoveChild (const lldb::UserSettingsControllerSP &child)
172{
173 Mutex::Locker locker (m_children_mutex);
174 std::vector<lldb::UserSettingsControllerSP>::iterator pos, end = m_children.end();
175
176 for (pos = m_children.begin(); pos != end; ++pos)
177 {
178 lldb::UserSettingsControllerSP entry = *pos;
179 if (entry == child)
180 {
181 m_children.erase (pos);
182 break;
183 }
184 }
185}
186
187Error
188UserSettingsController::SetVariable (const char *full_dot_name,
189 const char *value,
190 const lldb::VarSetOperationType op,
191 const bool override,
192 const char *index_value)
193{
194 Error err;
195 ConstString const_var_name;
196 const ConstString &default_name = InstanceSettings::GetDefaultName();
197
198 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
199 int num_pieces = names.GetArgumentCount();
200
201 if (num_pieces < 1)
202 {
203 err.SetErrorStringWithFormat ("'%s' is not a valid variable name; cannot assign value.\n", full_dot_name);
204 return err;
205 }
206
207 ConstString prefix (names.GetArgumentAtIndex (0));
208
209 if ((prefix == m_settings.level_name)
210 || (m_settings.level_name.GetLength() == 0))
211 {
212
213 if (prefix == m_settings.level_name)
214 {
215 names.Shift ();
216 num_pieces = names.GetArgumentCount();
217 }
218
219 if (num_pieces == 0)
220 {
221 err.SetErrorString ("No variable name specified; cannot assign value.\n");
222 return err;
223 }
224 else if (num_pieces == 1)
225 {
226
227 // Must be one of the class-wide settings.
228
229 const_var_name.SetCString (names.GetArgumentAtIndex (0));
230 const SettingEntry *entry = GetGlobalEntry (const_var_name);
231 if (entry)
232 {
233 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
234
235 if (err.Fail())
236 return err;
237
238 if ((value == NULL || value[0] == '\0')
239 && (op == lldb::eVarSetOperationAssign))
240 {
241 if (entry->var_type != lldb::eSetVarTypeEnum)
242 value = entry->default_value;
243 else
244 value = entry->enum_values[0].string_value;
245 }
246 UpdateGlobalVariable (const_var_name, index_value, value, *entry, op, err);
247 }
248 else
249 {
250 // MIGHT be instance variable, to be for ALL instances.
251
252 entry = GetInstanceEntry (const_var_name);
253 if (entry == NULL)
254 {
255 err.SetErrorStringWithFormat ("Unable to find variable '%s.%s'; cannot assign value.\n",
256 prefix.AsCString(), const_var_name.AsCString());
257 return err;
258 }
259 else
260 {
261 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
262
263 if (err.Fail())
264 return err;
265
266 if ((value == NULL || value[0] == '\0')
267 && (op == lldb::eVarSetOperationAssign))
268 {
269 if (entry->var_type != lldb::eSetVarTypeEnum)
270 value = entry->default_value;
271 else
272 value = entry->enum_values[0].string_value;
273 }
274
275 m_default_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
276 default_name, *entry, op, err, true);
277 if (override)
278 {
279 OverrideAllInstances (const_var_name, value, op, index_value, err);
280
281 // Update all pending records as well.
282 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos, end = m_pending_settings.end();
283 for (pos = m_pending_settings.begin(); pos != end; end++)
284 {
285 const ConstString instance_name (pos->first.c_str());
286 lldb::InstanceSettingsSP setting_sp = pos->second;
287 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
288 instance_name, *entry, op, err, true);
289 }
290 }
291 }
292 }
293 }
294 else
295 {
296 // Either a child's setting or an instance setting.
297
298 if (names.GetArgumentAtIndex(0)[0] == '[')
299 {
300 // An instance setting. Supposedly.
301
302 ConstString instance_name (names.GetArgumentAtIndex (0));
303
304 // First verify that there is only one more name.
305
306 names.Shift();
307
308 if (names.GetArgumentCount() != 1)
309 {
310 err.SetErrorStringWithFormat ("Invalid variable name format '%s'; cannot assign value.\n",
311 full_dot_name);
312 return err;
313 }
314
315 // Next verify that it is a valid instance setting name.
316
317 const_var_name.SetCString (names.GetArgumentAtIndex (0));
318 const SettingEntry *entry = GetInstanceEntry (const_var_name);
319
320 if (entry == NULL)
321 {
322 err.SetErrorStringWithFormat ("Unknown instance variable '%s'; cannot assign value.\n",
323 const_var_name.AsCString());
324 return err;
325 }
326
327 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
328
329 if (err.Fail())
330 return err;
331
332 if ((value == NULL || value[0] == '\0')
333 && (op == lldb::eVarSetOperationAssign))
334 {
335 if (entry->var_type != lldb::eSetVarTypeEnum)
336 value = entry->default_value;
337 else
338 value = entry->enum_values[0].string_value;
339 }
340
341 // Now look for existing instance with given instance name; if not found, find or create pending
342 // setting for instance with given name.
343
344 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
345
346 if (current_settings != NULL)
347 {
348 current_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
349 instance_name, *entry, op, err, false);
350
351 }
352 else
353 {
354 // Instance does not currently exist; make or update a pending setting for it.
355 lldb::InstanceSettingsSP current_settings_sp = PendingSettingsForInstance (instance_name);
356
357 // Now we have a settings record, update it appropriately.
358
359 current_settings_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
360 instance_name, *entry, op, err, true);
361
362 { // Scope for mutex.
363 Mutex::Locker locker (m_pending_settings_mutex);
364 m_pending_settings[instance_name.AsCString()] = current_settings_sp;
365 }
366
367 if (override)
368 {
369 OverrideAllInstances (const_var_name, value, op, index_value, err);
370
371 // Update all pending records as well.
372 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
373 std::map<std::string, lldb::InstanceSettingsSP>::iterator end = m_pending_settings.end();
374 for (pos = m_pending_settings.begin(); pos != end; end++)
375 {
376 const ConstString tmp_inst_name (pos->first.c_str());
377 lldb::InstanceSettingsSP setting_sp = pos->second;
378 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
379 tmp_inst_name, *entry, op, err, true);
380 }
381 }
382 }
383 }
384 else
385 {
386 // A child setting.
387 lldb::UserSettingsControllerSP child;
388 ConstString child_prefix (names.GetArgumentAtIndex (0));
389 int num_children = GetNumChildren();
390 bool found = false;
391 for (int i = 0; i < num_children && !found; ++i)
392 {
393 child = GetChildAtIndex (i);
394 ConstString current_prefix = child->GetLevelName();
395 if (current_prefix == child_prefix)
396 {
397 found = true;
398 std::string new_name;
399 for (int j = 0; j < names.GetArgumentCount(); ++j)
400 {
401 if (j > 0)
402 new_name += '.';
403 new_name += names.GetArgumentAtIndex (j);
404 }
405 return child->SetVariable (new_name.c_str(), value, op, override, index_value);
406 }
407 }
408 if (!found)
409 {
410 err.SetErrorStringWithFormat ("Unable to find variable '%s'; cannot assign value.\n",
411 full_dot_name);
412 return err;
413 }
414 }
415 }
416 }
417 else
418 {
419 err.SetErrorStringWithFormat ("'%s' is not a valid level name; was expecting '%s'. Cannot assign value.\n",
420 prefix.AsCString(), m_settings.level_name.AsCString());
421 }
422
423 return err;
424}
425
426StringList
427UserSettingsController::GetVariable (const char *full_dot_name, lldb::SettableVariableType &var_type)
428{
429 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
430 ConstString const_var_name;
431 StringList value;
432
433 int num_pieces = names.GetArgumentCount();
434
435 ConstString prefix (names.GetArgumentAtIndex (0));
436 const_var_name.SetCString (names.GetArgumentAtIndex (num_pieces - 1));
437
438 const SettingEntry *global_entry = GetGlobalEntry (const_var_name);
439 const SettingEntry *instance_entry = GetInstanceEntry (const_var_name);
440
441 if ((prefix != m_settings.level_name)
442 && (m_settings.level_name.GetLength () > 0))
443 {
444 value.AppendString ("Invalid variable name");
445 return value;
446 }
447
448 // prefix name matched; remove it from names.
449 if (m_settings.level_name.GetLength() > 0)
450 names.Shift();
451
452 // Should we pass this off to a child? If there is more than one name piece left, and the next name piece
453 // matches a child prefix, then yes.
454
455 lldb::UserSettingsControllerSP child;
456 if (names.GetArgumentCount() > 1)
457 {
458 ConstString child_prefix (names.GetArgumentAtIndex (0));
459 bool found = false;
460 for (int i = 0; i < m_children.size() && !found; ++i)
461 {
462 if (child_prefix == m_children[i]->GetLevelName())
463 {
464 found = true;
465 child = m_children[i];
466 std::string new_name;
467 for (int j = 0; j < names.GetArgumentCount(); ++j)
468 {
469 if (j > 0)
470 new_name += '.';
471 new_name += names.GetArgumentAtIndex (j);
472 }
473 return child->GetVariable (new_name.c_str(), var_type);
474 }
475 }
476
477 if (!found)
478 {
479 // Cannot be handled by a child, because name did not match any child prefixes.
480 // Cannot be a class-wide variable because there are too many name pieces.
481
482 if (instance_entry != NULL)
483 {
484 var_type = instance_entry->var_type;
485 ConstString instance_name (names.GetArgumentAtIndex (0));
486 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
487
488 if (current_settings != NULL)
489 {
490 current_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
491 }
492 else
493 {
494 // Look for instance name setting in pending settings.
495
496 std::string inst_name_str = instance_name.AsCString();
497 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
498
499 pos = m_pending_settings.find (inst_name_str);
500 if (pos != m_pending_settings.end())
501 {
502 lldb::InstanceSettingsSP settings_sp = pos->second;
503 settings_sp->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
504 }
505 else
506 {
507 // No valid instance name; assume they want the default settings.
508 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
509 }
510 }
511 }
512 else
513 value.AppendString ("Invalid variable name");
514 }
515 }
516 else
517 {
518 // Only one name left. It must belong to the current level, or be an error.
519 if ((global_entry == NULL)
520 && (instance_entry == NULL))
521 {
522 value.AppendString ("Invalid variable name");
523 }
524 else if (global_entry)
525 {
526 var_type = global_entry->var_type;
527 GetGlobalSettingsValue (const_var_name, value);
528 }
529 else if (instance_entry)
530 {
531 var_type = instance_entry->var_type;
532 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
533 }
534 }
535
536 return value;
537}
538
539void
540UserSettingsController::RemovePendingSettings (const ConstString &instance_name)
541{
542 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
543 std::string instance_name_str (instance_name.AsCString());
544 Mutex::Locker locker (m_pending_settings_mutex);
545
546 m_pending_settings.erase (instance_name_str);
547}
548
549const lldb::InstanceSettingsSP &
550UserSettingsController::FindPendingSettings (const ConstString &instance_name)
551{
552 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
553 std::string instance_name_str (instance_name.AsCString());
554
555 { // Scope for mutex.
556 Mutex::Locker locker (m_pending_settings_mutex);
557
558 pos = m_pending_settings.find (instance_name_str);
559 if (pos != m_pending_settings.end())
560 return pos->second;
561 }
562
563 return m_default_settings;
564}
565
566void
567UserSettingsController::CreateDefaultInstanceSettings ()
568{
569 Error err;
570 const ConstString &default_name = InstanceSettings::GetDefaultName();
571 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
572 {
573 SettingEntry &entry = m_settings.instance_settings[i];
574 ConstString var_name (entry.var_name);
575 const char *value = entry.default_value;
576
577 if (entry.var_type == lldb::eSetVarTypeEnum)
578 value = entry.enum_values[0].string_value;
579
580 m_default_settings->UpdateInstanceSettingsVariable (var_name, NULL, value, default_name, entry,
581 lldb::eVarSetOperationAssign, err, true);
582 }
583}
584
585void
586UserSettingsController::CopyDefaultSettings (const lldb::InstanceSettingsSP &actual_settings,
587 const ConstString &instance_name,
588 bool pending)
589{
590 Error err;
591 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
592 {
593 SettingEntry &entry = m_settings.instance_settings[i];
594 ConstString var_name (entry.var_name);
595 StringList value;
596 m_default_settings->GetInstanceSettingsValue (entry, var_name, value);
597
598 std::string value_str;
599 if (value.GetSize() == 1)
600 value_str.append (value.GetStringAtIndex (0));
601 else if (value.GetSize() > 1)
602 {
603 for (int j = 0; j < value.GetSize(); ++j)
604 {
605 if (j > 0)
606 value_str.append (" ");
607 value_str.append (value.GetStringAtIndex (j));
608 }
609 }
610
611 actual_settings->UpdateInstanceSettingsVariable (var_name, NULL, value_str.c_str(), instance_name, entry,
612 lldb::eVarSetOperationAssign, err, pending);
613
614 }
615}
616
617lldb::InstanceSettingsSP
618UserSettingsController::PendingSettingsForInstance (const ConstString &instance_name)
619{
620 std::string name_str (instance_name.AsCString());
621 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
622 Mutex::Locker locker (m_pending_settings_mutex);
623
624 pos = m_pending_settings.find (name_str);
625 if (pos != m_pending_settings.end())
626 {
627 lldb::InstanceSettingsSP settings_sp = pos->second;
628 return settings_sp;
629 }
630 else
631 {
632 lldb::InstanceSettingsSP default_settings_sp =
633 m_pending_settings[InstanceSettings::GetDefaultName().AsCString()];
634 lldb::InstanceSettingsSP new_settings_sp = CreateNewInstanceSettings ();
635 CopyDefaultSettings (new_settings_sp, instance_name, true);
636 m_pending_settings[name_str] = new_settings_sp;
637 return new_settings_sp;
638 }
639
640 // Should never reach this line.
641
642 lldb::InstanceSettingsSP dummy;
643
644 return dummy;
645}
646
647void
648UserSettingsController::GetAllDefaultSettingValues (StreamString &result_stream)
649{
650 std::string parent_prefix;
651 BuildParentPrefix (parent_prefix);
652 const char *prefix = parent_prefix.c_str();
653
654 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
655 {
656 SettingEntry &entry = m_settings.instance_settings[i];
657 ConstString var_name (entry.var_name);
658 StringList tmp_value;
659 m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value);
660
661 StreamString value_string;
662
663 if (tmp_value.GetSize() == 1)
664 value_string.Printf ("%s", tmp_value.GetStringAtIndex (0));
665 else
666 {
667 for (int j = 0; j < tmp_value.GetSize(); ++j)
668 value_string.Printf ("%s ", tmp_value.GetStringAtIndex (j));
669 }
670
671 if (! parent_prefix.empty()) // May need to test size() > 0
672 result_stream.Printf ("%s.[DEFAULT].%s (%s) = '%s'\n", prefix, var_name.AsCString(),
673 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
674 else
675 result_stream.Printf ("[DEFAULT].%s (%s) = '%s'\n", var_name.AsCString(),
676 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
677 }
678}
679
680void
681UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
682{
683 //StreamString description;
684 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
685
686 std::string parent_prefix;
687 BuildParentPrefix (parent_prefix);
688 const char *prefix = parent_prefix.c_str();
689
690 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
691 {
692 std::string tmp_name = pos->first;
693 lldb::InstanceSettingsSP settings_sp = pos->second;
694
695 const ConstString instance_name (tmp_name.c_str());
696
697 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
698 {
699 SettingEntry &entry = m_settings.instance_settings[i];
700 ConstString var_name (entry.var_name);
701 StringList tmp_value;
702 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value);
703
704 StreamString value_str;
705
706 if (tmp_value.GetSize() == 0)
707 break;
708 if (tmp_value.GetSize() == 1)
709 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
710 else
711 {
712 for (int j = 0; j < tmp_value.GetSize(); ++j)
713 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j));
714 }
715
716 if (parent_prefix.length() > 0)
717 {
718 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
719 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
720 value_str.GetData());
721 }
722 else
723 {
724 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
725 UserSettingsController::GetTypeString (entry.var_type),
726 value_str.GetData());
727 }
728 }
729 }
730}
731
732InstanceSettings *
733UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
734{
735 std::string instance_name_str (instance_name.AsCString());
736 std::map<std::string, InstanceSettings *>::iterator pos;
737
738 pos = m_live_settings.find (instance_name_str);
739 if (pos != m_live_settings.end ())
740 {
741 InstanceSettings *settings = pos->second;
742 return settings;
743 }
744
745 return NULL;
746}
747
748void
749UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
750 StreamString &result_stream)
751{
752 std::map<std::string, InstanceSettings *>::iterator pos;
753 std::string parent_prefix;
754 BuildParentPrefix (parent_prefix);
755 const char *prefix = parent_prefix.c_str();
756 StreamString description;
757
758 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
759 {
760 std::string instance_name = pos->first;
761 InstanceSettings *settings = pos->second;
762
763 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
764 {
765 SettingEntry &entry = m_settings.instance_settings[i];
766 const ConstString var_name (entry.var_name);
767 StringList tmp_value;
768 settings->GetInstanceSettingsValue (entry, var_name, tmp_value);
769 StreamString tmp_value_str;
770
771 if (tmp_value.GetSize() == 0)
772 break;
773
774 if (tmp_value.GetSize() == 1)
775 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
776 else
777 {
778 for (int j = 0; j < tmp_value.GetSize(); ++j)
779 tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j));
780 }
781
782 description.Clear();
783 if (parent_prefix.length() > 0)
784 {
785 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(),
786 UserSettingsController::GetTypeString (entry.var_type),
787 tmp_value_str.GetData());
788 }
789 else
790 {
791 description.Printf ("%s (%s) = '%s'", var_name.AsCString(),
792 UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData());
793 }
794 result_stream.Printf ("%s\n", description.GetData());
795 }
796 }
797}
798
799void
800UserSettingsController::OverrideAllInstances (const ConstString &var_name,
801 const char *value,
802 lldb::VarSetOperationType op,
803 const char *index_value,
804 Error &err)
805{
806 std::map<std::string, InstanceSettings *>::iterator pos;
807 StreamString description;
808
809 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
810 {
811 InstanceSettings *settings = pos->second;
812 StreamString tmp_name;
813 tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString());
814 const ConstString instance_name (tmp_name.GetData());
815 const SettingEntry *entry = GetInstanceEntry (var_name);
816 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false);
817
818 }
819}
820
821void
822UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings)
823{
824 Mutex::Locker locker (m_live_settings_mutex);
825 StreamString tmp_name;
826 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString());
827 const ConstString instance_name (tmp_name.GetData());
828 std::string instance_name_str (instance_name.AsCString());
829 if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0)
830 m_live_settings[instance_name_str] = instance_settings;
831}
832
833void
834UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance)
835{
836 Mutex::Locker locker (m_live_settings_mutex);
837 StreamString tmp_name;
838 tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString());
839 std::string instance_name (tmp_name.GetData());
840
841 std::map <std::string, InstanceSettings *>::iterator pos;
842
843 pos = m_live_settings.find (instance_name);
844 if (pos != m_live_settings.end())
845 m_live_settings.erase (pos);
846}
847
848void
849UserSettingsController::CreateSettingsVector (const SettingEntry *table,
850 bool global)
851{
852 int i = 0;
853 while (table[i].var_name != NULL)
854 {
855 const SettingEntry &table_entry = table[i];
856 ConstString const_var_name (table_entry.var_name);
857 SettingEntry new_entry;
858
859 new_entry = table_entry;
860 new_entry.var_name = const_var_name.AsCString();
861
862 if (global)
863 m_settings.global_settings.push_back (new_entry);
864 else
865 m_settings.instance_settings.push_back (new_entry);
866
867 ++i;
868 }
869}
870
871//----------------------------------------------------------------------
872// UserSettingsController static methods
873//----------------------------------------------------------------------
874
875int
876FindMaxNameLength (std::vector<SettingEntry> table)
877{
878 int max_length = 1;
879
880 for (int i = 0; i < table.size(); ++i)
881 {
882 int len = strlen (table[i].var_name);
883 if (len > max_length)
884 max_length = len;
885 }
886
887 return max_length;
888}
889
890const char *
891UserSettingsController::GetTypeString (lldb::SettableVariableType var_type)
892{
893 switch (var_type)
894 {
895 case lldb::eSetVarTypeInt:
896 return "int";
897 case lldb::eSetVarTypeBool:
898 return "boolean";
899 case lldb::eSetVarTypeString:
900 return "string";
901 case lldb::eSetVarTypeArray:
902 return "array";
903 case lldb::eSetVarTypeDictionary:
904 return "dictionary";
905 case lldb::eSetVarTypeEnum:
906 return "enum";
907 case lldb::eSetVarTypeNone:
908 return "no type";
909 }
910
911 return "";
912}
913
914void
915UserSettingsController::PrintEnumValues (const lldb::OptionEnumValueElement *enum_values, Stream &str)
916{
917 int i = 0;
918 while (enum_values[i].string_value != NULL)
919 {
920 str.Printf ("%s ", enum_values[i].string_value);
921 ++i;
922 }
923
924}
925
926void
927UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter,
928 lldb::UserSettingsControllerSP root,
929 std::string &current_prefix,
930 StreamString &result_stream,
931 Error &err)
932{
933 // Write out current prefix line.
934 StreamString prefix_line;
935 StreamString description;
936 uint32_t max_len;
937 int num_entries = root->m_settings.global_settings.size();
938
939 max_len = FindMaxNameLength (root->m_settings.global_settings);
940
941 if (! current_prefix.empty())
942 result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str());
943 else
944 result_stream.Printf ("\nTop level variables:\n\n");
945
946 if (num_entries > 0)
947 {
948 // Write out all "global" variables.
949 for (int i = 0; i < num_entries; ++i)
950 {
951 SettingEntry entry = root->m_settings.global_settings[i];
952 description.Clear();
953 if (entry.var_type == lldb::eSetVarTypeEnum)
954 {
955 StreamString enum_values_str;
956 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
957 description.Printf ("[static, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
958 enum_values_str.GetData(), entry.enum_values[0].string_value);
959 }
960 else if (entry.default_value != NULL)
961 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
962 entry.description, entry.default_value);
963
964 else
965 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
966 entry.description);
967 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
968 max_len);
969 }
970 }
971
972 num_entries = root->m_settings.instance_settings.size();
973 max_len = FindMaxNameLength (root->m_settings.instance_settings);
974
975 if (num_entries > 0)
976 {
977 // Write out all instance variables.
978 for (int i = 0; i < num_entries; ++i)
979 {
980 SettingEntry entry = root->m_settings.instance_settings[i];
981 description.Clear();
982 if (entry.var_type == lldb::eSetVarTypeEnum)
983 {
984 StreamString enum_values_str;
985 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
986 description.Printf ("[instance, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
987 enum_values_str.GetData(), entry.enum_values[0].string_value);
988 }
989 else if (entry.default_value != NULL)
990 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
991 entry.description, entry.default_value);
992 else
993 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
994 entry.description);
995 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
996 max_len);
997 }
998
999 }
1000
1001 // Now, recurse across all children.
1002 int num_children = root->GetNumChildren();
1003 for (int i = 0; i < num_children; ++i)
1004 {
1005 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1006
1007 if (child)
1008 {
1009 ConstString child_prefix = child->GetLevelName();
1010 StreamString new_prefix;
1011 if (! current_prefix.empty() ) // May need to see if size() > 0
1012 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1013 else
1014 new_prefix.Printf ("%s", child_prefix.AsCString());
1015 std::string new_prefix_str = new_prefix.GetData();
1016 UserSettingsController::FindAllSettingsDescriptions (interpreter, child, new_prefix_str, result_stream,
1017 err);
1018 }
1019 }
1020}
1021
1022void
1023UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter,
1024 lldb::UserSettingsControllerSP root,
1025 std::string &current_prefix,
1026 StreamString &result_stream,
1027 Error &err)
1028{
1029 StreamString description;
1030 int num_entries = root->m_settings.global_settings.size();
1031 lldb::SettableVariableType var_type;
1032
1033
1034 for (int i = 0; i < num_entries; ++i)
1035 {
1036 StreamString full_var_name;
1037 SettingEntry entry = root->m_settings.global_settings[i];
1038 if (! current_prefix.empty()) // May need to see if size() > 0
1039 full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1040 else
1041 full_var_name.Printf ("%s", entry.var_name);
1042 StringList value = root->GetVariable (full_var_name.GetData(), var_type);
1043 description.Clear();
1044 if (value.GetSize() == 1)
Caroline Tice49e27372010-09-07 18:35:40 +00001045 description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type),
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001046 value.GetStringAtIndex (0));
1047 else
1048 {
Caroline Tice49e27372010-09-07 18:35:40 +00001049 description.Printf ("%s (%s) = '", full_var_name.GetData(), GetTypeString (entry.var_type));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001050 for (int j = 0; j < value.GetSize(); ++j)
1051 description.Printf ("%s ", value.GetStringAtIndex (j));
Caroline Tice49e27372010-09-07 18:35:40 +00001052 description.Printf ("'");
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001053 }
1054
1055 result_stream.Printf ("%s\n", description.GetData());
1056 }
1057
1058 root->GetAllInstanceVariableValues (interpreter, result_stream);
1059 root->GetAllPendingSettingValues (result_stream);
1060 root->GetAllDefaultSettingValues (result_stream);
1061
1062
1063 // Now, recurse across all children.
1064 int num_children = root->GetNumChildren();
1065 for (int i = 0; i < num_children; ++i)
1066 {
1067 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1068
1069 if (child)
1070 {
1071 ConstString child_prefix = child->GetLevelName();
1072 StreamString new_prefix;
1073 if (! current_prefix.empty()) // May need to see if size() > 0
1074 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1075 else
1076 new_prefix.Printf ("%s", child_prefix.AsCString());
1077 std::string new_prefix_str = new_prefix.GetData();
1078 UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream,
1079 err);
1080 }
1081 }
1082
1083}
1084
1085Args
1086UserSettingsController::BreakNameIntoPieces (const char *full_dot_name)
1087{
1088 Args return_value;
1089 std::string name_string (full_dot_name);
1090 bool done = false;
1091
1092 std::string piece;
1093 std::string remainder (full_dot_name);
1094
1095 while (!done)
1096 {
1097 size_t idx = remainder.find_first_of ('.');
1098 piece = remainder.substr (0, idx);
1099 return_value.AppendArgument (piece.c_str());
1100 if (idx != std::string::npos)
1101 remainder = remainder.substr (idx+1);
1102 else
1103 done = true;
1104 }
1105
1106 return return_value;
1107}
1108
1109bool
1110UserSettingsController::IsLiveInstance (const std::string &instance_name)
1111{
1112 std::map<std::string, InstanceSettings *>::iterator pos;
1113
1114 pos = m_live_settings.find (instance_name);
1115 if (pos != m_live_settings.end())
1116 return true;
1117
1118 return false;
1119}
1120
1121int
1122UserSettingsController::CompleteSettingsValue (lldb::UserSettingsControllerSP root_settings,
1123 const char *full_dot_name,
1124 const char *partial_value,
1125 bool &word_complete,
1126 StringList &matches)
1127{
1128 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
1129 int num_pieces = names.GetArgumentCount();
1130 word_complete = true;
1131
1132 ConstString root_level = root_settings->GetLevelName();
1133 int num_extra_levels = num_pieces - 2;
1134 if ((num_extra_levels > 0)
1135 && root_level.GetLength() > 0)
1136 {
1137 ConstString current_level (names.GetArgumentAtIndex (0));
1138 if (current_level == root_level)
1139 {
1140 names.Shift();
1141 --num_extra_levels;
1142 }
1143 else
1144 return 0;
1145 }
1146
1147 for (int i = 0; i < num_extra_levels; ++i)
1148 {
1149 ConstString child_level (names.GetArgumentAtIndex (0));
1150 bool found = false;
1151 int num_children = root_settings->GetNumChildren();
1152 for (int j = 0; j < num_children && !found; ++j)
1153 {
1154 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1155 {
1156 found = true;
1157 root_settings = root_settings->GetChildAtIndex (j);
1158 names.Shift();
1159 }
1160 }
1161 if (!found)
1162 return 0;
1163 }
1164
1165 if (names.GetArgumentCount() != 2)
1166 return 0;
1167
1168 std::string next_name (names.GetArgumentAtIndex (0));
1169 int len = next_name.length();
1170 names.Shift();
1171
1172 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1173 {
1174 // 'next_name' is instance name. Instance names are irrelevent here.
1175 }
1176 else
1177 {
1178 // 'next_name' is child name.
1179 bool found = false;
1180 int num_children = root_settings->GetNumChildren();
1181 ConstString child_level (next_name.c_str());
1182 for (int j = 0; j < num_children && !found; ++j)
1183 {
1184 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1185 {
1186 found = true;
1187 root_settings = root_settings->GetChildAtIndex (j);
1188 }
1189 }
1190 if (!found)
1191 return 0;
1192 }
1193
1194 ConstString var_name (names.GetArgumentAtIndex(0));
1195 const SettingEntry *entry = root_settings->GetGlobalEntry (var_name);
1196 if (entry == NULL)
1197 entry = root_settings->GetInstanceEntry (var_name);
1198
1199 if (entry == NULL)
1200 return 0;
1201
1202 if (entry->var_type == lldb::eSetVarTypeBool)
1203 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches);
1204 else if (entry->var_type == lldb::eSetVarTypeEnum)
1205 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches);
1206 else
1207 return 0;
1208}
1209
1210int
1211UserSettingsController::BooleanMatches (const char *partial_value,
1212 bool &word_complete,
1213 StringList &matches)
1214{
1215 static const std::string true_string ("true");
1216 static const std::string false_string ("false");
1217
1218 if (partial_value == NULL)
1219 {
1220 matches.AppendString ("true");
1221 matches.AppendString ("false");
1222 }
1223 else
1224 {
1225 int partial_len = strlen (partial_value);
1226
1227 if ((partial_len <= true_string.length())
1228 && (true_string.find (partial_value) == 0))
1229 matches.AppendString ("true");
1230 else if ((partial_len <= false_string.length())
1231 && (false_string.find (partial_value) == 0))
1232 matches.AppendString ("false");
1233 }
1234
1235 word_complete = false;
1236 if (matches.GetSize() == 1)
1237 word_complete = true;
1238
1239 return matches.GetSize();
1240}
1241
1242int
1243UserSettingsController::EnumMatches (const char *partial_value,
1244 lldb::OptionEnumValueElement *enum_values,
1245 bool &word_complete,
1246 StringList &matches)
1247{
1248 int len = (partial_value != NULL) ? strlen (partial_value) : 0;
1249
1250 int i = 0;
1251 while (enum_values[i].string_value != NULL)
1252 {
1253 if (len == 0)
1254 matches.AppendString (enum_values[i].string_value);
1255 else
1256 {
1257 std::string tmp_value (enum_values[i].string_value);
1258 if ((len <= tmp_value.length())
1259 && tmp_value.find (partial_value) == 0)
1260 matches.AppendString (enum_values[i].string_value);
1261 }
1262 ++i;
1263 }
1264
1265 word_complete = false;
1266 if (matches.GetSize() == 1)
1267 word_complete = true;
1268
1269 return matches.GetSize();
1270}
1271
1272int
1273UserSettingsController::CompleteSettingsNames (lldb::UserSettingsControllerSP root_settings,
1274 Args &partial_setting_name_pieces,
1275 bool &word_complete,
1276 StringList &matches)
1277{
1278 int num_matches = 0;
1279 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount();
1280
1281 if (num_name_pieces > 1)
1282 {
1283 // There are at least two pieces, perhaps with multiple level names preceding them.
1284 // First traverse all the extra levels, until we have exactly two pieces left.
1285
1286 int num_extra_levels = num_name_pieces - 2;
1287
1288 // Deal with current level first.
1289
1290 ConstString root_level = root_settings->GetLevelName();
1291 if ((num_extra_levels > 0)
1292 && (root_level.GetLength() > 0))
1293 {
1294 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1295 if (current_level == root_level)
1296 {
1297 partial_setting_name_pieces.Shift();
1298 --num_extra_levels;
1299 }
1300 else
1301 return 0; // The current level did not match the name pieces; something is wrong, so return immediately
1302
1303 }
1304
1305 for (int i = 0; i < num_extra_levels; ++i)
1306 {
1307 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1308 bool found = false;
1309 int num_children = root_settings->GetNumChildren();
1310 for (int j = 0; j < num_children && !found; ++j)
1311 {
1312 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1313 {
1314 found = true;
1315 root_settings = root_settings->GetChildAtIndex (j);
1316 partial_setting_name_pieces.Shift();
1317 }
1318 }
1319 if (! found)
1320 {
1321 return 0; // Unable to find a matching child level name; something is wrong, so return immediately.
1322 }
1323 }
1324
1325 // Now there should be exactly two name pieces left. If not there is an error, so return immediately
1326
1327 if (partial_setting_name_pieces.GetArgumentCount() != 2)
1328 return 0;
1329
1330 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1331 int len = next_name.length();
1332 partial_setting_name_pieces.Shift();
1333
1334 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1335 {
1336 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an
1337 // instance_name, assuming 'next_name' is valid.
1338
1339 if (root_settings->IsLiveInstance (next_name))
1340 {
1341 std::string complete_prefix;
1342 root_settings->BuildParentPrefix (complete_prefix);
1343
1344 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0),
1345 complete_prefix,
1346 next_name.c_str(),
1347 matches);
1348 word_complete = true;
1349 if (num_matches > 1)
1350 word_complete = false;
1351
1352 return num_matches;
1353 }
1354 else
1355 return 0; // Invalid instance_name
1356 }
1357 else
1358 {
1359 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved.
1360 bool found = false;
1361 int num_children = root_settings->GetNumChildren();
1362 ConstString child_level (next_name.c_str());
1363 for (int i = 0; i < num_children; ++i)
1364 {
1365 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level)
1366 {
1367 found = true;
1368 return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i),
1369 partial_setting_name_pieces,
1370 word_complete, matches);
1371 }
1372 }
1373 if (!found)
1374 return 0;
1375 }
1376 }
1377 else if (num_name_pieces == 1)
1378 {
1379 std::string complete_prefix;
1380 root_settings->BuildParentPrefix (complete_prefix);
1381
1382 word_complete = true;
1383 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1384
1385 if (name[0] == '[')
1386 {
1387 // It's a partial instance name.
1388
1389 num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches);
1390 }
1391 else
1392 {
1393 // It could be anything *except* an instance name...
1394
1395 num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches);
1396 num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches);
1397 num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches);
1398 }
1399
1400 if (num_matches > 1)
1401 word_complete = false;
1402
1403 return num_matches;
1404 }
1405 else
1406 {
1407 // We have a user settings controller with a blank partial string. Return everything possible at this level.
1408
1409 std::string complete_prefix;
1410 root_settings->BuildParentPrefix (complete_prefix);
1411 num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches);
1412 num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches);
1413 num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches);
1414 num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches);
1415 word_complete = false;
1416 return num_matches;
1417 }
1418
1419 return num_matches;
1420}
1421
1422int
1423UserSettingsController::GlobalVariableMatches (const char *partial_name,
1424 const std::string &complete_prefix,
1425 StringList &matches)
1426{
1427 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1428 int num_matches = 0;
1429
1430 for (size_t i = 0; i < m_settings.global_settings.size(); ++i)
1431 {
1432 SettingEntry &entry = m_settings.global_settings[i];
1433 std::string var_name (entry.var_name);
1434 if ((partial_len == 0)
1435 || ((partial_len <= var_name.length())
1436 && (var_name.find (partial_name) == 0)))
1437 {
1438 StreamString match_name;
1439 if (complete_prefix.length() > 0)
1440 {
1441 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1442 matches.AppendString (match_name.GetData());
1443 }
1444 else
1445 matches.AppendString (var_name.c_str());
1446 ++num_matches;
1447 }
1448 }
1449 return num_matches;
1450}
1451
1452int
1453UserSettingsController::InstanceVariableMatches (const char *partial_name,
1454 const std::string &complete_prefix,
1455 const char *instance_name,
1456 StringList &matches)
1457{
1458 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1459 int num_matches = 0;
1460
1461 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i)
1462 {
1463 SettingEntry &entry = m_settings.instance_settings[i];
1464 std::string var_name (entry.var_name);
1465 if ((partial_len == 0)
1466 || ((partial_len <= var_name.length())
1467 && (var_name.find (partial_name) == 0)))
1468 {
1469 StreamString match_name;
1470 if (complete_prefix.length() > 0)
1471 {
1472 if (instance_name != NULL)
1473 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str());
1474 else
1475 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1476
1477 matches.AppendString (match_name.GetData());
1478 }
1479 else
1480 {
1481 if (instance_name != NULL)
1482 {
1483 match_name.Printf ("%s.%s", instance_name, var_name.c_str());
1484 matches.AppendString (match_name.GetData());
1485 }
1486 else
1487 matches.AppendString (var_name.c_str());
1488 }
1489 ++num_matches;
1490 }
1491 }
1492 return num_matches;
1493}
1494
1495int
1496UserSettingsController::LiveInstanceMatches (const char *partial_name,
1497 const std::string &complete_prefix,
1498 bool &word_complete,
1499 StringList &matches)
1500{
1501 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1502 int num_matches = 0;
1503
1504 std::map<std::string, InstanceSettings*>::iterator pos;
1505 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
1506 {
1507 std::string instance_name = pos->first;
1508 if ((partial_len == 0)
1509 || ((partial_len <= instance_name.length())
1510 && (instance_name.find (partial_name) == 0)))
1511 {
1512 StreamString match_name;
1513 if (complete_prefix.length() > 0)
1514 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str());
1515 else
1516 match_name.Printf ("%s.", instance_name.c_str());
1517 matches.AppendString (match_name.GetData());
1518 ++num_matches;
1519 }
1520 }
1521
1522 if (num_matches > 0)
1523 word_complete = false;
1524
1525 return num_matches;
1526}
1527
1528int
1529UserSettingsController::ChildMatches (const char *partial_name,
1530 const std::string &complete_prefix,
1531 bool &word_complete,
1532 StringList &matches)
1533{
1534 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1535 int num_children = GetNumChildren();
1536 int num_matches = 0;
1537 for (int i = 0; i < num_children; ++i)
1538 {
1539 std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString());
1540 StreamString match_name;
1541 if ((partial_len == 0)
1542 || ((partial_len <= child_name.length())
1543 && (child_name.find (partial_name) == 0)))
1544 {
1545 if (complete_prefix.length() > 0)
1546 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str());
1547 else
1548 match_name.Printf ("%s.", child_name.c_str());
1549 matches.AppendString (match_name.GetData());
1550 ++num_matches;
1551 }
1552 }
1553
1554 if (num_matches > 0)
1555 word_complete = false;
1556
1557 return num_matches;
1558}
1559
1560void
1561UserSettingsController::VerifyOperationForType (lldb::SettableVariableType var_type,
1562 lldb::VarSetOperationType op,
1563 const ConstString &var_name,
1564 Error &err)
1565{
1566 if (op == lldb::eVarSetOperationAssign)
1567 return;
1568
1569
1570 if (op == lldb::eVarSetOperationInvalid)
1571 {
1572 err.SetErrorString ("Invalid 'settings ' subcommand operation.\n");
1573 return;
1574 }
1575
1576 switch (op)
1577 {
1578 case lldb::eVarSetOperationInsertBefore:
1579 case lldb::eVarSetOperationInsertAfter:
1580 if (var_type != lldb::eSetVarTypeArray)
1581 err.SetErrorString ("Invalid operation: This operation can only be performed on array variables.\n");
1582 break;
1583 case lldb::eVarSetOperationReplace:
1584 case lldb::eVarSetOperationRemove:
1585 if ((var_type != lldb::eSetVarTypeArray)
1586 && (var_type != lldb::eSetVarTypeDictionary))
1587 err.SetErrorString ("Invalid operation: This operation can only be performed on array or dictionary"
1588 " variables.\n");
1589 break;
1590 case lldb::eVarSetOperationAppend:
1591 case lldb::eVarSetOperationClear:
1592 if ((var_type != lldb::eSetVarTypeArray)
1593 && (var_type != lldb::eSetVarTypeDictionary)
1594 && (var_type != lldb::eSetVarTypeString))
1595 err.SetErrorString ("Invalid operation: This operation can only be performed on array, dictionary "
1596 "or string variables.\n");
1597 break;
1598 default:
1599 break;
1600 }
1601
1602 return;
1603}
1604
1605void
1606UserSettingsController::UpdateStringVariable (lldb::VarSetOperationType op,
1607 std::string &string_var,
1608 const char *new_value,
1609 Error &err)
1610{
1611 if (op == lldb::eVarSetOperationAssign)
1612 string_var = new_value;
1613 else if (op == lldb::eVarSetOperationAppend)
1614 string_var.append (new_value);
1615 else if (op == lldb::eVarSetOperationClear)
1616 string_var.clear();
1617 else
1618 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1619}
1620
1621void
1622UserSettingsController::UpdateBooleanVariable (lldb::VarSetOperationType op,
1623 bool &bool_var,
1624 const char *new_value,
1625 Error &err)
1626{
1627 if (op != lldb::eVarSetOperationAssign)
1628 err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
1629
1630
1631 if ((new_value == NULL)
1632 || (new_value[0] == '\0'))
1633 err.SetErrorString ("Invalid value. Cannot perform update.\n");
1634
1635 std::string bool_val_str (new_value);
1636
1637 std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
1638
1639 if (bool_val_str == "true")
1640 bool_var = true;
1641 else if (bool_val_str == "false")
1642 bool_var = false;
1643}
1644
1645void
1646UserSettingsController::UpdateStringArrayVariable (lldb::VarSetOperationType op,
1647 const char *index_value,
1648 Args &array_var,
1649 const char *new_value,
1650 Error &err)
1651{
1652 int index = -1;
1653 bool valid_index = true;
1654
1655 if (index_value != NULL)
1656 {
1657 for (int i = 0; i < strlen(index_value); ++i)
1658 if (!isdigit (index_value[i]))
1659 {
1660 valid_index = false;
1661 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n",
1662 index_value);
1663 }
1664
1665 if (valid_index)
1666 index = atoi (index_value);
1667
1668 if (index < 0
1669 || index >= array_var.GetArgumentCount())
1670 {
1671 valid_index = false;
1672 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. "
1673 "Cannot update array value.\n", index);
1674 }
1675 }
1676
1677 switch (op)
1678 {
1679 case lldb::eVarSetOperationAssign:
1680 array_var.SetCommandString (new_value);
1681 break;
1682 case lldb::eVarSetOperationReplace:
1683 {
1684 if (valid_index)
1685 array_var.ReplaceArgumentAtIndex (index, new_value);
1686 break;
1687 }
1688 case lldb::eVarSetOperationInsertBefore:
1689 case lldb::eVarSetOperationInsertAfter:
1690 {
1691 if (valid_index)
1692 {
1693 Args new_array (new_value);
1694 if (op == lldb::eVarSetOperationInsertAfter)
1695 ++index;
1696 for (int i = 0; i < new_array.GetArgumentCount(); ++i)
1697 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i));
1698 }
1699 break;
1700 }
1701 case lldb::eVarSetOperationRemove:
1702 {
1703 if (valid_index)
1704 array_var.DeleteArgumentAtIndex (index);
1705 break;
1706 }
1707 case lldb::eVarSetOperationAppend:
1708 {
1709 Args new_array (new_value);
1710 array_var.AppendArguments (new_array);
1711 break;
1712 }
1713 case lldb::eVarSetOperationClear:
1714 array_var.Clear();
1715 break;
1716 default:
1717 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1718 break;
1719 }
1720}
1721
1722void
1723UserSettingsController::UpdateDictionaryVariable (lldb::VarSetOperationType op,
1724 const char *index_value,
1725 std::map<std::string, std::string> &dictionary,
1726 const char *new_value,
1727 Error &err)
1728{
1729 switch (op)
1730 {
1731 case lldb::eVarSetOperationReplace:
1732 if (index_value != NULL)
1733 {
1734 std::string key (index_value);
1735 std::map<std::string, std::string>::iterator pos;
1736
1737 pos = dictionary.find (key);
1738 if (pos != dictionary.end())
1739 dictionary[key] = new_value;
1740 else
1741 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value);
1742 }
1743 else
1744 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n");
1745 break;
1746 case lldb::eVarSetOperationRemove:
1747 if (index_value != NULL)
1748 {
1749 std::string key (index_value);
1750 dictionary.erase (key);
1751 }
1752 else
1753 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n");
1754 break;
1755 case lldb::eVarSetOperationClear:
1756 dictionary.clear ();
1757 break;
1758 case lldb::eVarSetOperationAppend:
1759 case lldb::eVarSetOperationAssign:
1760 {
1761 Args args (new_value);
1762 size_t num_args = args.GetArgumentCount();
1763 for (size_t i = 0; i < num_args; ++i)
1764 {
1765 std::string tmp_arg = args.GetArgumentAtIndex (i);
1766 size_t eq_sign = tmp_arg.find ('=');
1767 if (eq_sign != std::string::npos)
1768 {
1769 if (eq_sign > 4)
1770 {
1771 std::string tmp_key = tmp_arg.substr (0, eq_sign);
1772 std::string real_value = tmp_arg.substr (eq_sign+1);
1773 if ((tmp_key[0] == '[')
1774 && (tmp_key[1] == '"')
1775 && (tmp_key[eq_sign-2] == '"')
1776 && (tmp_key[eq_sign-1] == ']'))
1777 {
1778 std::string real_key = tmp_key.substr (2, eq_sign-4);
1779 dictionary[real_key] = real_value;
1780 }
1781 else
1782 err.SetErrorString ("Invalid key format for dictionary assignment. "
1783 "Expected '[\"<key>\"]'\n");
1784 }
1785 else
1786 err.SetErrorString ("Invalid key format for dictionary assignment. "
1787 "Expected '[\"<key>\"]'\n");
1788 }
1789 else
1790 err.SetErrorString ("Invalid format for dictionary value. Expected '[\"<key>\"]=<value>'\n");
1791 }
1792 }
1793 break;
1794 case lldb::eVarSetOperationInsertBefore:
1795 case lldb::eVarSetOperationInsertAfter:
1796 err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n");
1797 break;
1798 default:
1799 err.SetErrorString ("Unrecognized operation.\n");
1800 break;
1801 }
1802}
1803
1804const char *
1805UserSettingsController::EnumToString (const lldb::OptionEnumValueElement *enum_values,
1806 int value)
1807{
1808 int i = 0;
1809 while (enum_values[i].string_value != NULL)
1810 {
1811 if (enum_values[i].value == value)
1812 return enum_values[i].string_value;
1813 ++i;
1814 }
1815
1816 return "Invalid enumeration value";
1817}
1818
1819
1820void
1821UserSettingsController::UpdateEnumVariable (lldb::OptionEnumValueElement *enum_values,
1822 int *enum_var,
1823 const char *new_value,
1824 Error &err)
1825{
1826 bool found_one;
1827
1828 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one);
1829
1830 if (!found_one)
1831 err.SetErrorString ("Invalid enumeration value; cannot update variable.\n");
1832}
1833
1834//----------------------------------------------------------------------
1835// class InstanceSettings
1836//----------------------------------------------------------------------
1837
1838InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name) :
1839 m_owner (owner),
1840 m_instance_name (instance_name)
1841{
1842 if (m_instance_name != InstanceSettings::GetDefaultName())
1843 m_owner.RegisterInstanceSettings (this);
1844}
1845
1846InstanceSettings::~InstanceSettings ()
1847{
1848 if (m_instance_name != InstanceSettings::GetDefaultName())
1849 m_owner.UnregisterInstanceSettings (this);
1850}
1851
1852const ConstString &
1853InstanceSettings::GetDefaultName ()
1854{
1855 static const ConstString g_default_settings_name ("[DEFAULT]");
1856
1857 return g_default_settings_name;
1858}