blob: 82a58aad5c470072954b868f6daa2c91f815ed4d [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.
350 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 }
358 }
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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +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 Ticedaccaa92010-09-20 20:44:43 +0000719 m_default_settings->GetInstanceSettingsValue (entry, var_name, value, err);
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 Ticedaccaa92010-09-20 20:44:43 +0000780 Error err;
781 m_default_settings->GetInstanceSettingsValue (entry, var_name, tmp_value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000782
783 StreamString value_string;
784
785 if (tmp_value.GetSize() == 1)
786 value_string.Printf ("%s", tmp_value.GetStringAtIndex (0));
787 else
788 {
789 for (int j = 0; j < tmp_value.GetSize(); ++j)
790 value_string.Printf ("%s ", tmp_value.GetStringAtIndex (j));
791 }
792
Caroline Ticeded2fa32010-09-15 05:35:14 +0000793 if (! parent_prefix.empty())
794 result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(),
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000795 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
796 }
797}
798
799void
800UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
801{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000802 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
803
804 std::string parent_prefix;
805 BuildParentPrefix (parent_prefix);
806 const char *prefix = parent_prefix.c_str();
807
808 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
809 {
810 std::string tmp_name = pos->first;
811 lldb::InstanceSettingsSP settings_sp = pos->second;
812
813 const ConstString instance_name (tmp_name.c_str());
814
815 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
816 {
817 SettingEntry &entry = m_settings.instance_settings[i];
818 ConstString var_name (entry.var_name);
819 StringList tmp_value;
Caroline Ticedaccaa92010-09-20 20:44:43 +0000820 Error err;
821 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000822
823 StreamString value_str;
824
825 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000826 value_str.Printf ("");
827 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000828 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
829 else
830 {
831 for (int j = 0; j < tmp_value.GetSize(); ++j)
832 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j));
833 }
834
835 if (parent_prefix.length() > 0)
836 {
837 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
838 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
839 value_str.GetData());
840 }
841 else
842 {
843 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
844 UserSettingsController::GetTypeString (entry.var_type),
845 value_str.GetData());
846 }
847 }
848 }
849}
850
851InstanceSettings *
852UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
853{
854 std::string instance_name_str (instance_name.AsCString());
855 std::map<std::string, InstanceSettings *>::iterator pos;
856
857 pos = m_live_settings.find (instance_name_str);
858 if (pos != m_live_settings.end ())
859 {
860 InstanceSettings *settings = pos->second;
861 return settings;
862 }
863
864 return NULL;
865}
866
867void
868UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
869 StreamString &result_stream)
870{
871 std::map<std::string, InstanceSettings *>::iterator pos;
872 std::string parent_prefix;
873 BuildParentPrefix (parent_prefix);
874 const char *prefix = parent_prefix.c_str();
875 StreamString description;
876
877 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
878 {
879 std::string instance_name = pos->first;
880 InstanceSettings *settings = pos->second;
881
882 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
883 {
884 SettingEntry &entry = m_settings.instance_settings[i];
885 const ConstString var_name (entry.var_name);
886 StringList tmp_value;
Caroline Ticedaccaa92010-09-20 20:44:43 +0000887 Error err;
888 settings->GetInstanceSettingsValue (entry, var_name, tmp_value, err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000889 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,
Caroline Ticedaccaa92010-09-20 20:44:43 +00001365 interpreter.GetDebugger().GetInstanceName().AsCString(), err);
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