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