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