blob: b97aa1d7ea7619d24bbe6fe46c948e6705767fb0 [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),
Jim Inghama767c9a2010-09-07 23:31:30 +000029 m_pending_settings_mutex (Mutex::eMutexTypeRecursive),
30 m_live_settings_mutex (Mutex::eMutexTypeRecursive)
Caroline Tice3df9a8d2010-09-04 00:03:46 +000031{
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
Jim Ingham95852752010-09-07 20:27:09 +000041bool
42UserSettingsController::InitializeSettingsController (lldb::UserSettingsControllerSP &controller_sp,
43 SettingEntry *global_settings,
44 SettingEntry *instance_settings)
45{
46 const lldb::UserSettingsControllerSP &parent = controller_sp->GetParent ();
47 if (parent)
48 parent->RegisterChild (controller_sp);
49
Caroline Tice91123da2010-09-08 17:48:55 +000050 controller_sp->CreateSettingsVector (global_settings, true);
51 controller_sp->CreateSettingsVector (instance_settings, false);
Jim Ingham95852752010-09-07 20:27:09 +000052
Caroline Tice91123da2010-09-08 17:48:55 +000053 controller_sp->InitializeGlobalVariables ();
Jim Ingham95852752010-09-07 20:27:09 +000054 controller_sp->CreateDefaultInstanceSettings ();
55
56 return true;
57}
58
59void
60UserSettingsController::FinalizeSettingsController (lldb::UserSettingsControllerSP &controller_sp)
61{
62 const lldb::UserSettingsControllerSP &parent = controller_sp->GetParent ();
63 if (parent)
64 parent->RemoveChild (controller_sp);
65}
66
Caroline Tice3df9a8d2010-09-04 00:03:46 +000067void
68UserSettingsController::InitializeGlobalVariables ()
69{
70 static bool global_initialized = false;
71 int num_entries;
72 const char *prefix = GetLevelName().AsCString();
73
74 if (! global_initialized)
75 {
76 num_entries = m_settings.global_settings.size();
77 for (int i = 0; i < num_entries; ++i)
78 {
79 SettingEntry &entry = m_settings.global_settings[i];
80 if (entry.default_value != NULL)
81 {
82 StreamString full_name;
83 if (prefix[0] != '\0')
84 full_name.Printf ("%s.%s", prefix, entry.var_name);
85 else
86 full_name.Printf ("%s", entry.var_name);
Caroline Tice101c7c22010-09-09 06:25:08 +000087 SetVariable (full_name.GetData(), entry.default_value, lldb::eVarSetOperationAssign, false, "");
Caroline Tice3df9a8d2010-09-04 00:03:46 +000088 }
89 else if ((entry.var_type == lldb::eSetVarTypeEnum)
90 && (entry.enum_values != NULL))
91 {
92 StreamString full_name;
93 if (prefix[0] != '\0')
94 full_name.Printf ("%s.%s", prefix, entry.var_name);
95 else
96 full_name.Printf ("%s", entry.var_name);
97 SetVariable (full_name.GetData(), entry.enum_values[0].string_value, lldb::eVarSetOperationAssign,
Caroline Tice101c7c22010-09-09 06:25:08 +000098 false, "");
Caroline Tice3df9a8d2010-09-04 00:03:46 +000099 }
100 }
101 global_initialized = true;
102 }
103}
104
105const lldb::UserSettingsControllerSP &
106UserSettingsController::GetParent ()
107{
108 return m_settings.parent;
109}
110
111void
112UserSettingsController::RegisterChild (const lldb::UserSettingsControllerSP &child)
113{
114 Mutex::Locker locker (m_children_mutex);
115
116 // Verify child is not already in m_children.
117 size_t num_children = m_children.size();
118 bool found = false;
119 for (size_t i = 0; i < num_children; ++i)
120 {
121 if (m_children[i].get() == child.get())
122 found = true;
123 }
124
125 // Add child to m_children.
126 if (! found)
127 m_children.push_back (child);
128}
129
130const ConstString &
131UserSettingsController::GetLevelName ()
132{
133 return m_settings.level_name;
134}
135
136size_t
137UserSettingsController::GetNumChildren ()
138{
139 return m_children.size();
140}
141
142const lldb::UserSettingsControllerSP
143UserSettingsController::GetChildAtIndex (size_t index)
144{
145 if (index < m_children.size())
146 return m_children[index];
147
148 lldb::UserSettingsControllerSP dummy_value;
149
150 return dummy_value;
151}
152
153const SettingEntry *
154UserSettingsController::GetGlobalEntry (const ConstString &var_name)
155{
156
157 for (int i = 0; i < m_settings.global_settings.size(); ++i)
158 {
159 SettingEntry &entry = m_settings.global_settings[i];
160 ConstString entry_name (entry.var_name);
161 if (entry_name == var_name)
162 return &entry;
163 }
164
165 return NULL;
166}
167
168const SettingEntry *
169UserSettingsController::GetInstanceEntry (const ConstString &const_var_name)
170{
171
172 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
173 {
174 SettingEntry &entry = m_settings.instance_settings[i];
175 ConstString entry_name (entry.var_name);
176 if (entry_name == const_var_name)
177 return &entry;
178 }
179
180 return NULL;
181}
182
183void
184UserSettingsController::BuildParentPrefix (std::string &parent_prefix)
185{
186 lldb::UserSettingsControllerSP parent = GetParent();
187 if (parent.get() != NULL)
188 {
189 parent->BuildParentPrefix (parent_prefix);
190 if (parent_prefix.length() > 0)
191 parent_prefix.append (".");
192 }
193 parent_prefix.append (GetLevelName().AsCString());
194}
195
196void
197UserSettingsController::RemoveChild (const lldb::UserSettingsControllerSP &child)
198{
199 Mutex::Locker locker (m_children_mutex);
200 std::vector<lldb::UserSettingsControllerSP>::iterator pos, end = m_children.end();
201
202 for (pos = m_children.begin(); pos != end; ++pos)
203 {
204 lldb::UserSettingsControllerSP entry = *pos;
205 if (entry == child)
206 {
207 m_children.erase (pos);
208 break;
209 }
210 }
211}
212
213Error
214UserSettingsController::SetVariable (const char *full_dot_name,
215 const char *value,
216 const lldb::VarSetOperationType op,
217 const bool override,
Caroline Tice101c7c22010-09-09 06:25:08 +0000218 const char *debugger_instance_name,
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000219 const char *index_value)
220{
221 Error err;
222 ConstString const_var_name;
223 const ConstString &default_name = InstanceSettings::GetDefaultName();
224
225 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
226 int num_pieces = names.GetArgumentCount();
227
228 if (num_pieces < 1)
229 {
230 err.SetErrorStringWithFormat ("'%s' is not a valid variable name; cannot assign value.\n", full_dot_name);
231 return err;
232 }
233
234 ConstString prefix (names.GetArgumentAtIndex (0));
235
236 if ((prefix == m_settings.level_name)
237 || (m_settings.level_name.GetLength() == 0))
238 {
239
240 if (prefix == m_settings.level_name)
241 {
242 names.Shift ();
243 num_pieces = names.GetArgumentCount();
244 }
245
246 if (num_pieces == 0)
247 {
248 err.SetErrorString ("No variable name specified; cannot assign value.\n");
249 return err;
250 }
251 else if (num_pieces == 1)
252 {
253
254 // Must be one of the class-wide settings.
255
256 const_var_name.SetCString (names.GetArgumentAtIndex (0));
257 const SettingEntry *entry = GetGlobalEntry (const_var_name);
258 if (entry)
259 {
260 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
261
262 if (err.Fail())
263 return err;
264
265 if ((value == NULL || value[0] == '\0')
266 && (op == lldb::eVarSetOperationAssign))
267 {
268 if (entry->var_type != lldb::eSetVarTypeEnum)
269 value = entry->default_value;
270 else
271 value = entry->enum_values[0].string_value;
272 }
273 UpdateGlobalVariable (const_var_name, index_value, value, *entry, op, err);
274 }
275 else
276 {
277 // MIGHT be instance variable, to be for ALL instances.
278
279 entry = GetInstanceEntry (const_var_name);
280 if (entry == NULL)
281 {
282 err.SetErrorStringWithFormat ("Unable to find variable '%s.%s'; cannot assign value.\n",
283 prefix.AsCString(), const_var_name.AsCString());
284 return err;
285 }
286 else
287 {
288 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
289
290 if (err.Fail())
291 return err;
292
293 if ((value == NULL || value[0] == '\0')
294 && (op == lldb::eVarSetOperationAssign))
295 {
296 if (entry->var_type != lldb::eSetVarTypeEnum)
297 value = entry->default_value;
298 else
299 value = entry->enum_values[0].string_value;
300 }
301
Caroline Tice101c7c22010-09-09 06:25:08 +0000302 if ((m_settings.level_name.GetLength() > 0)
303 || strlen (debugger_instance_name) == 0)
304 {
305 // Set the default settings
306 m_default_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
307 default_name, *entry, op, err, true);
308 }
309 else
310 {
311 // We're at the Debugger level; find the correct debugger instance and set those settings
312 StreamString tmp_name;
313 if (debugger_instance_name[0] != '[')
314 tmp_name.Printf ("[%s]", debugger_instance_name);
315 else
316 tmp_name.Printf ("%s", debugger_instance_name);
317 ConstString dbg_name (tmp_name.GetData());
318 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
319 if (dbg_settings)
320 dbg_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value, dbg_name,
321 *entry, op, err, false);
322 }
323
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000324 if (override)
325 {
326 OverrideAllInstances (const_var_name, value, op, index_value, err);
327
328 // Update all pending records as well.
329 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos, end = m_pending_settings.end();
330 for (pos = m_pending_settings.begin(); pos != end; end++)
331 {
332 const ConstString instance_name (pos->first.c_str());
333 lldb::InstanceSettingsSP setting_sp = pos->second;
334 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
335 instance_name, *entry, op, err, true);
336 }
337 }
338 }
339 }
340 }
341 else
342 {
343 // Either a child's setting or an instance setting.
344
345 if (names.GetArgumentAtIndex(0)[0] == '[')
346 {
347 // An instance setting. Supposedly.
348
349 ConstString instance_name (names.GetArgumentAtIndex (0));
350
351 // First verify that there is only one more name.
352
353 names.Shift();
354
355 if (names.GetArgumentCount() != 1)
356 {
357 err.SetErrorStringWithFormat ("Invalid variable name format '%s'; cannot assign value.\n",
358 full_dot_name);
359 return err;
360 }
361
362 // Next verify that it is a valid instance setting name.
363
364 const_var_name.SetCString (names.GetArgumentAtIndex (0));
365 const SettingEntry *entry = GetInstanceEntry (const_var_name);
366
367 if (entry == NULL)
368 {
369 err.SetErrorStringWithFormat ("Unknown instance variable '%s'; cannot assign value.\n",
370 const_var_name.AsCString());
371 return err;
372 }
373
374 UserSettingsController::VerifyOperationForType (entry->var_type, op, const_var_name, err);
375
376 if (err.Fail())
377 return err;
378
379 if ((value == NULL || value[0] == '\0')
380 && (op == lldb::eVarSetOperationAssign))
381 {
382 if (entry->var_type != lldb::eSetVarTypeEnum)
383 value = entry->default_value;
384 else
385 value = entry->enum_values[0].string_value;
386 }
387
388 // Now look for existing instance with given instance name; if not found, find or create pending
389 // setting for instance with given name.
390
391 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
392
393 if (current_settings != NULL)
394 {
395 current_settings->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
396 instance_name, *entry, op, err, false);
397
398 }
399 else
400 {
401 // Instance does not currently exist; make or update a pending setting for it.
402 lldb::InstanceSettingsSP current_settings_sp = PendingSettingsForInstance (instance_name);
403
404 // Now we have a settings record, update it appropriately.
405
406 current_settings_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
407 instance_name, *entry, op, err, true);
408
409 { // Scope for mutex.
410 Mutex::Locker locker (m_pending_settings_mutex);
411 m_pending_settings[instance_name.AsCString()] = current_settings_sp;
412 }
413
414 if (override)
415 {
416 OverrideAllInstances (const_var_name, value, op, index_value, err);
417
418 // Update all pending records as well.
419 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
420 std::map<std::string, lldb::InstanceSettingsSP>::iterator end = m_pending_settings.end();
421 for (pos = m_pending_settings.begin(); pos != end; end++)
422 {
423 const ConstString tmp_inst_name (pos->first.c_str());
424 lldb::InstanceSettingsSP setting_sp = pos->second;
425 setting_sp->UpdateInstanceSettingsVariable (const_var_name, index_value, value,
426 tmp_inst_name, *entry, op, err, true);
427 }
428 }
429 }
430 }
431 else
432 {
433 // A child setting.
434 lldb::UserSettingsControllerSP child;
435 ConstString child_prefix (names.GetArgumentAtIndex (0));
436 int num_children = GetNumChildren();
437 bool found = false;
438 for (int i = 0; i < num_children && !found; ++i)
439 {
440 child = GetChildAtIndex (i);
441 ConstString current_prefix = child->GetLevelName();
442 if (current_prefix == child_prefix)
443 {
444 found = true;
445 std::string new_name;
446 for (int j = 0; j < names.GetArgumentCount(); ++j)
447 {
448 if (j > 0)
449 new_name += '.';
450 new_name += names.GetArgumentAtIndex (j);
451 }
Caroline Tice101c7c22010-09-09 06:25:08 +0000452 return child->SetVariable (new_name.c_str(), value, op, override, debugger_instance_name,
453 index_value);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000454 }
455 }
456 if (!found)
457 {
458 err.SetErrorStringWithFormat ("Unable to find variable '%s'; cannot assign value.\n",
459 full_dot_name);
460 return err;
461 }
462 }
463 }
464 }
465 else
466 {
467 err.SetErrorStringWithFormat ("'%s' is not a valid level name; was expecting '%s'. Cannot assign value.\n",
468 prefix.AsCString(), m_settings.level_name.AsCString());
469 }
470
471 return err;
472}
473
474StringList
Caroline Tice101c7c22010-09-09 06:25:08 +0000475UserSettingsController::GetVariable (const char *full_dot_name, lldb::SettableVariableType &var_type,
476 const char *debugger_instance_name)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000477{
478 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
479 ConstString const_var_name;
480 StringList value;
481
482 int num_pieces = names.GetArgumentCount();
483
484 ConstString prefix (names.GetArgumentAtIndex (0));
485 const_var_name.SetCString (names.GetArgumentAtIndex (num_pieces - 1));
486
487 const SettingEntry *global_entry = GetGlobalEntry (const_var_name);
488 const SettingEntry *instance_entry = GetInstanceEntry (const_var_name);
489
490 if ((prefix != m_settings.level_name)
491 && (m_settings.level_name.GetLength () > 0))
492 {
493 value.AppendString ("Invalid variable name");
494 return value;
495 }
496
497 // prefix name matched; remove it from names.
498 if (m_settings.level_name.GetLength() > 0)
499 names.Shift();
500
501 // Should we pass this off to a child? If there is more than one name piece left, and the next name piece
502 // matches a child prefix, then yes.
503
504 lldb::UserSettingsControllerSP child;
505 if (names.GetArgumentCount() > 1)
506 {
507 ConstString child_prefix (names.GetArgumentAtIndex (0));
508 bool found = false;
509 for (int i = 0; i < m_children.size() && !found; ++i)
510 {
511 if (child_prefix == m_children[i]->GetLevelName())
512 {
513 found = true;
514 child = m_children[i];
515 std::string new_name;
516 for (int j = 0; j < names.GetArgumentCount(); ++j)
517 {
518 if (j > 0)
519 new_name += '.';
520 new_name += names.GetArgumentAtIndex (j);
521 }
Caroline Tice101c7c22010-09-09 06:25:08 +0000522 return child->GetVariable (new_name.c_str(), var_type, debugger_instance_name);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000523 }
524 }
525
526 if (!found)
527 {
528 // Cannot be handled by a child, because name did not match any child prefixes.
529 // Cannot be a class-wide variable because there are too many name pieces.
530
531 if (instance_entry != NULL)
532 {
533 var_type = instance_entry->var_type;
534 ConstString instance_name (names.GetArgumentAtIndex (0));
535 InstanceSettings *current_settings = FindSettingsForInstance (instance_name);
536
537 if (current_settings != NULL)
538 {
539 current_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
540 }
541 else
542 {
543 // Look for instance name setting in pending settings.
544
545 std::string inst_name_str = instance_name.AsCString();
546 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
547
548 pos = m_pending_settings.find (inst_name_str);
549 if (pos != m_pending_settings.end())
550 {
551 lldb::InstanceSettingsSP settings_sp = pos->second;
552 settings_sp->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
553 }
554 else
555 {
Caroline Tice101c7c22010-09-09 06:25:08 +0000556 if (m_settings.level_name.GetLength() > 0)
557 {
558 // No valid instance name; assume they want the default settings.
559 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
560 }
561 else
562 {
563 // We're at the Debugger level; use the debugger's instance settings.
564 StreamString tmp_name;
565 if (debugger_instance_name[0] != '[')
566 tmp_name.Printf ("[%s]", debugger_instance_name);
567 else
568 tmp_name.Printf ("%s", debugger_instance_name);
569 ConstString dbg_name (debugger_instance_name);
570 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
571 if (dbg_settings)
572 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
573 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000574 }
575 }
576 }
577 else
578 value.AppendString ("Invalid variable name");
579 }
580 }
581 else
582 {
583 // Only one name left. It must belong to the current level, or be an error.
584 if ((global_entry == NULL)
585 && (instance_entry == NULL))
586 {
587 value.AppendString ("Invalid variable name");
588 }
589 else if (global_entry)
590 {
591 var_type = global_entry->var_type;
592 GetGlobalSettingsValue (const_var_name, value);
593 }
594 else if (instance_entry)
595 {
596 var_type = instance_entry->var_type;
Caroline Tice101c7c22010-09-09 06:25:08 +0000597 if (m_settings.level_name.GetLength() > 0)
598 m_default_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
599 else
600 {
601 // We're at the Debugger level; use the debugger's instance settings.
602 StreamString tmp_name;
603 if (debugger_instance_name[0] != '[')
604 tmp_name.Printf ("[%s]", debugger_instance_name);
605 else
606 tmp_name.Printf ("%s", debugger_instance_name);
607 ConstString dbg_name (tmp_name.GetData());
608 InstanceSettings *dbg_settings = FindSettingsForInstance (dbg_name);
609 if (dbg_settings)
610 dbg_settings->GetInstanceSettingsValue (*instance_entry, const_var_name, value);
611 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000612 }
613 }
614
615 return value;
616}
617
618void
619UserSettingsController::RemovePendingSettings (const ConstString &instance_name)
620{
Caroline Tice91123da2010-09-08 17:48:55 +0000621 StreamString tmp_name;
622
623 // Add surrounding brackets to instance name if not already present.
624
625 if (instance_name.AsCString()[0] != '[')
626 tmp_name.Printf ("[%s]", instance_name.AsCString());
627 else
628 tmp_name.Printf ("%s", instance_name.AsCString());
629
630 std::string instance_name_str (tmp_name.GetData());
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000631 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000632 Mutex::Locker locker (m_pending_settings_mutex);
633
634 m_pending_settings.erase (instance_name_str);
635}
636
637const lldb::InstanceSettingsSP &
638UserSettingsController::FindPendingSettings (const ConstString &instance_name)
639{
640 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
Caroline Tice91123da2010-09-08 17:48:55 +0000641 StreamString tmp_name;
642
643 // Add surrounding brackets to instance name if not already present.
644
645 if (instance_name.AsCString()[0] != '[')
646 tmp_name.Printf ("[%s]", instance_name.AsCString());
647 else
648 tmp_name.Printf ("%s", instance_name.AsCString());
649
650 std::string instance_name_str (tmp_name.GetData()); // Need std::string for std::map look-up
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000651
652 { // Scope for mutex.
653 Mutex::Locker locker (m_pending_settings_mutex);
654
655 pos = m_pending_settings.find (instance_name_str);
656 if (pos != m_pending_settings.end())
657 return pos->second;
658 }
659
660 return m_default_settings;
661}
662
663void
664UserSettingsController::CreateDefaultInstanceSettings ()
665{
666 Error err;
667 const ConstString &default_name = InstanceSettings::GetDefaultName();
668 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
669 {
670 SettingEntry &entry = m_settings.instance_settings[i];
671 ConstString var_name (entry.var_name);
672 const char *value = entry.default_value;
673
674 if (entry.var_type == lldb::eSetVarTypeEnum)
675 value = entry.enum_values[0].string_value;
676
677 m_default_settings->UpdateInstanceSettingsVariable (var_name, NULL, value, default_name, entry,
678 lldb::eVarSetOperationAssign, err, true);
679 }
680}
681
682void
683UserSettingsController::CopyDefaultSettings (const lldb::InstanceSettingsSP &actual_settings,
684 const ConstString &instance_name,
685 bool pending)
686{
687 Error err;
688 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
689 {
690 SettingEntry &entry = m_settings.instance_settings[i];
691 ConstString var_name (entry.var_name);
692 StringList value;
693 m_default_settings->GetInstanceSettingsValue (entry, var_name, value);
694
695 std::string value_str;
696 if (value.GetSize() == 1)
697 value_str.append (value.GetStringAtIndex (0));
698 else if (value.GetSize() > 1)
699 {
700 for (int j = 0; j < value.GetSize(); ++j)
701 {
702 if (j > 0)
703 value_str.append (" ");
704 value_str.append (value.GetStringAtIndex (j));
705 }
706 }
707
708 actual_settings->UpdateInstanceSettingsVariable (var_name, NULL, value_str.c_str(), instance_name, entry,
709 lldb::eVarSetOperationAssign, err, pending);
710
711 }
712}
713
714lldb::InstanceSettingsSP
715UserSettingsController::PendingSettingsForInstance (const ConstString &instance_name)
716{
717 std::string name_str (instance_name.AsCString());
718 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
719 Mutex::Locker locker (m_pending_settings_mutex);
720
721 pos = m_pending_settings.find (name_str);
722 if (pos != m_pending_settings.end())
723 {
724 lldb::InstanceSettingsSP settings_sp = pos->second;
725 return settings_sp;
726 }
727 else
728 {
Caroline Tice91123da2010-09-08 17:48:55 +0000729 lldb::InstanceSettingsSP new_settings_sp = CreateNewInstanceSettings (instance_name.AsCString());
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000730 CopyDefaultSettings (new_settings_sp, instance_name, true);
731 m_pending_settings[name_str] = new_settings_sp;
732 return new_settings_sp;
733 }
734
735 // Should never reach this line.
736
737 lldb::InstanceSettingsSP dummy;
738
739 return dummy;
740}
741
742void
743UserSettingsController::GetAllDefaultSettingValues (StreamString &result_stream)
744{
745 std::string parent_prefix;
746 BuildParentPrefix (parent_prefix);
747 const char *prefix = parent_prefix.c_str();
748
749 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
750 {
751 SettingEntry &entry = m_settings.instance_settings[i];
752 ConstString var_name (entry.var_name);
753 StringList tmp_value;
754 m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value);
755
756 StreamString value_string;
757
758 if (tmp_value.GetSize() == 1)
759 value_string.Printf ("%s", tmp_value.GetStringAtIndex (0));
760 else
761 {
762 for (int j = 0; j < tmp_value.GetSize(); ++j)
763 value_string.Printf ("%s ", tmp_value.GetStringAtIndex (j));
764 }
765
Caroline Ticeded2fa32010-09-15 05:35:14 +0000766 if (! parent_prefix.empty())
767 result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(),
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000768 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
769 }
770}
771
772void
773UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
774{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000775 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
776
777 std::string parent_prefix;
778 BuildParentPrefix (parent_prefix);
779 const char *prefix = parent_prefix.c_str();
780
781 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
782 {
783 std::string tmp_name = pos->first;
784 lldb::InstanceSettingsSP settings_sp = pos->second;
785
786 const ConstString instance_name (tmp_name.c_str());
787
788 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
789 {
790 SettingEntry &entry = m_settings.instance_settings[i];
791 ConstString var_name (entry.var_name);
792 StringList tmp_value;
793 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value);
794
795 StreamString value_str;
796
797 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000798 value_str.Printf ("");
799 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000800 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
801 else
802 {
803 for (int j = 0; j < tmp_value.GetSize(); ++j)
804 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j));
805 }
806
807 if (parent_prefix.length() > 0)
808 {
809 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
810 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
811 value_str.GetData());
812 }
813 else
814 {
815 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
816 UserSettingsController::GetTypeString (entry.var_type),
817 value_str.GetData());
818 }
819 }
820 }
821}
822
823InstanceSettings *
824UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
825{
826 std::string instance_name_str (instance_name.AsCString());
827 std::map<std::string, InstanceSettings *>::iterator pos;
828
829 pos = m_live_settings.find (instance_name_str);
830 if (pos != m_live_settings.end ())
831 {
832 InstanceSettings *settings = pos->second;
833 return settings;
834 }
835
836 return NULL;
837}
838
839void
840UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
841 StreamString &result_stream)
842{
843 std::map<std::string, InstanceSettings *>::iterator pos;
844 std::string parent_prefix;
845 BuildParentPrefix (parent_prefix);
846 const char *prefix = parent_prefix.c_str();
847 StreamString description;
848
849 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
850 {
851 std::string instance_name = pos->first;
852 InstanceSettings *settings = pos->second;
853
854 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
855 {
856 SettingEntry &entry = m_settings.instance_settings[i];
857 const ConstString var_name (entry.var_name);
858 StringList tmp_value;
859 settings->GetInstanceSettingsValue (entry, var_name, tmp_value);
860 StreamString tmp_value_str;
861
862 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000863 tmp_value_str.Printf ("");
864 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000865 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
866 else
867 {
868 for (int j = 0; j < tmp_value.GetSize(); ++j)
869 tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j));
870 }
871
872 description.Clear();
873 if (parent_prefix.length() > 0)
874 {
875 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(),
876 UserSettingsController::GetTypeString (entry.var_type),
877 tmp_value_str.GetData());
878 }
879 else
880 {
881 description.Printf ("%s (%s) = '%s'", var_name.AsCString(),
882 UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData());
883 }
884 result_stream.Printf ("%s\n", description.GetData());
885 }
886 }
887}
888
889void
890UserSettingsController::OverrideAllInstances (const ConstString &var_name,
891 const char *value,
892 lldb::VarSetOperationType op,
893 const char *index_value,
894 Error &err)
895{
896 std::map<std::string, InstanceSettings *>::iterator pos;
897 StreamString description;
898
899 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
900 {
901 InstanceSettings *settings = pos->second;
902 StreamString tmp_name;
903 tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString());
904 const ConstString instance_name (tmp_name.GetData());
905 const SettingEntry *entry = GetInstanceEntry (var_name);
906 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false);
907
908 }
909}
910
911void
912UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings)
913{
914 Mutex::Locker locker (m_live_settings_mutex);
915 StreamString tmp_name;
916 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString());
917 const ConstString instance_name (tmp_name.GetData());
918 std::string instance_name_str (instance_name.AsCString());
919 if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0)
920 m_live_settings[instance_name_str] = instance_settings;
921}
922
923void
924UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance)
925{
926 Mutex::Locker locker (m_live_settings_mutex);
927 StreamString tmp_name;
928 tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString());
929 std::string instance_name (tmp_name.GetData());
930
931 std::map <std::string, InstanceSettings *>::iterator pos;
932
933 pos = m_live_settings.find (instance_name);
934 if (pos != m_live_settings.end())
935 m_live_settings.erase (pos);
936}
937
938void
939UserSettingsController::CreateSettingsVector (const SettingEntry *table,
940 bool global)
941{
942 int i = 0;
943 while (table[i].var_name != NULL)
944 {
945 const SettingEntry &table_entry = table[i];
946 ConstString const_var_name (table_entry.var_name);
947 SettingEntry new_entry;
948
949 new_entry = table_entry;
950 new_entry.var_name = const_var_name.AsCString();
951
952 if (global)
953 m_settings.global_settings.push_back (new_entry);
954 else
955 m_settings.instance_settings.push_back (new_entry);
956
957 ++i;
958 }
959}
960
961//----------------------------------------------------------------------
962// UserSettingsController static methods
963//----------------------------------------------------------------------
964
965int
966FindMaxNameLength (std::vector<SettingEntry> table)
967{
968 int max_length = 1;
969
970 for (int i = 0; i < table.size(); ++i)
971 {
972 int len = strlen (table[i].var_name);
973 if (len > max_length)
974 max_length = len;
975 }
976
977 return max_length;
978}
979
980const char *
981UserSettingsController::GetTypeString (lldb::SettableVariableType var_type)
982{
983 switch (var_type)
984 {
985 case lldb::eSetVarTypeInt:
986 return "int";
987 case lldb::eSetVarTypeBool:
988 return "boolean";
989 case lldb::eSetVarTypeString:
990 return "string";
991 case lldb::eSetVarTypeArray:
992 return "array";
993 case lldb::eSetVarTypeDictionary:
994 return "dictionary";
995 case lldb::eSetVarTypeEnum:
996 return "enum";
997 case lldb::eSetVarTypeNone:
998 return "no type";
999 }
1000
1001 return "";
1002}
1003
1004void
1005UserSettingsController::PrintEnumValues (const lldb::OptionEnumValueElement *enum_values, Stream &str)
1006{
1007 int i = 0;
1008 while (enum_values[i].string_value != NULL)
1009 {
1010 str.Printf ("%s ", enum_values[i].string_value);
1011 ++i;
1012 }
1013
1014}
1015
1016void
1017UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter,
1018 lldb::UserSettingsControllerSP root,
1019 std::string &current_prefix,
1020 StreamString &result_stream,
1021 Error &err)
1022{
1023 // Write out current prefix line.
1024 StreamString prefix_line;
1025 StreamString description;
1026 uint32_t max_len;
1027 int num_entries = root->m_settings.global_settings.size();
1028
1029 max_len = FindMaxNameLength (root->m_settings.global_settings);
1030
1031 if (! current_prefix.empty())
1032 result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str());
1033 else
1034 result_stream.Printf ("\nTop level variables:\n\n");
1035
1036 if (num_entries > 0)
1037 {
1038 // Write out all "global" variables.
1039 for (int i = 0; i < num_entries; ++i)
1040 {
1041 SettingEntry entry = root->m_settings.global_settings[i];
1042 description.Clear();
1043 if (entry.var_type == lldb::eSetVarTypeEnum)
1044 {
1045 StreamString enum_values_str;
1046 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1047 description.Printf ("[static, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1048 enum_values_str.GetData(), entry.enum_values[0].string_value);
1049 }
1050 else if (entry.default_value != NULL)
1051 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1052 entry.description, entry.default_value);
1053
1054 else
1055 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1056 entry.description);
1057 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1058 max_len);
1059 }
1060 }
1061
1062 num_entries = root->m_settings.instance_settings.size();
1063 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1064
1065 if (num_entries > 0)
1066 {
1067 // Write out all instance variables.
1068 for (int i = 0; i < num_entries; ++i)
1069 {
1070 SettingEntry entry = root->m_settings.instance_settings[i];
1071 description.Clear();
1072 if (entry.var_type == lldb::eSetVarTypeEnum)
1073 {
1074 StreamString enum_values_str;
1075 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1076 description.Printf ("[instance, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1077 enum_values_str.GetData(), entry.enum_values[0].string_value);
1078 }
1079 else if (entry.default_value != NULL)
1080 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1081 entry.description, entry.default_value);
1082 else
1083 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1084 entry.description);
1085 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1086 max_len);
1087 }
1088
1089 }
1090
1091 // Now, recurse across all children.
1092 int num_children = root->GetNumChildren();
1093 for (int i = 0; i < num_children; ++i)
1094 {
1095 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1096
1097 if (child)
1098 {
1099 ConstString child_prefix = child->GetLevelName();
1100 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001101 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001102 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1103 else
1104 new_prefix.Printf ("%s", child_prefix.AsCString());
1105 std::string new_prefix_str = new_prefix.GetData();
1106 UserSettingsController::FindAllSettingsDescriptions (interpreter, child, new_prefix_str, result_stream,
1107 err);
1108 }
1109 }
1110}
1111
1112void
Caroline Tice7d9edf62010-09-15 06:56:39 +00001113UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter,
1114 lldb::UserSettingsControllerSP root,
1115 std::string &current_prefix,
1116 const char *search_name,
1117 StreamString &result_stream,
1118 Error &err)
1119{
1120 Args names = UserSettingsController::BreakNameIntoPieces (search_name);
1121 int num_pieces = names.GetArgumentCount ();
1122
1123 if (num_pieces == 0)
1124 return;
1125
1126 if (root->GetLevelName().GetLength() > 0)
1127 {
1128 ConstString prefix (names.GetArgumentAtIndex (0));
1129 if (prefix != root->GetLevelName())
1130 {
1131 std::string parent_prefix;
1132 root->BuildParentPrefix (parent_prefix);
1133 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(),
1134 prefix.AsCString());
1135 return;
1136 }
1137 else
1138 {
1139 names.Shift();
1140 --num_pieces;
1141 }
1142 }
1143
1144 // If there's nothing left then dump all global and instance descriptions for this root.
1145 if (num_pieces == 0)
1146 {
1147 StreamString prefix_line;
1148 StreamString description;
1149 uint32_t max_len;
1150 int num_entries = root->m_settings.global_settings.size();
1151
1152 max_len = FindMaxNameLength (root->m_settings.global_settings);
1153
1154 result_stream.Printf ("\n'%s' variables:\n\n", search_name);
1155
1156 if (num_entries > 0)
1157 {
1158 // Write out all "global" variables.
1159 for (int i = 0; i < num_entries; ++i)
1160 {
1161 SettingEntry entry = root->m_settings.global_settings[i];
1162 description.Clear();
1163 if (entry.var_type == lldb::eSetVarTypeEnum)
1164 {
1165 StreamString enum_values_str;
1166 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1167 description.Printf ("[static, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1168 enum_values_str.GetData(), entry.enum_values[0].string_value);
1169 }
1170 else if (entry.default_value != NULL)
1171 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1172 entry.description, entry.default_value);
1173 else
1174 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1175 entry.description);
1176 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1177 max_len);
1178 }
1179 }
1180
1181 num_entries = root->m_settings.instance_settings.size();
1182 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1183
1184 if (num_entries > 0)
1185 {
1186 // Write out all instance variables.
1187 for (int i = 0; i < num_entries; ++i)
1188 {
1189 SettingEntry entry = root->m_settings.instance_settings[i];
1190 description.Clear();
1191 if (entry.var_type == lldb::eSetVarTypeEnum)
1192 {
1193 StreamString enum_values_str;
1194 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1195 description.Printf ("[instance, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1196 enum_values_str.GetData(), entry.enum_values[0].string_value);
1197 }
1198 else if (entry.default_value != NULL)
1199 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1200 entry.description, entry.default_value);
1201 else
1202 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1203 entry.description);
1204 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1205 max_len);
1206 }
1207 }
1208 }
1209 else if (num_pieces == 1)
1210 {
1211 ConstString var_name (names.GetArgumentAtIndex (0));
1212 bool is_global = false;
1213
1214 const SettingEntry *setting_entry = root->GetGlobalEntry (var_name);
1215
1216 if (setting_entry == NULL)
1217 setting_entry = root->GetInstanceEntry (var_name);
1218 else
1219 is_global = true;
1220
1221 // Check to see if it is a global or instance variable name.
1222 if (setting_entry != NULL)
1223 {
1224 StreamString description;
1225 if (setting_entry->var_type == lldb::eSetVarTypeEnum)
1226 {
1227 StreamString enum_values_str;
1228 UserSettingsController::PrintEnumValues (setting_entry->enum_values, enum_values_str);
1229 description.Printf ("[%s, enum] %s. Valid values: {%s} (default: '%s')",
1230 (is_global ? "static" : "instance"),
1231 setting_entry->description,
1232 enum_values_str.GetData(), setting_entry->enum_values[0].string_value);
1233 }
1234 else if (setting_entry->default_value != NULL)
1235 description.Printf ("[%s, %s] %s (default: '%s')",
1236 (is_global ? "static" : "instance"),
1237 GetTypeString (setting_entry->var_type),
1238 setting_entry->description, setting_entry->default_value);
1239 else
1240 description.Printf ("[%s, %s] %s (default: '')",
1241 (is_global ? "static" : "instance"),
1242 GetTypeString (setting_entry->var_type),
1243 setting_entry->description);
1244 interpreter.OutputFormattedHelpText (result_stream, setting_entry->var_name, "--", description.GetData(),
1245 var_name.GetLength());
1246 }
1247 else
1248 {
1249 // It must be a child name.
1250 int num_children = root->GetNumChildren();
1251 bool found = false;
1252 for (int i = 0; i < num_children && !found; ++i)
1253 {
1254 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1255 if (child)
1256 {
1257 ConstString child_prefix = child->GetLevelName();
1258 if (child_prefix == var_name)
1259 {
1260 found = true;
1261 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1262 var_name.AsCString(), result_stream, err);
1263 }
1264 }
1265 }
1266 if (!found)
1267 {
1268 std::string parent_prefix;
1269 root->BuildParentPrefix (parent_prefix);
1270 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1271 return;
1272 }
1273 }
1274 }
1275 else
1276 {
1277 // It must be a child name; find the child and call this function recursively on child.
1278 ConstString child_name (names.GetArgumentAtIndex (0));
1279
1280 StreamString rest_of_search_name;
1281 for (int i = 0; i < num_pieces; ++i)
1282 {
1283 rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i));
1284 if ((i + 1) < num_pieces)
1285 rest_of_search_name.Printf (".");
1286 }
1287
1288 int num_children = root->GetNumChildren();
1289 bool found = false;
1290 for (int i = 0; i < num_children && !found; ++i)
1291 {
1292 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1293 if (child)
1294 {
1295 ConstString child_prefix = child->GetLevelName();
1296 if (child_prefix == child_name)
1297 {
1298 found = true;
1299 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1300 rest_of_search_name.GetData(), result_stream,
1301 err);
1302 }
1303 }
1304 }
1305 if (!found)
1306 {
1307 std::string parent_prefix;
1308 root->BuildParentPrefix (parent_prefix);
1309 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1310 return;
1311 }
1312 }
1313}
1314
1315void
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001316UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter,
1317 lldb::UserSettingsControllerSP root,
1318 std::string &current_prefix,
1319 StreamString &result_stream,
1320 Error &err)
1321{
1322 StreamString description;
1323 int num_entries = root->m_settings.global_settings.size();
1324 lldb::SettableVariableType var_type;
1325
1326
1327 for (int i = 0; i < num_entries; ++i)
1328 {
1329 StreamString full_var_name;
1330 SettingEntry entry = root->m_settings.global_settings[i];
Caroline Ticeded2fa32010-09-15 05:35:14 +00001331 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001332 full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1333 else
1334 full_var_name.Printf ("%s", entry.var_name);
Caroline Tice101c7c22010-09-09 06:25:08 +00001335 StringList value = root->GetVariable (full_var_name.GetData(), var_type,
1336 interpreter.GetDebugger().GetInstanceName().AsCString());
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001337 description.Clear();
1338 if (value.GetSize() == 1)
Caroline Tice49e27372010-09-07 18:35:40 +00001339 description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type),
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001340 value.GetStringAtIndex (0));
1341 else
1342 {
Caroline Tice49e27372010-09-07 18:35:40 +00001343 description.Printf ("%s (%s) = '", full_var_name.GetData(), GetTypeString (entry.var_type));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001344 for (int j = 0; j < value.GetSize(); ++j)
1345 description.Printf ("%s ", value.GetStringAtIndex (j));
Caroline Tice49e27372010-09-07 18:35:40 +00001346 description.Printf ("'");
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001347 }
1348
1349 result_stream.Printf ("%s\n", description.GetData());
1350 }
1351
1352 root->GetAllInstanceVariableValues (interpreter, result_stream);
1353 root->GetAllPendingSettingValues (result_stream);
Caroline Tice101c7c22010-09-09 06:25:08 +00001354 if (root->GetLevelName().GetLength() > 0) // Don't bother with default values for Debugger level.
1355 root->GetAllDefaultSettingValues (result_stream);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001356
1357
1358 // Now, recurse across all children.
1359 int num_children = root->GetNumChildren();
1360 for (int i = 0; i < num_children; ++i)
1361 {
1362 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1363
1364 if (child)
1365 {
1366 ConstString child_prefix = child->GetLevelName();
1367 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001368 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001369 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1370 else
1371 new_prefix.Printf ("%s", child_prefix.AsCString());
1372 std::string new_prefix_str = new_prefix.GetData();
1373 UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream,
1374 err);
1375 }
1376 }
1377
1378}
1379
1380Args
1381UserSettingsController::BreakNameIntoPieces (const char *full_dot_name)
1382{
1383 Args return_value;
1384 std::string name_string (full_dot_name);
1385 bool done = false;
1386
1387 std::string piece;
1388 std::string remainder (full_dot_name);
1389
1390 while (!done)
1391 {
1392 size_t idx = remainder.find_first_of ('.');
1393 piece = remainder.substr (0, idx);
1394 return_value.AppendArgument (piece.c_str());
1395 if (idx != std::string::npos)
1396 remainder = remainder.substr (idx+1);
1397 else
1398 done = true;
1399 }
1400
1401 return return_value;
1402}
1403
1404bool
1405UserSettingsController::IsLiveInstance (const std::string &instance_name)
1406{
1407 std::map<std::string, InstanceSettings *>::iterator pos;
1408
1409 pos = m_live_settings.find (instance_name);
1410 if (pos != m_live_settings.end())
1411 return true;
1412
1413 return false;
1414}
1415
1416int
1417UserSettingsController::CompleteSettingsValue (lldb::UserSettingsControllerSP root_settings,
1418 const char *full_dot_name,
1419 const char *partial_value,
1420 bool &word_complete,
1421 StringList &matches)
1422{
1423 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
1424 int num_pieces = names.GetArgumentCount();
1425 word_complete = true;
1426
1427 ConstString root_level = root_settings->GetLevelName();
1428 int num_extra_levels = num_pieces - 2;
1429 if ((num_extra_levels > 0)
1430 && root_level.GetLength() > 0)
1431 {
1432 ConstString current_level (names.GetArgumentAtIndex (0));
1433 if (current_level == root_level)
1434 {
1435 names.Shift();
1436 --num_extra_levels;
1437 }
1438 else
1439 return 0;
1440 }
1441
1442 for (int i = 0; i < num_extra_levels; ++i)
1443 {
1444 ConstString child_level (names.GetArgumentAtIndex (0));
1445 bool found = false;
1446 int num_children = root_settings->GetNumChildren();
1447 for (int j = 0; j < num_children && !found; ++j)
1448 {
1449 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1450 {
1451 found = true;
1452 root_settings = root_settings->GetChildAtIndex (j);
1453 names.Shift();
1454 }
1455 }
1456 if (!found)
1457 return 0;
1458 }
1459
1460 if (names.GetArgumentCount() != 2)
1461 return 0;
1462
1463 std::string next_name (names.GetArgumentAtIndex (0));
1464 int len = next_name.length();
1465 names.Shift();
1466
1467 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1468 {
1469 // 'next_name' is instance name. Instance names are irrelevent here.
1470 }
1471 else
1472 {
1473 // 'next_name' is child name.
1474 bool found = false;
1475 int num_children = root_settings->GetNumChildren();
1476 ConstString child_level (next_name.c_str());
1477 for (int j = 0; j < num_children && !found; ++j)
1478 {
1479 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1480 {
1481 found = true;
1482 root_settings = root_settings->GetChildAtIndex (j);
1483 }
1484 }
1485 if (!found)
1486 return 0;
1487 }
1488
1489 ConstString var_name (names.GetArgumentAtIndex(0));
1490 const SettingEntry *entry = root_settings->GetGlobalEntry (var_name);
1491 if (entry == NULL)
1492 entry = root_settings->GetInstanceEntry (var_name);
1493
1494 if (entry == NULL)
1495 return 0;
1496
1497 if (entry->var_type == lldb::eSetVarTypeBool)
1498 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches);
1499 else if (entry->var_type == lldb::eSetVarTypeEnum)
1500 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches);
1501 else
1502 return 0;
1503}
1504
1505int
1506UserSettingsController::BooleanMatches (const char *partial_value,
1507 bool &word_complete,
1508 StringList &matches)
1509{
1510 static const std::string true_string ("true");
1511 static const std::string false_string ("false");
1512
1513 if (partial_value == NULL)
1514 {
1515 matches.AppendString ("true");
1516 matches.AppendString ("false");
1517 }
1518 else
1519 {
1520 int partial_len = strlen (partial_value);
1521
1522 if ((partial_len <= true_string.length())
1523 && (true_string.find (partial_value) == 0))
1524 matches.AppendString ("true");
1525 else if ((partial_len <= false_string.length())
1526 && (false_string.find (partial_value) == 0))
1527 matches.AppendString ("false");
1528 }
1529
1530 word_complete = false;
1531 if (matches.GetSize() == 1)
1532 word_complete = true;
1533
1534 return matches.GetSize();
1535}
1536
1537int
1538UserSettingsController::EnumMatches (const char *partial_value,
1539 lldb::OptionEnumValueElement *enum_values,
1540 bool &word_complete,
1541 StringList &matches)
1542{
1543 int len = (partial_value != NULL) ? strlen (partial_value) : 0;
1544
1545 int i = 0;
1546 while (enum_values[i].string_value != NULL)
1547 {
1548 if (len == 0)
1549 matches.AppendString (enum_values[i].string_value);
1550 else
1551 {
1552 std::string tmp_value (enum_values[i].string_value);
1553 if ((len <= tmp_value.length())
1554 && tmp_value.find (partial_value) == 0)
1555 matches.AppendString (enum_values[i].string_value);
1556 }
1557 ++i;
1558 }
1559
1560 word_complete = false;
1561 if (matches.GetSize() == 1)
1562 word_complete = true;
1563
1564 return matches.GetSize();
1565}
1566
1567int
1568UserSettingsController::CompleteSettingsNames (lldb::UserSettingsControllerSP root_settings,
1569 Args &partial_setting_name_pieces,
1570 bool &word_complete,
1571 StringList &matches)
1572{
1573 int num_matches = 0;
1574 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount();
1575
1576 if (num_name_pieces > 1)
1577 {
1578 // There are at least two pieces, perhaps with multiple level names preceding them.
1579 // First traverse all the extra levels, until we have exactly two pieces left.
1580
1581 int num_extra_levels = num_name_pieces - 2;
1582
1583 // Deal with current level first.
1584
1585 ConstString root_level = root_settings->GetLevelName();
1586 if ((num_extra_levels > 0)
1587 && (root_level.GetLength() > 0))
1588 {
1589 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1590 if (current_level == root_level)
1591 {
1592 partial_setting_name_pieces.Shift();
1593 --num_extra_levels;
1594 }
1595 else
1596 return 0; // The current level did not match the name pieces; something is wrong, so return immediately
1597
1598 }
1599
1600 for (int i = 0; i < num_extra_levels; ++i)
1601 {
1602 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1603 bool found = false;
1604 int num_children = root_settings->GetNumChildren();
1605 for (int j = 0; j < num_children && !found; ++j)
1606 {
1607 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1608 {
1609 found = true;
1610 root_settings = root_settings->GetChildAtIndex (j);
1611 partial_setting_name_pieces.Shift();
1612 }
1613 }
1614 if (! found)
1615 {
1616 return 0; // Unable to find a matching child level name; something is wrong, so return immediately.
1617 }
1618 }
1619
1620 // Now there should be exactly two name pieces left. If not there is an error, so return immediately
1621
1622 if (partial_setting_name_pieces.GetArgumentCount() != 2)
1623 return 0;
1624
1625 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1626 int len = next_name.length();
1627 partial_setting_name_pieces.Shift();
1628
1629 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1630 {
1631 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an
1632 // instance_name, assuming 'next_name' is valid.
1633
1634 if (root_settings->IsLiveInstance (next_name))
1635 {
1636 std::string complete_prefix;
1637 root_settings->BuildParentPrefix (complete_prefix);
1638
1639 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0),
1640 complete_prefix,
1641 next_name.c_str(),
1642 matches);
1643 word_complete = true;
1644 if (num_matches > 1)
1645 word_complete = false;
1646
1647 return num_matches;
1648 }
1649 else
1650 return 0; // Invalid instance_name
1651 }
1652 else
1653 {
1654 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved.
1655 bool found = false;
1656 int num_children = root_settings->GetNumChildren();
1657 ConstString child_level (next_name.c_str());
1658 for (int i = 0; i < num_children; ++i)
1659 {
1660 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level)
1661 {
1662 found = true;
1663 return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i),
1664 partial_setting_name_pieces,
1665 word_complete, matches);
1666 }
1667 }
1668 if (!found)
1669 return 0;
1670 }
1671 }
1672 else if (num_name_pieces == 1)
1673 {
1674 std::string complete_prefix;
1675 root_settings->BuildParentPrefix (complete_prefix);
1676
1677 word_complete = true;
1678 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1679
1680 if (name[0] == '[')
1681 {
1682 // It's a partial instance name.
1683
1684 num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches);
1685 }
1686 else
1687 {
1688 // It could be anything *except* an instance name...
1689
1690 num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches);
1691 num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches);
1692 num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches);
1693 }
1694
1695 if (num_matches > 1)
1696 word_complete = false;
1697
1698 return num_matches;
1699 }
1700 else
1701 {
1702 // We have a user settings controller with a blank partial string. Return everything possible at this level.
1703
1704 std::string complete_prefix;
1705 root_settings->BuildParentPrefix (complete_prefix);
1706 num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches);
1707 num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches);
1708 num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches);
1709 num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches);
1710 word_complete = false;
1711 return num_matches;
1712 }
1713
1714 return num_matches;
1715}
1716
1717int
1718UserSettingsController::GlobalVariableMatches (const char *partial_name,
1719 const std::string &complete_prefix,
1720 StringList &matches)
1721{
1722 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1723 int num_matches = 0;
1724
1725 for (size_t i = 0; i < m_settings.global_settings.size(); ++i)
1726 {
1727 SettingEntry &entry = m_settings.global_settings[i];
1728 std::string var_name (entry.var_name);
1729 if ((partial_len == 0)
1730 || ((partial_len <= var_name.length())
1731 && (var_name.find (partial_name) == 0)))
1732 {
1733 StreamString match_name;
1734 if (complete_prefix.length() > 0)
1735 {
1736 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1737 matches.AppendString (match_name.GetData());
1738 }
1739 else
1740 matches.AppendString (var_name.c_str());
1741 ++num_matches;
1742 }
1743 }
1744 return num_matches;
1745}
1746
1747int
1748UserSettingsController::InstanceVariableMatches (const char *partial_name,
1749 const std::string &complete_prefix,
1750 const char *instance_name,
1751 StringList &matches)
1752{
1753 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1754 int num_matches = 0;
1755
1756 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i)
1757 {
1758 SettingEntry &entry = m_settings.instance_settings[i];
1759 std::string var_name (entry.var_name);
1760 if ((partial_len == 0)
1761 || ((partial_len <= var_name.length())
1762 && (var_name.find (partial_name) == 0)))
1763 {
1764 StreamString match_name;
1765 if (complete_prefix.length() > 0)
1766 {
1767 if (instance_name != NULL)
1768 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str());
1769 else
1770 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1771
1772 matches.AppendString (match_name.GetData());
1773 }
1774 else
1775 {
1776 if (instance_name != NULL)
1777 {
1778 match_name.Printf ("%s.%s", instance_name, var_name.c_str());
1779 matches.AppendString (match_name.GetData());
1780 }
1781 else
1782 matches.AppendString (var_name.c_str());
1783 }
1784 ++num_matches;
1785 }
1786 }
1787 return num_matches;
1788}
1789
1790int
1791UserSettingsController::LiveInstanceMatches (const char *partial_name,
1792 const std::string &complete_prefix,
1793 bool &word_complete,
1794 StringList &matches)
1795{
1796 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1797 int num_matches = 0;
1798
1799 std::map<std::string, InstanceSettings*>::iterator pos;
1800 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
1801 {
1802 std::string instance_name = pos->first;
1803 if ((partial_len == 0)
1804 || ((partial_len <= instance_name.length())
1805 && (instance_name.find (partial_name) == 0)))
1806 {
1807 StreamString match_name;
1808 if (complete_prefix.length() > 0)
1809 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str());
1810 else
1811 match_name.Printf ("%s.", instance_name.c_str());
1812 matches.AppendString (match_name.GetData());
1813 ++num_matches;
1814 }
1815 }
1816
1817 if (num_matches > 0)
1818 word_complete = false;
1819
1820 return num_matches;
1821}
1822
1823int
1824UserSettingsController::ChildMatches (const char *partial_name,
1825 const std::string &complete_prefix,
1826 bool &word_complete,
1827 StringList &matches)
1828{
1829 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1830 int num_children = GetNumChildren();
1831 int num_matches = 0;
1832 for (int i = 0; i < num_children; ++i)
1833 {
1834 std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString());
1835 StreamString match_name;
1836 if ((partial_len == 0)
1837 || ((partial_len <= child_name.length())
1838 && (child_name.find (partial_name) == 0)))
1839 {
1840 if (complete_prefix.length() > 0)
1841 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str());
1842 else
1843 match_name.Printf ("%s.", child_name.c_str());
1844 matches.AppendString (match_name.GetData());
1845 ++num_matches;
1846 }
1847 }
1848
1849 if (num_matches > 0)
1850 word_complete = false;
1851
1852 return num_matches;
1853}
1854
1855void
1856UserSettingsController::VerifyOperationForType (lldb::SettableVariableType var_type,
1857 lldb::VarSetOperationType op,
1858 const ConstString &var_name,
1859 Error &err)
1860{
1861 if (op == lldb::eVarSetOperationAssign)
1862 return;
1863
1864
1865 if (op == lldb::eVarSetOperationInvalid)
1866 {
1867 err.SetErrorString ("Invalid 'settings ' subcommand operation.\n");
1868 return;
1869 }
1870
1871 switch (op)
1872 {
1873 case lldb::eVarSetOperationInsertBefore:
1874 case lldb::eVarSetOperationInsertAfter:
1875 if (var_type != lldb::eSetVarTypeArray)
1876 err.SetErrorString ("Invalid operation: This operation can only be performed on array variables.\n");
1877 break;
1878 case lldb::eVarSetOperationReplace:
1879 case lldb::eVarSetOperationRemove:
1880 if ((var_type != lldb::eSetVarTypeArray)
1881 && (var_type != lldb::eSetVarTypeDictionary))
1882 err.SetErrorString ("Invalid operation: This operation can only be performed on array or dictionary"
1883 " variables.\n");
1884 break;
1885 case lldb::eVarSetOperationAppend:
1886 case lldb::eVarSetOperationClear:
1887 if ((var_type != lldb::eSetVarTypeArray)
1888 && (var_type != lldb::eSetVarTypeDictionary)
1889 && (var_type != lldb::eSetVarTypeString))
1890 err.SetErrorString ("Invalid operation: This operation can only be performed on array, dictionary "
1891 "or string variables.\n");
1892 break;
1893 default:
1894 break;
1895 }
1896
1897 return;
1898}
1899
1900void
1901UserSettingsController::UpdateStringVariable (lldb::VarSetOperationType op,
1902 std::string &string_var,
1903 const char *new_value,
1904 Error &err)
1905{
1906 if (op == lldb::eVarSetOperationAssign)
1907 string_var = new_value;
1908 else if (op == lldb::eVarSetOperationAppend)
1909 string_var.append (new_value);
1910 else if (op == lldb::eVarSetOperationClear)
1911 string_var.clear();
1912 else
1913 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1914}
1915
1916void
1917UserSettingsController::UpdateBooleanVariable (lldb::VarSetOperationType op,
1918 bool &bool_var,
1919 const char *new_value,
1920 Error &err)
1921{
1922 if (op != lldb::eVarSetOperationAssign)
1923 err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
1924
1925
1926 if ((new_value == NULL)
1927 || (new_value[0] == '\0'))
1928 err.SetErrorString ("Invalid value. Cannot perform update.\n");
1929
1930 std::string bool_val_str (new_value);
1931
1932 std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
1933
1934 if (bool_val_str == "true")
1935 bool_var = true;
1936 else if (bool_val_str == "false")
1937 bool_var = false;
1938}
1939
1940void
1941UserSettingsController::UpdateStringArrayVariable (lldb::VarSetOperationType op,
1942 const char *index_value,
1943 Args &array_var,
1944 const char *new_value,
1945 Error &err)
1946{
1947 int index = -1;
1948 bool valid_index = true;
1949
1950 if (index_value != NULL)
1951 {
1952 for (int i = 0; i < strlen(index_value); ++i)
1953 if (!isdigit (index_value[i]))
1954 {
1955 valid_index = false;
1956 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n",
1957 index_value);
1958 }
1959
1960 if (valid_index)
1961 index = atoi (index_value);
1962
1963 if (index < 0
1964 || index >= array_var.GetArgumentCount())
1965 {
1966 valid_index = false;
1967 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. "
1968 "Cannot update array value.\n", index);
1969 }
1970 }
1971
1972 switch (op)
1973 {
1974 case lldb::eVarSetOperationAssign:
1975 array_var.SetCommandString (new_value);
1976 break;
1977 case lldb::eVarSetOperationReplace:
1978 {
1979 if (valid_index)
1980 array_var.ReplaceArgumentAtIndex (index, new_value);
1981 break;
1982 }
1983 case lldb::eVarSetOperationInsertBefore:
1984 case lldb::eVarSetOperationInsertAfter:
1985 {
1986 if (valid_index)
1987 {
1988 Args new_array (new_value);
1989 if (op == lldb::eVarSetOperationInsertAfter)
1990 ++index;
1991 for (int i = 0; i < new_array.GetArgumentCount(); ++i)
1992 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i));
1993 }
1994 break;
1995 }
1996 case lldb::eVarSetOperationRemove:
1997 {
1998 if (valid_index)
1999 array_var.DeleteArgumentAtIndex (index);
2000 break;
2001 }
2002 case lldb::eVarSetOperationAppend:
2003 {
2004 Args new_array (new_value);
2005 array_var.AppendArguments (new_array);
2006 break;
2007 }
2008 case lldb::eVarSetOperationClear:
2009 array_var.Clear();
2010 break;
2011 default:
2012 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
2013 break;
2014 }
2015}
2016
2017void
2018UserSettingsController::UpdateDictionaryVariable (lldb::VarSetOperationType op,
2019 const char *index_value,
2020 std::map<std::string, std::string> &dictionary,
2021 const char *new_value,
2022 Error &err)
2023{
2024 switch (op)
2025 {
2026 case lldb::eVarSetOperationReplace:
2027 if (index_value != NULL)
2028 {
2029 std::string key (index_value);
2030 std::map<std::string, std::string>::iterator pos;
2031
2032 pos = dictionary.find (key);
2033 if (pos != dictionary.end())
2034 dictionary[key] = new_value;
2035 else
2036 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value);
2037 }
2038 else
2039 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n");
2040 break;
2041 case lldb::eVarSetOperationRemove:
2042 if (index_value != NULL)
2043 {
2044 std::string key (index_value);
2045 dictionary.erase (key);
2046 }
2047 else
2048 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n");
2049 break;
2050 case lldb::eVarSetOperationClear:
2051 dictionary.clear ();
2052 break;
2053 case lldb::eVarSetOperationAppend:
2054 case lldb::eVarSetOperationAssign:
2055 {
2056 Args args (new_value);
2057 size_t num_args = args.GetArgumentCount();
2058 for (size_t i = 0; i < num_args; ++i)
2059 {
2060 std::string tmp_arg = args.GetArgumentAtIndex (i);
2061 size_t eq_sign = tmp_arg.find ('=');
2062 if (eq_sign != std::string::npos)
2063 {
2064 if (eq_sign > 4)
2065 {
2066 std::string tmp_key = tmp_arg.substr (0, eq_sign);
2067 std::string real_value = tmp_arg.substr (eq_sign+1);
2068 if ((tmp_key[0] == '[')
2069 && (tmp_key[1] == '"')
2070 && (tmp_key[eq_sign-2] == '"')
2071 && (tmp_key[eq_sign-1] == ']'))
2072 {
2073 std::string real_key = tmp_key.substr (2, eq_sign-4);
2074 dictionary[real_key] = real_value;
2075 }
2076 else
2077 err.SetErrorString ("Invalid key format for dictionary assignment. "
2078 "Expected '[\"<key>\"]'\n");
2079 }
2080 else
2081 err.SetErrorString ("Invalid key format for dictionary assignment. "
2082 "Expected '[\"<key>\"]'\n");
2083 }
2084 else
2085 err.SetErrorString ("Invalid format for dictionary value. Expected '[\"<key>\"]=<value>'\n");
2086 }
2087 }
2088 break;
2089 case lldb::eVarSetOperationInsertBefore:
2090 case lldb::eVarSetOperationInsertAfter:
2091 err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n");
2092 break;
2093 default:
2094 err.SetErrorString ("Unrecognized operation.\n");
2095 break;
2096 }
2097}
2098
2099const char *
2100UserSettingsController::EnumToString (const lldb::OptionEnumValueElement *enum_values,
2101 int value)
2102{
2103 int i = 0;
2104 while (enum_values[i].string_value != NULL)
2105 {
2106 if (enum_values[i].value == value)
2107 return enum_values[i].string_value;
2108 ++i;
2109 }
2110
2111 return "Invalid enumeration value";
2112}
2113
2114
2115void
2116UserSettingsController::UpdateEnumVariable (lldb::OptionEnumValueElement *enum_values,
2117 int *enum_var,
2118 const char *new_value,
2119 Error &err)
2120{
2121 bool found_one;
2122
2123 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one);
2124
2125 if (!found_one)
2126 err.SetErrorString ("Invalid enumeration value; cannot update variable.\n");
2127}
2128
Caroline Ticeded2fa32010-09-15 05:35:14 +00002129void
2130UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name)
2131{
2132 Mutex::Locker live_mutex (m_live_settings_mutex);
2133 Mutex::Locker pending_mutex (m_pending_settings_mutex);
2134 std::string old_name_key (old_name);
2135 std::string new_name_key (new_name);
2136
2137 // First, find the live instance settings for the old_name. If they don't exist in the live settings
2138 // list, then this is not a setting that can be renamed.
2139
2140 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']'))
2141 {
2142 StreamString tmp_str;
2143 tmp_str.Printf ("[%s]", old_name);
2144 old_name_key = tmp_str.GetData();
2145 }
2146
2147 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']'))
2148 {
2149 StreamString tmp_str;
2150 tmp_str.Printf ("[%s]", new_name);
2151 new_name_key = tmp_str.GetData();
2152 }
2153
2154 std::map<std::string, InstanceSettings *>::iterator pos;
2155
2156 pos = m_live_settings.find (old_name_key);
2157 if (pos != m_live_settings.end())
2158 {
2159 InstanceSettings *live_settings = pos->second;
2160
2161 // Rename the settings.
2162 live_settings->ChangeInstanceName (new_name_key);
2163
2164 // Now see if there are any pending settings for the new name; if so, copy them into live_settings.
2165 std::map<std::string, lldb::InstanceSettingsSP>::iterator pending_pos;
2166 pending_pos = m_pending_settings.find (new_name_key);
2167 if (pending_pos != m_pending_settings.end())
2168 {
2169 lldb::InstanceSettingsSP pending_settings_sp = pending_pos->second;
2170 live_settings->CopyInstanceSettings (pending_settings_sp, false);
2171 }
2172
2173 // Erase the old entry (under the old name) from live settings.
2174 m_live_settings.erase (pos);
2175
2176 // Add the new entry, with the new name, into live settings.
2177 m_live_settings[new_name_key] = live_settings;
2178 }
2179}
2180
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002181//----------------------------------------------------------------------
2182// class InstanceSettings
2183//----------------------------------------------------------------------
2184
Caroline Tice91123da2010-09-08 17:48:55 +00002185InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) :
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002186 m_owner (owner),
2187 m_instance_name (instance_name)
2188{
Caroline Tice91123da2010-09-08 17:48:55 +00002189 if ((m_instance_name != InstanceSettings::GetDefaultName())
2190 && live_instance)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002191 m_owner.RegisterInstanceSettings (this);
2192}
2193
2194InstanceSettings::~InstanceSettings ()
2195{
2196 if (m_instance_name != InstanceSettings::GetDefaultName())
2197 m_owner.UnregisterInstanceSettings (this);
2198}
2199
2200const ConstString &
2201InstanceSettings::GetDefaultName ()
2202{
2203 static const ConstString g_default_settings_name ("[DEFAULT]");
2204
2205 return g_default_settings_name;
2206}
Caroline Ticeded2fa32010-09-15 05:35:14 +00002207
2208void
2209InstanceSettings::ChangeInstanceName (const std::string &new_instance_name)
2210{
2211 m_instance_name.SetCString (new_instance_name.c_str());
2212}
2213
2214