blob: fc8d1aab57f8ccdb71b1c263d10c4f6982f294ff [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)
Greg Claytondbe54502010-11-19 03:46:01 +000074 parent->RegisterChild (controller_sp);
Jim Ingham95852752010-09-07 20:27:09 +000075
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;
Caroline Tice2d5289d2010-12-10 00:26:54 +0000783 bool multi_value = false;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000784
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)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000790 {
791 if (entry.var_type == lldb::eSetVarTypeArray)
792 value_string.Printf ("\n [%d]: '%s'", j, tmp_value.GetStringAtIndex (j));
793 else if (entry.var_type == lldb::eSetVarTypeDictionary)
794 value_string.Printf ("\n '%s'", tmp_value.GetStringAtIndex (j));
795 }
796 multi_value = true;
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000797 }
798
Caroline Ticeded2fa32010-09-15 05:35:14 +0000799 if (! parent_prefix.empty())
Caroline Tice2d5289d2010-12-10 00:26:54 +0000800 {
801 if (multi_value)
802 result_stream.Printf ("%s.%s (%s):%s\n", prefix, var_name.AsCString(),
803 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
804 else
805 result_stream.Printf ("%s.%s (%s) = '%s'\n", prefix, var_name.AsCString(),
806 UserSettingsController::GetTypeString (entry.var_type), value_string.GetData());
807 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000808 }
809}
810
811void
812UserSettingsController::GetAllPendingSettingValues (StreamString &result_stream)
813{
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000814 std::map<std::string, lldb::InstanceSettingsSP>::iterator pos;
815
816 std::string parent_prefix;
817 BuildParentPrefix (parent_prefix);
818 const char *prefix = parent_prefix.c_str();
819
820 for (pos = m_pending_settings.begin(); pos != m_pending_settings.end(); ++pos)
821 {
822 std::string tmp_name = pos->first;
823 lldb::InstanceSettingsSP settings_sp = pos->second;
824
825 const ConstString instance_name (tmp_name.c_str());
826
827 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
828 {
829 SettingEntry &entry = m_settings.instance_settings[i];
830 ConstString var_name (entry.var_name);
831 StringList tmp_value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000832 settings_sp->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000833
834 StreamString value_str;
835
836 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000837 value_str.Printf ("");
838 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000839 value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
840 else
841 {
842 for (int j = 0; j < tmp_value.GetSize(); ++j)
843 value_str.Printf ("%s ", tmp_value.GetStringAtIndex (j));
844 }
845
846 if (parent_prefix.length() > 0)
847 {
848 result_stream.Printf ("%s.%s.%s (%s) = '%s' [pending]\n", prefix, instance_name.AsCString(),
849 var_name.AsCString(), UserSettingsController::GetTypeString (entry.var_type),
850 value_str.GetData());
851 }
852 else
853 {
854 result_stream.Printf ("%s (%s) = '%s' [pending]\n", var_name.AsCString(),
855 UserSettingsController::GetTypeString (entry.var_type),
856 value_str.GetData());
857 }
858 }
859 }
860}
861
862InstanceSettings *
863UserSettingsController::FindSettingsForInstance (const ConstString &instance_name)
864{
865 std::string instance_name_str (instance_name.AsCString());
866 std::map<std::string, InstanceSettings *>::iterator pos;
867
868 pos = m_live_settings.find (instance_name_str);
869 if (pos != m_live_settings.end ())
870 {
871 InstanceSettings *settings = pos->second;
872 return settings;
873 }
874
875 return NULL;
876}
877
878void
879UserSettingsController::GetAllInstanceVariableValues (CommandInterpreter &interpreter,
880 StreamString &result_stream)
881{
882 std::map<std::string, InstanceSettings *>::iterator pos;
883 std::string parent_prefix;
884 BuildParentPrefix (parent_prefix);
885 const char *prefix = parent_prefix.c_str();
886 StreamString description;
887
888 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
889 {
890 std::string instance_name = pos->first;
891 InstanceSettings *settings = pos->second;
892
893 for (int i = 0; i < m_settings.instance_settings.size(); ++i)
894 {
895 SettingEntry &entry = m_settings.instance_settings[i];
896 const ConstString var_name (entry.var_name);
897 StringList tmp_value;
Caroline Tice12cecd72010-09-20 21:37:42 +0000898 settings->GetInstanceSettingsValue (entry, var_name, tmp_value, NULL);
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000899 StreamString tmp_value_str;
900
901 if (tmp_value.GetSize() == 0)
Caroline Ticeded2fa32010-09-15 05:35:14 +0000902 tmp_value_str.Printf ("");
903 else if (tmp_value.GetSize() == 1)
Caroline Tice3df9a8d2010-09-04 00:03:46 +0000904 tmp_value_str.Printf ("%s", tmp_value.GetStringAtIndex (0));
905 else
906 {
907 for (int j = 0; j < tmp_value.GetSize(); ++j)
908 tmp_value_str.Printf ("%s ",tmp_value.GetStringAtIndex (j));
909 }
910
911 description.Clear();
912 if (parent_prefix.length() > 0)
913 {
914 description.Printf ("%s.%s.%s (%s) = '%s'", prefix, instance_name.c_str(), var_name.AsCString(),
915 UserSettingsController::GetTypeString (entry.var_type),
916 tmp_value_str.GetData());
917 }
918 else
919 {
920 description.Printf ("%s (%s) = '%s'", var_name.AsCString(),
921 UserSettingsController::GetTypeString (entry.var_type), tmp_value_str.GetData());
922 }
923 result_stream.Printf ("%s\n", description.GetData());
924 }
925 }
926}
927
928void
929UserSettingsController::OverrideAllInstances (const ConstString &var_name,
930 const char *value,
931 lldb::VarSetOperationType op,
932 const char *index_value,
933 Error &err)
934{
935 std::map<std::string, InstanceSettings *>::iterator pos;
936 StreamString description;
937
938 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
939 {
940 InstanceSettings *settings = pos->second;
941 StreamString tmp_name;
942 tmp_name.Printf ("[%s]", settings->GetInstanceName().AsCString());
943 const ConstString instance_name (tmp_name.GetData());
944 const SettingEntry *entry = GetInstanceEntry (var_name);
945 settings->UpdateInstanceSettingsVariable (var_name, index_value, value, instance_name, *entry, op, err, false);
946
947 }
948}
949
950void
951UserSettingsController::RegisterInstanceSettings (InstanceSettings *instance_settings)
952{
953 Mutex::Locker locker (m_live_settings_mutex);
954 StreamString tmp_name;
955 tmp_name.Printf ("[%s]", instance_settings->GetInstanceName().AsCString());
956 const ConstString instance_name (tmp_name.GetData());
957 std::string instance_name_str (instance_name.AsCString());
958 if (instance_name_str.compare (InstanceSettings::GetDefaultName().AsCString()) != 0)
959 m_live_settings[instance_name_str] = instance_settings;
960}
961
962void
963UserSettingsController::UnregisterInstanceSettings (InstanceSettings *instance)
964{
965 Mutex::Locker locker (m_live_settings_mutex);
966 StreamString tmp_name;
967 tmp_name.Printf ("[%s]", instance->GetInstanceName().AsCString());
968 std::string instance_name (tmp_name.GetData());
969
970 std::map <std::string, InstanceSettings *>::iterator pos;
971
972 pos = m_live_settings.find (instance_name);
973 if (pos != m_live_settings.end())
974 m_live_settings.erase (pos);
975}
976
977void
978UserSettingsController::CreateSettingsVector (const SettingEntry *table,
979 bool global)
980{
981 int i = 0;
982 while (table[i].var_name != NULL)
983 {
984 const SettingEntry &table_entry = table[i];
985 ConstString const_var_name (table_entry.var_name);
986 SettingEntry new_entry;
987
988 new_entry = table_entry;
989 new_entry.var_name = const_var_name.AsCString();
990
991 if (global)
992 m_settings.global_settings.push_back (new_entry);
993 else
994 m_settings.instance_settings.push_back (new_entry);
995
996 ++i;
997 }
998}
999
1000//----------------------------------------------------------------------
1001// UserSettingsController static methods
1002//----------------------------------------------------------------------
1003
1004int
1005FindMaxNameLength (std::vector<SettingEntry> table)
1006{
1007 int max_length = 1;
1008
1009 for (int i = 0; i < table.size(); ++i)
1010 {
1011 int len = strlen (table[i].var_name);
1012 if (len > max_length)
1013 max_length = len;
1014 }
1015
1016 return max_length;
1017}
1018
1019const char *
1020UserSettingsController::GetTypeString (lldb::SettableVariableType var_type)
1021{
1022 switch (var_type)
1023 {
1024 case lldb::eSetVarTypeInt:
1025 return "int";
Jim Ingham06e827c2010-11-11 19:26:09 +00001026 case lldb::eSetVarTypeBoolean:
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001027 return "boolean";
1028 case lldb::eSetVarTypeString:
1029 return "string";
1030 case lldb::eSetVarTypeArray:
1031 return "array";
1032 case lldb::eSetVarTypeDictionary:
1033 return "dictionary";
1034 case lldb::eSetVarTypeEnum:
1035 return "enum";
1036 case lldb::eSetVarTypeNone:
1037 return "no type";
1038 }
1039
1040 return "";
1041}
1042
1043void
1044UserSettingsController::PrintEnumValues (const lldb::OptionEnumValueElement *enum_values, Stream &str)
1045{
1046 int i = 0;
1047 while (enum_values[i].string_value != NULL)
1048 {
1049 str.Printf ("%s ", enum_values[i].string_value);
1050 ++i;
1051 }
1052
1053}
1054
1055void
1056UserSettingsController::FindAllSettingsDescriptions (CommandInterpreter &interpreter,
1057 lldb::UserSettingsControllerSP root,
1058 std::string &current_prefix,
1059 StreamString &result_stream,
1060 Error &err)
1061{
1062 // Write out current prefix line.
1063 StreamString prefix_line;
1064 StreamString description;
1065 uint32_t max_len;
1066 int num_entries = root->m_settings.global_settings.size();
1067
1068 max_len = FindMaxNameLength (root->m_settings.global_settings);
1069
1070 if (! current_prefix.empty())
1071 result_stream.Printf ("\n'%s' variables:\n\n", current_prefix.c_str());
1072 else
1073 result_stream.Printf ("\nTop level variables:\n\n");
1074
1075 if (num_entries > 0)
1076 {
1077 // Write out all "global" variables.
1078 for (int i = 0; i < num_entries; ++i)
1079 {
1080 SettingEntry entry = root->m_settings.global_settings[i];
1081 description.Clear();
1082 if (entry.var_type == lldb::eSetVarTypeEnum)
1083 {
1084 StreamString enum_values_str;
1085 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1086 description.Printf ("[static, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1087 enum_values_str.GetData(), entry.enum_values[0].string_value);
1088 }
1089 else if (entry.default_value != NULL)
1090 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1091 entry.description, entry.default_value);
1092
1093 else
1094 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1095 entry.description);
1096 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1097 max_len);
1098 }
1099 }
1100
1101 num_entries = root->m_settings.instance_settings.size();
1102 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1103
1104 if (num_entries > 0)
1105 {
1106 // Write out all instance variables.
1107 for (int i = 0; i < num_entries; ++i)
1108 {
1109 SettingEntry entry = root->m_settings.instance_settings[i];
1110 description.Clear();
1111 if (entry.var_type == lldb::eSetVarTypeEnum)
1112 {
1113 StreamString enum_values_str;
1114 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1115 description.Printf ("[instance, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1116 enum_values_str.GetData(), entry.enum_values[0].string_value);
1117 }
1118 else if (entry.default_value != NULL)
1119 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1120 entry.description, entry.default_value);
1121 else
1122 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1123 entry.description);
1124 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1125 max_len);
1126 }
1127
1128 }
1129
1130 // Now, recurse across all children.
1131 int num_children = root->GetNumChildren();
1132 for (int i = 0; i < num_children; ++i)
1133 {
1134 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1135
1136 if (child)
1137 {
1138 ConstString child_prefix = child->GetLevelName();
1139 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001140 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001141 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1142 else
1143 new_prefix.Printf ("%s", child_prefix.AsCString());
1144 std::string new_prefix_str = new_prefix.GetData();
1145 UserSettingsController::FindAllSettingsDescriptions (interpreter, child, new_prefix_str, result_stream,
1146 err);
1147 }
1148 }
1149}
1150
1151void
Caroline Tice7d9edf62010-09-15 06:56:39 +00001152UserSettingsController::FindSettingsDescriptions (CommandInterpreter &interpreter,
1153 lldb::UserSettingsControllerSP root,
1154 std::string &current_prefix,
1155 const char *search_name,
1156 StreamString &result_stream,
1157 Error &err)
1158{
1159 Args names = UserSettingsController::BreakNameIntoPieces (search_name);
1160 int num_pieces = names.GetArgumentCount ();
1161
1162 if (num_pieces == 0)
1163 return;
1164
1165 if (root->GetLevelName().GetLength() > 0)
1166 {
1167 ConstString prefix (names.GetArgumentAtIndex (0));
1168 if (prefix != root->GetLevelName())
1169 {
1170 std::string parent_prefix;
1171 root->BuildParentPrefix (parent_prefix);
1172 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(),
1173 prefix.AsCString());
1174 return;
1175 }
1176 else
1177 {
1178 names.Shift();
1179 --num_pieces;
1180 }
1181 }
1182
1183 // If there's nothing left then dump all global and instance descriptions for this root.
1184 if (num_pieces == 0)
1185 {
1186 StreamString prefix_line;
1187 StreamString description;
1188 uint32_t max_len;
1189 int num_entries = root->m_settings.global_settings.size();
1190
1191 max_len = FindMaxNameLength (root->m_settings.global_settings);
1192
1193 result_stream.Printf ("\n'%s' variables:\n\n", search_name);
1194
1195 if (num_entries > 0)
1196 {
1197 // Write out all "global" variables.
1198 for (int i = 0; i < num_entries; ++i)
1199 {
1200 SettingEntry entry = root->m_settings.global_settings[i];
1201 description.Clear();
1202 if (entry.var_type == lldb::eSetVarTypeEnum)
1203 {
1204 StreamString enum_values_str;
1205 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1206 description.Printf ("[static, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1207 enum_values_str.GetData(), entry.enum_values[0].string_value);
1208 }
1209 else if (entry.default_value != NULL)
1210 description.Printf ("[static, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1211 entry.description, entry.default_value);
1212 else
1213 description.Printf ("[static, %s] %s (default: '')", GetTypeString (entry.var_type),
1214 entry.description);
1215 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1216 max_len);
1217 }
1218 }
1219
1220 num_entries = root->m_settings.instance_settings.size();
1221 max_len = FindMaxNameLength (root->m_settings.instance_settings);
1222
1223 if (num_entries > 0)
1224 {
1225 // Write out all instance variables.
1226 for (int i = 0; i < num_entries; ++i)
1227 {
1228 SettingEntry entry = root->m_settings.instance_settings[i];
1229 description.Clear();
1230 if (entry.var_type == lldb::eSetVarTypeEnum)
1231 {
1232 StreamString enum_values_str;
1233 UserSettingsController::PrintEnumValues (entry.enum_values, enum_values_str);
1234 description.Printf ("[instance, enum] %s. Valid values: {%s} (default: '%s')", entry.description,
1235 enum_values_str.GetData(), entry.enum_values[0].string_value);
1236 }
1237 else if (entry.default_value != NULL)
1238 description.Printf ("[instance, %s] %s (default: '%s')", GetTypeString (entry.var_type),
1239 entry.description, entry.default_value);
1240 else
1241 description.Printf ("[instance, %s] %s (default: '')", GetTypeString (entry.var_type),
1242 entry.description);
1243 interpreter.OutputFormattedHelpText (result_stream, entry.var_name, "--", description.GetData(),
1244 max_len);
1245 }
1246 }
1247 }
1248 else if (num_pieces == 1)
1249 {
1250 ConstString var_name (names.GetArgumentAtIndex (0));
1251 bool is_global = false;
1252
1253 const SettingEntry *setting_entry = root->GetGlobalEntry (var_name);
1254
1255 if (setting_entry == NULL)
1256 setting_entry = root->GetInstanceEntry (var_name);
1257 else
1258 is_global = true;
1259
1260 // Check to see if it is a global or instance variable name.
1261 if (setting_entry != NULL)
1262 {
1263 StreamString description;
1264 if (setting_entry->var_type == lldb::eSetVarTypeEnum)
1265 {
1266 StreamString enum_values_str;
1267 UserSettingsController::PrintEnumValues (setting_entry->enum_values, enum_values_str);
1268 description.Printf ("[%s, enum] %s. Valid values: {%s} (default: '%s')",
1269 (is_global ? "static" : "instance"),
1270 setting_entry->description,
1271 enum_values_str.GetData(), setting_entry->enum_values[0].string_value);
1272 }
1273 else if (setting_entry->default_value != NULL)
1274 description.Printf ("[%s, %s] %s (default: '%s')",
1275 (is_global ? "static" : "instance"),
1276 GetTypeString (setting_entry->var_type),
1277 setting_entry->description, setting_entry->default_value);
1278 else
1279 description.Printf ("[%s, %s] %s (default: '')",
1280 (is_global ? "static" : "instance"),
1281 GetTypeString (setting_entry->var_type),
1282 setting_entry->description);
1283 interpreter.OutputFormattedHelpText (result_stream, setting_entry->var_name, "--", description.GetData(),
1284 var_name.GetLength());
1285 }
1286 else
1287 {
1288 // It must be a child name.
1289 int num_children = root->GetNumChildren();
1290 bool found = false;
1291 for (int i = 0; i < num_children && !found; ++i)
1292 {
1293 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1294 if (child)
1295 {
1296 ConstString child_prefix = child->GetLevelName();
1297 if (child_prefix == var_name)
1298 {
1299 found = true;
1300 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1301 var_name.AsCString(), result_stream, err);
1302 }
1303 }
1304 }
1305 if (!found)
1306 {
1307 std::string parent_prefix;
1308 root->BuildParentPrefix (parent_prefix);
1309 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1310 return;
1311 }
1312 }
1313 }
1314 else
1315 {
1316 // It must be a child name; find the child and call this function recursively on child.
1317 ConstString child_name (names.GetArgumentAtIndex (0));
1318
1319 StreamString rest_of_search_name;
1320 for (int i = 0; i < num_pieces; ++i)
1321 {
1322 rest_of_search_name.Printf ("%s", names.GetArgumentAtIndex (i));
1323 if ((i + 1) < num_pieces)
1324 rest_of_search_name.Printf (".");
1325 }
1326
1327 int num_children = root->GetNumChildren();
1328 bool found = false;
1329 for (int i = 0; i < num_children && !found; ++i)
1330 {
1331 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1332 if (child)
1333 {
1334 ConstString child_prefix = child->GetLevelName();
1335 if (child_prefix == child_name)
1336 {
1337 found = true;
1338 UserSettingsController::FindSettingsDescriptions (interpreter, child, current_prefix,
1339 rest_of_search_name.GetData(), result_stream,
1340 err);
1341 }
1342 }
1343 }
1344 if (!found)
1345 {
1346 std::string parent_prefix;
1347 root->BuildParentPrefix (parent_prefix);
1348 err.SetErrorStringWithFormat ("Cannot find match for '%s.%s'\n", parent_prefix.c_str(), search_name);
1349 return;
1350 }
1351 }
1352}
1353
1354void
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001355UserSettingsController::GetAllVariableValues (CommandInterpreter &interpreter,
1356 lldb::UserSettingsControllerSP root,
1357 std::string &current_prefix,
1358 StreamString &result_stream,
1359 Error &err)
1360{
1361 StreamString description;
1362 int num_entries = root->m_settings.global_settings.size();
1363 lldb::SettableVariableType var_type;
1364
1365
1366 for (int i = 0; i < num_entries; ++i)
1367 {
1368 StreamString full_var_name;
1369 SettingEntry entry = root->m_settings.global_settings[i];
Caroline Ticeded2fa32010-09-15 05:35:14 +00001370 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001371 full_var_name.Printf ("%s.%s", current_prefix.c_str(), entry.var_name);
1372 else
1373 full_var_name.Printf ("%s", entry.var_name);
Caroline Tice101c7c22010-09-09 06:25:08 +00001374 StringList value = root->GetVariable (full_var_name.GetData(), var_type,
Caroline Ticedaccaa92010-09-20 20:44:43 +00001375 interpreter.GetDebugger().GetInstanceName().AsCString(), err);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001376 description.Clear();
1377 if (value.GetSize() == 1)
Caroline Tice49e27372010-09-07 18:35:40 +00001378 description.Printf ("%s (%s) = '%s'", full_var_name.GetData(), GetTypeString (entry.var_type),
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001379 value.GetStringAtIndex (0));
1380 else
1381 {
Caroline Tice2d5289d2010-12-10 00:26:54 +00001382 description.Printf ("%s (%s):\n", full_var_name.GetData(), GetTypeString (entry.var_type));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001383 for (int j = 0; j < value.GetSize(); ++j)
Caroline Tice2d5289d2010-12-10 00:26:54 +00001384 if (entry.var_type == lldb::eSetVarTypeArray)
1385 description.Printf (" [%d]: '%s'\n", j, value.GetStringAtIndex (j));
1386 else if (entry.var_type == lldb::eSetVarTypeDictionary)
1387 description.Printf (" '%s'\n", value.GetStringAtIndex (j));
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001388 }
1389
1390 result_stream.Printf ("%s\n", description.GetData());
1391 }
1392
1393 root->GetAllInstanceVariableValues (interpreter, result_stream);
1394 root->GetAllPendingSettingValues (result_stream);
Caroline Tice101c7c22010-09-09 06:25:08 +00001395 if (root->GetLevelName().GetLength() > 0) // Don't bother with default values for Debugger level.
1396 root->GetAllDefaultSettingValues (result_stream);
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001397
1398
1399 // Now, recurse across all children.
1400 int num_children = root->GetNumChildren();
1401 for (int i = 0; i < num_children; ++i)
1402 {
1403 lldb::UserSettingsControllerSP child = root->GetChildAtIndex (i);
1404
1405 if (child)
1406 {
1407 ConstString child_prefix = child->GetLevelName();
1408 StreamString new_prefix;
Caroline Ticeded2fa32010-09-15 05:35:14 +00001409 if (! current_prefix.empty())
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001410 new_prefix.Printf ("%s.%s", current_prefix.c_str(), child_prefix.AsCString());
1411 else
1412 new_prefix.Printf ("%s", child_prefix.AsCString());
1413 std::string new_prefix_str = new_prefix.GetData();
1414 UserSettingsController::GetAllVariableValues (interpreter, child, new_prefix_str, result_stream,
1415 err);
1416 }
1417 }
1418
1419}
1420
1421Args
1422UserSettingsController::BreakNameIntoPieces (const char *full_dot_name)
1423{
1424 Args return_value;
1425 std::string name_string (full_dot_name);
1426 bool done = false;
1427
1428 std::string piece;
1429 std::string remainder (full_dot_name);
1430
1431 while (!done)
1432 {
1433 size_t idx = remainder.find_first_of ('.');
1434 piece = remainder.substr (0, idx);
1435 return_value.AppendArgument (piece.c_str());
1436 if (idx != std::string::npos)
1437 remainder = remainder.substr (idx+1);
1438 else
1439 done = true;
1440 }
1441
1442 return return_value;
1443}
1444
1445bool
1446UserSettingsController::IsLiveInstance (const std::string &instance_name)
1447{
1448 std::map<std::string, InstanceSettings *>::iterator pos;
1449
1450 pos = m_live_settings.find (instance_name);
1451 if (pos != m_live_settings.end())
1452 return true;
1453
1454 return false;
1455}
1456
1457int
1458UserSettingsController::CompleteSettingsValue (lldb::UserSettingsControllerSP root_settings,
1459 const char *full_dot_name,
1460 const char *partial_value,
1461 bool &word_complete,
1462 StringList &matches)
1463{
1464 Args names = UserSettingsController::BreakNameIntoPieces (full_dot_name);
1465 int num_pieces = names.GetArgumentCount();
1466 word_complete = true;
1467
1468 ConstString root_level = root_settings->GetLevelName();
1469 int num_extra_levels = num_pieces - 2;
1470 if ((num_extra_levels > 0)
1471 && root_level.GetLength() > 0)
1472 {
1473 ConstString current_level (names.GetArgumentAtIndex (0));
1474 if (current_level == root_level)
1475 {
1476 names.Shift();
1477 --num_extra_levels;
1478 }
1479 else
1480 return 0;
1481 }
1482
1483 for (int i = 0; i < num_extra_levels; ++i)
1484 {
1485 ConstString child_level (names.GetArgumentAtIndex (0));
1486 bool found = false;
1487 int num_children = root_settings->GetNumChildren();
1488 for (int j = 0; j < num_children && !found; ++j)
1489 {
1490 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1491 {
1492 found = true;
1493 root_settings = root_settings->GetChildAtIndex (j);
1494 names.Shift();
1495 }
1496 }
1497 if (!found)
1498 return 0;
1499 }
1500
1501 if (names.GetArgumentCount() != 2)
1502 return 0;
1503
1504 std::string next_name (names.GetArgumentAtIndex (0));
1505 int len = next_name.length();
1506 names.Shift();
1507
1508 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1509 {
1510 // 'next_name' is instance name. Instance names are irrelevent here.
1511 }
1512 else
1513 {
1514 // 'next_name' is child name.
1515 bool found = false;
1516 int num_children = root_settings->GetNumChildren();
1517 ConstString child_level (next_name.c_str());
1518 for (int j = 0; j < num_children && !found; ++j)
1519 {
1520 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1521 {
1522 found = true;
1523 root_settings = root_settings->GetChildAtIndex (j);
1524 }
1525 }
1526 if (!found)
1527 return 0;
1528 }
1529
1530 ConstString var_name (names.GetArgumentAtIndex(0));
1531 const SettingEntry *entry = root_settings->GetGlobalEntry (var_name);
1532 if (entry == NULL)
1533 entry = root_settings->GetInstanceEntry (var_name);
1534
1535 if (entry == NULL)
1536 return 0;
1537
Jim Ingham06e827c2010-11-11 19:26:09 +00001538 if (entry->var_type == lldb::eSetVarTypeBoolean)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00001539 return UserSettingsController::BooleanMatches (partial_value, word_complete, matches);
1540 else if (entry->var_type == lldb::eSetVarTypeEnum)
1541 return UserSettingsController::EnumMatches (partial_value, entry->enum_values, word_complete, matches);
1542 else
1543 return 0;
1544}
1545
1546int
1547UserSettingsController::BooleanMatches (const char *partial_value,
1548 bool &word_complete,
1549 StringList &matches)
1550{
1551 static const std::string true_string ("true");
1552 static const std::string false_string ("false");
1553
1554 if (partial_value == NULL)
1555 {
1556 matches.AppendString ("true");
1557 matches.AppendString ("false");
1558 }
1559 else
1560 {
1561 int partial_len = strlen (partial_value);
1562
1563 if ((partial_len <= true_string.length())
1564 && (true_string.find (partial_value) == 0))
1565 matches.AppendString ("true");
1566 else if ((partial_len <= false_string.length())
1567 && (false_string.find (partial_value) == 0))
1568 matches.AppendString ("false");
1569 }
1570
1571 word_complete = false;
1572 if (matches.GetSize() == 1)
1573 word_complete = true;
1574
1575 return matches.GetSize();
1576}
1577
1578int
1579UserSettingsController::EnumMatches (const char *partial_value,
1580 lldb::OptionEnumValueElement *enum_values,
1581 bool &word_complete,
1582 StringList &matches)
1583{
1584 int len = (partial_value != NULL) ? strlen (partial_value) : 0;
1585
1586 int i = 0;
1587 while (enum_values[i].string_value != NULL)
1588 {
1589 if (len == 0)
1590 matches.AppendString (enum_values[i].string_value);
1591 else
1592 {
1593 std::string tmp_value (enum_values[i].string_value);
1594 if ((len <= tmp_value.length())
1595 && tmp_value.find (partial_value) == 0)
1596 matches.AppendString (enum_values[i].string_value);
1597 }
1598 ++i;
1599 }
1600
1601 word_complete = false;
1602 if (matches.GetSize() == 1)
1603 word_complete = true;
1604
1605 return matches.GetSize();
1606}
1607
1608int
1609UserSettingsController::CompleteSettingsNames (lldb::UserSettingsControllerSP root_settings,
1610 Args &partial_setting_name_pieces,
1611 bool &word_complete,
1612 StringList &matches)
1613{
1614 int num_matches = 0;
1615 int num_name_pieces = partial_setting_name_pieces.GetArgumentCount();
1616
1617 if (num_name_pieces > 1)
1618 {
1619 // There are at least two pieces, perhaps with multiple level names preceding them.
1620 // First traverse all the extra levels, until we have exactly two pieces left.
1621
1622 int num_extra_levels = num_name_pieces - 2;
1623
1624 // Deal with current level first.
1625
1626 ConstString root_level = root_settings->GetLevelName();
1627 if ((num_extra_levels > 0)
1628 && (root_level.GetLength() > 0))
1629 {
1630 ConstString current_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1631 if (current_level == root_level)
1632 {
1633 partial_setting_name_pieces.Shift();
1634 --num_extra_levels;
1635 }
1636 else
1637 return 0; // The current level did not match the name pieces; something is wrong, so return immediately
1638
1639 }
1640
1641 for (int i = 0; i < num_extra_levels; ++i)
1642 {
1643 ConstString child_level (partial_setting_name_pieces.GetArgumentAtIndex (0));
1644 bool found = false;
1645 int num_children = root_settings->GetNumChildren();
1646 for (int j = 0; j < num_children && !found; ++j)
1647 {
1648 if (root_settings->GetChildAtIndex (j)->GetLevelName() == child_level)
1649 {
1650 found = true;
1651 root_settings = root_settings->GetChildAtIndex (j);
1652 partial_setting_name_pieces.Shift();
1653 }
1654 }
1655 if (! found)
1656 {
1657 return 0; // Unable to find a matching child level name; something is wrong, so return immediately.
1658 }
1659 }
1660
1661 // Now there should be exactly two name pieces left. If not there is an error, so return immediately
1662
1663 if (partial_setting_name_pieces.GetArgumentCount() != 2)
1664 return 0;
1665
1666 std::string next_name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1667 int len = next_name.length();
1668 partial_setting_name_pieces.Shift();
1669
1670 if ((next_name[0] == '[') && (next_name[len-1] == ']'))
1671 {
1672 // 'next_name' is an instance name. The last name piece must be a non-empty partial match against an
1673 // instance_name, assuming 'next_name' is valid.
1674
1675 if (root_settings->IsLiveInstance (next_name))
1676 {
1677 std::string complete_prefix;
1678 root_settings->BuildParentPrefix (complete_prefix);
1679
1680 num_matches = root_settings->InstanceVariableMatches(partial_setting_name_pieces.GetArgumentAtIndex(0),
1681 complete_prefix,
1682 next_name.c_str(),
1683 matches);
1684 word_complete = true;
1685 if (num_matches > 1)
1686 word_complete = false;
1687
1688 return num_matches;
1689 }
1690 else
1691 return 0; // Invalid instance_name
1692 }
1693 else
1694 {
1695 // 'next_name' must be a child name. Find the correct child and pass the remaining piece to be resolved.
1696 bool found = false;
1697 int num_children = root_settings->GetNumChildren();
1698 ConstString child_level (next_name.c_str());
1699 for (int i = 0; i < num_children; ++i)
1700 {
1701 if (root_settings->GetChildAtIndex (i)->GetLevelName() == child_level)
1702 {
1703 found = true;
1704 return UserSettingsController::CompleteSettingsNames (root_settings->GetChildAtIndex (i),
1705 partial_setting_name_pieces,
1706 word_complete, matches);
1707 }
1708 }
1709 if (!found)
1710 return 0;
1711 }
1712 }
1713 else if (num_name_pieces == 1)
1714 {
1715 std::string complete_prefix;
1716 root_settings->BuildParentPrefix (complete_prefix);
1717
1718 word_complete = true;
1719 std::string name (partial_setting_name_pieces.GetArgumentAtIndex (0));
1720
1721 if (name[0] == '[')
1722 {
1723 // It's a partial instance name.
1724
1725 num_matches = root_settings->LiveInstanceMatches (name.c_str(), complete_prefix, word_complete, matches);
1726 }
1727 else
1728 {
1729 // It could be anything *except* an instance name...
1730
1731 num_matches = root_settings->GlobalVariableMatches (name.c_str(), complete_prefix, matches);
1732 num_matches += root_settings->InstanceVariableMatches (name.c_str(), complete_prefix, NULL, matches);
1733 num_matches += root_settings->ChildMatches (name.c_str(), complete_prefix, word_complete, matches);
1734 }
1735
1736 if (num_matches > 1)
1737 word_complete = false;
1738
1739 return num_matches;
1740 }
1741 else
1742 {
1743 // We have a user settings controller with a blank partial string. Return everything possible at this level.
1744
1745 std::string complete_prefix;
1746 root_settings->BuildParentPrefix (complete_prefix);
1747 num_matches = root_settings->GlobalVariableMatches (NULL, complete_prefix, matches);
1748 num_matches += root_settings->InstanceVariableMatches (NULL, complete_prefix, NULL, matches);
1749 num_matches += root_settings->LiveInstanceMatches (NULL, complete_prefix, word_complete, matches);
1750 num_matches += root_settings->ChildMatches (NULL, complete_prefix, word_complete, matches);
1751 word_complete = false;
1752 return num_matches;
1753 }
1754
1755 return num_matches;
1756}
1757
1758int
1759UserSettingsController::GlobalVariableMatches (const char *partial_name,
1760 const std::string &complete_prefix,
1761 StringList &matches)
1762{
1763 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1764 int num_matches = 0;
1765
1766 for (size_t i = 0; i < m_settings.global_settings.size(); ++i)
1767 {
1768 SettingEntry &entry = m_settings.global_settings[i];
1769 std::string var_name (entry.var_name);
1770 if ((partial_len == 0)
1771 || ((partial_len <= var_name.length())
1772 && (var_name.find (partial_name) == 0)))
1773 {
1774 StreamString match_name;
1775 if (complete_prefix.length() > 0)
1776 {
1777 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1778 matches.AppendString (match_name.GetData());
1779 }
1780 else
1781 matches.AppendString (var_name.c_str());
1782 ++num_matches;
1783 }
1784 }
1785 return num_matches;
1786}
1787
1788int
1789UserSettingsController::InstanceVariableMatches (const char *partial_name,
1790 const std::string &complete_prefix,
1791 const char *instance_name,
1792 StringList &matches)
1793{
1794 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1795 int num_matches = 0;
1796
1797 for (size_t i = 0; i < m_settings.instance_settings.size(); ++i)
1798 {
1799 SettingEntry &entry = m_settings.instance_settings[i];
1800 std::string var_name (entry.var_name);
1801 if ((partial_len == 0)
1802 || ((partial_len <= var_name.length())
1803 && (var_name.find (partial_name) == 0)))
1804 {
1805 StreamString match_name;
1806 if (complete_prefix.length() > 0)
1807 {
1808 if (instance_name != NULL)
1809 match_name.Printf ("%s.%s.%s", complete_prefix.c_str(), instance_name, var_name.c_str());
1810 else
1811 match_name.Printf ("%s.%s", complete_prefix.c_str(), var_name.c_str());
1812
1813 matches.AppendString (match_name.GetData());
1814 }
1815 else
1816 {
1817 if (instance_name != NULL)
1818 {
1819 match_name.Printf ("%s.%s", instance_name, var_name.c_str());
1820 matches.AppendString (match_name.GetData());
1821 }
1822 else
1823 matches.AppendString (var_name.c_str());
1824 }
1825 ++num_matches;
1826 }
1827 }
1828 return num_matches;
1829}
1830
1831int
1832UserSettingsController::LiveInstanceMatches (const char *partial_name,
1833 const std::string &complete_prefix,
1834 bool &word_complete,
1835 StringList &matches)
1836{
1837 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1838 int num_matches = 0;
1839
1840 std::map<std::string, InstanceSettings*>::iterator pos;
1841 for (pos = m_live_settings.begin(); pos != m_live_settings.end(); ++pos)
1842 {
1843 std::string instance_name = pos->first;
1844 if ((partial_len == 0)
1845 || ((partial_len <= instance_name.length())
1846 && (instance_name.find (partial_name) == 0)))
1847 {
1848 StreamString match_name;
1849 if (complete_prefix.length() > 0)
1850 match_name.Printf ("%s.%s.", complete_prefix.c_str(), instance_name.c_str());
1851 else
1852 match_name.Printf ("%s.", instance_name.c_str());
1853 matches.AppendString (match_name.GetData());
1854 ++num_matches;
1855 }
1856 }
1857
1858 if (num_matches > 0)
1859 word_complete = false;
1860
1861 return num_matches;
1862}
1863
1864int
1865UserSettingsController::ChildMatches (const char *partial_name,
1866 const std::string &complete_prefix,
1867 bool &word_complete,
1868 StringList &matches)
1869{
1870 int partial_len = (partial_name != NULL) ? strlen (partial_name) : 0;
1871 int num_children = GetNumChildren();
1872 int num_matches = 0;
1873 for (int i = 0; i < num_children; ++i)
1874 {
1875 std::string child_name (GetChildAtIndex(i)->GetLevelName().AsCString());
1876 StreamString match_name;
1877 if ((partial_len == 0)
1878 || ((partial_len <= child_name.length())
1879 && (child_name.find (partial_name) == 0)))
1880 {
1881 if (complete_prefix.length() > 0)
1882 match_name.Printf ("%s.%s.", complete_prefix.c_str(), child_name.c_str());
1883 else
1884 match_name.Printf ("%s.", child_name.c_str());
1885 matches.AppendString (match_name.GetData());
1886 ++num_matches;
1887 }
1888 }
1889
1890 if (num_matches > 0)
1891 word_complete = false;
1892
1893 return num_matches;
1894}
1895
1896void
1897UserSettingsController::VerifyOperationForType (lldb::SettableVariableType var_type,
1898 lldb::VarSetOperationType op,
1899 const ConstString &var_name,
1900 Error &err)
1901{
1902 if (op == lldb::eVarSetOperationAssign)
1903 return;
1904
1905
1906 if (op == lldb::eVarSetOperationInvalid)
1907 {
1908 err.SetErrorString ("Invalid 'settings ' subcommand operation.\n");
1909 return;
1910 }
1911
1912 switch (op)
1913 {
1914 case lldb::eVarSetOperationInsertBefore:
1915 case lldb::eVarSetOperationInsertAfter:
1916 if (var_type != lldb::eSetVarTypeArray)
1917 err.SetErrorString ("Invalid operation: This operation can only be performed on array variables.\n");
1918 break;
1919 case lldb::eVarSetOperationReplace:
1920 case lldb::eVarSetOperationRemove:
1921 if ((var_type != lldb::eSetVarTypeArray)
1922 && (var_type != lldb::eSetVarTypeDictionary))
1923 err.SetErrorString ("Invalid operation: This operation can only be performed on array or dictionary"
1924 " variables.\n");
1925 break;
1926 case lldb::eVarSetOperationAppend:
1927 case lldb::eVarSetOperationClear:
1928 if ((var_type != lldb::eSetVarTypeArray)
1929 && (var_type != lldb::eSetVarTypeDictionary)
1930 && (var_type != lldb::eSetVarTypeString))
1931 err.SetErrorString ("Invalid operation: This operation can only be performed on array, dictionary "
1932 "or string variables.\n");
1933 break;
1934 default:
1935 break;
1936 }
1937
1938 return;
1939}
1940
1941void
1942UserSettingsController::UpdateStringVariable (lldb::VarSetOperationType op,
1943 std::string &string_var,
1944 const char *new_value,
1945 Error &err)
1946{
1947 if (op == lldb::eVarSetOperationAssign)
1948 string_var = new_value;
1949 else if (op == lldb::eVarSetOperationAppend)
1950 string_var.append (new_value);
1951 else if (op == lldb::eVarSetOperationClear)
1952 string_var.clear();
1953 else
1954 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
1955}
1956
1957void
1958UserSettingsController::UpdateBooleanVariable (lldb::VarSetOperationType op,
1959 bool &bool_var,
1960 const char *new_value,
1961 Error &err)
1962{
1963 if (op != lldb::eVarSetOperationAssign)
1964 err.SetErrorString ("Invalid operation for Boolean variable. Cannot update value.\n");
1965
1966
1967 if ((new_value == NULL)
1968 || (new_value[0] == '\0'))
1969 err.SetErrorString ("Invalid value. Cannot perform update.\n");
1970
1971 std::string bool_val_str (new_value);
1972
1973 std::transform (bool_val_str.begin(), bool_val_str.end(), bool_val_str.begin(), ::tolower);
1974
1975 if (bool_val_str == "true")
1976 bool_var = true;
1977 else if (bool_val_str == "false")
1978 bool_var = false;
1979}
1980
1981void
1982UserSettingsController::UpdateStringArrayVariable (lldb::VarSetOperationType op,
1983 const char *index_value,
1984 Args &array_var,
1985 const char *new_value,
1986 Error &err)
1987{
1988 int index = -1;
1989 bool valid_index = true;
1990
1991 if (index_value != NULL)
1992 {
1993 for (int i = 0; i < strlen(index_value); ++i)
1994 if (!isdigit (index_value[i]))
1995 {
1996 valid_index = false;
1997 err.SetErrorStringWithFormat ("'%s' is not a valid integer index. Cannot update array value.\n",
1998 index_value);
1999 }
2000
2001 if (valid_index)
2002 index = atoi (index_value);
2003
2004 if (index < 0
2005 || index >= array_var.GetArgumentCount())
2006 {
2007 valid_index = false;
2008 err.SetErrorStringWithFormat ("%d is outside the bounds of the specified array variable. "
2009 "Cannot update array value.\n", index);
2010 }
2011 }
2012
2013 switch (op)
2014 {
2015 case lldb::eVarSetOperationAssign:
2016 array_var.SetCommandString (new_value);
2017 break;
2018 case lldb::eVarSetOperationReplace:
2019 {
2020 if (valid_index)
2021 array_var.ReplaceArgumentAtIndex (index, new_value);
2022 break;
2023 }
2024 case lldb::eVarSetOperationInsertBefore:
2025 case lldb::eVarSetOperationInsertAfter:
2026 {
2027 if (valid_index)
2028 {
2029 Args new_array (new_value);
2030 if (op == lldb::eVarSetOperationInsertAfter)
2031 ++index;
2032 for (int i = 0; i < new_array.GetArgumentCount(); ++i)
2033 array_var.InsertArgumentAtIndex (index, new_array.GetArgumentAtIndex (i));
2034 }
2035 break;
2036 }
2037 case lldb::eVarSetOperationRemove:
2038 {
2039 if (valid_index)
2040 array_var.DeleteArgumentAtIndex (index);
2041 break;
2042 }
2043 case lldb::eVarSetOperationAppend:
2044 {
2045 Args new_array (new_value);
2046 array_var.AppendArguments (new_array);
2047 break;
2048 }
2049 case lldb::eVarSetOperationClear:
2050 array_var.Clear();
2051 break;
2052 default:
2053 err.SetErrorString ("Unrecognized operation. Cannot update value.\n");
2054 break;
2055 }
2056}
2057
2058void
2059UserSettingsController::UpdateDictionaryVariable (lldb::VarSetOperationType op,
2060 const char *index_value,
2061 std::map<std::string, std::string> &dictionary,
2062 const char *new_value,
2063 Error &err)
2064{
2065 switch (op)
2066 {
2067 case lldb::eVarSetOperationReplace:
2068 if (index_value != NULL)
2069 {
2070 std::string key (index_value);
2071 std::map<std::string, std::string>::iterator pos;
2072
2073 pos = dictionary.find (key);
2074 if (pos != dictionary.end())
2075 dictionary[key] = new_value;
2076 else
2077 err.SetErrorStringWithFormat ("'%s' is not an existing key; cannot replace value.\n", index_value);
2078 }
2079 else
2080 err.SetErrorString ("'settings replace' requires a key for dictionary variables. No key supplied.\n");
2081 break;
2082 case lldb::eVarSetOperationRemove:
2083 if (index_value != NULL)
2084 {
2085 std::string key (index_value);
2086 dictionary.erase (key);
2087 }
2088 else
2089 err.SetErrorString ("'settings remove' requires a key for dictionary variables. No key supplied.\n");
2090 break;
2091 case lldb::eVarSetOperationClear:
2092 dictionary.clear ();
2093 break;
2094 case lldb::eVarSetOperationAppend:
2095 case lldb::eVarSetOperationAssign:
2096 {
Johnny Chen73b4f712010-10-20 01:03:00 +00002097 // Clear the dictionary if it's an assign with new_value as NULL.
2098 if (new_value == NULL && op == lldb::eVarSetOperationAssign)
2099 {
2100 dictionary.clear ();
2101 break;
2102 }
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002103 Args args (new_value);
2104 size_t num_args = args.GetArgumentCount();
2105 for (size_t i = 0; i < num_args; ++i)
2106 {
2107 std::string tmp_arg = args.GetArgumentAtIndex (i);
2108 size_t eq_sign = tmp_arg.find ('=');
2109 if (eq_sign != std::string::npos)
2110 {
2111 if (eq_sign > 4)
2112 {
2113 std::string tmp_key = tmp_arg.substr (0, eq_sign);
2114 std::string real_value = tmp_arg.substr (eq_sign+1);
2115 if ((tmp_key[0] == '[')
2116 && (tmp_key[1] == '"')
2117 && (tmp_key[eq_sign-2] == '"')
2118 && (tmp_key[eq_sign-1] == ']'))
2119 {
2120 std::string real_key = tmp_key.substr (2, eq_sign-4);
2121 dictionary[real_key] = real_value;
2122 }
2123 else
2124 err.SetErrorString ("Invalid key format for dictionary assignment. "
2125 "Expected '[\"<key>\"]'\n");
2126 }
2127 else
2128 err.SetErrorString ("Invalid key format for dictionary assignment. "
2129 "Expected '[\"<key>\"]'\n");
2130 }
2131 else
2132 err.SetErrorString ("Invalid format for dictionary value. Expected '[\"<key>\"]=<value>'\n");
2133 }
2134 }
2135 break;
2136 case lldb::eVarSetOperationInsertBefore:
2137 case lldb::eVarSetOperationInsertAfter:
2138 err.SetErrorString ("Specified operation cannot be performed on dictionary variables.\n");
2139 break;
2140 default:
2141 err.SetErrorString ("Unrecognized operation.\n");
2142 break;
2143 }
2144}
2145
2146const char *
2147UserSettingsController::EnumToString (const lldb::OptionEnumValueElement *enum_values,
2148 int value)
2149{
2150 int i = 0;
2151 while (enum_values[i].string_value != NULL)
2152 {
2153 if (enum_values[i].value == value)
2154 return enum_values[i].string_value;
2155 ++i;
2156 }
2157
2158 return "Invalid enumeration value";
2159}
2160
2161
2162void
2163UserSettingsController::UpdateEnumVariable (lldb::OptionEnumValueElement *enum_values,
2164 int *enum_var,
2165 const char *new_value,
2166 Error &err)
2167{
2168 bool found_one;
2169
2170 *enum_var = Args::StringToOptionEnum (new_value, enum_values, enum_values[0].value, &found_one);
2171
2172 if (!found_one)
2173 err.SetErrorString ("Invalid enumeration value; cannot update variable.\n");
2174}
2175
Caroline Ticeded2fa32010-09-15 05:35:14 +00002176void
2177UserSettingsController::RenameInstanceSettings (const char *old_name, const char *new_name)
2178{
2179 Mutex::Locker live_mutex (m_live_settings_mutex);
2180 Mutex::Locker pending_mutex (m_pending_settings_mutex);
2181 std::string old_name_key (old_name);
2182 std::string new_name_key (new_name);
2183
2184 // First, find the live instance settings for the old_name. If they don't exist in the live settings
2185 // list, then this is not a setting that can be renamed.
2186
2187 if ((old_name_key[0] != '[') || (old_name_key[old_name_key.size() -1] != ']'))
Caroline Tice1559a462010-09-27 00:30:10 +00002188 {
Caroline Ticeded2fa32010-09-15 05:35:14 +00002189 StreamString tmp_str;
2190 tmp_str.Printf ("[%s]", old_name);
2191 old_name_key = tmp_str.GetData();
Caroline Tice1559a462010-09-27 00:30:10 +00002192 }
Caroline Ticeded2fa32010-09-15 05:35:14 +00002193
2194 if ((new_name_key[0] != '[') || (new_name_key[new_name_key.size() -1] != ']'))
Caroline Tice1559a462010-09-27 00:30:10 +00002195 {
Caroline Ticeded2fa32010-09-15 05:35:14 +00002196 StreamString tmp_str;
2197 tmp_str.Printf ("[%s]", new_name);
2198 new_name_key = tmp_str.GetData();
Caroline Tice1559a462010-09-27 00:30:10 +00002199 }
2200
2201 if (old_name_key.compare (new_name_key) == 0)
2202 return;
2203
2204 size_t len = new_name_key.length();
2205 std::string stripped_new_name = new_name_key.substr (1, len-2); // new name without the '[ ]'
Caroline Ticeded2fa32010-09-15 05:35:14 +00002206
2207 std::map<std::string, InstanceSettings *>::iterator pos;
2208
2209 pos = m_live_settings.find (old_name_key);
2210 if (pos != m_live_settings.end())
2211 {
2212 InstanceSettings *live_settings = pos->second;
2213
2214 // Rename the settings.
Caroline Tice1559a462010-09-27 00:30:10 +00002215 live_settings->ChangeInstanceName (stripped_new_name);
Caroline Ticeded2fa32010-09-15 05:35:14 +00002216
2217 // Now see if there are any pending settings for the new name; if so, copy them into live_settings.
2218 std::map<std::string, lldb::InstanceSettingsSP>::iterator pending_pos;
2219 pending_pos = m_pending_settings.find (new_name_key);
2220 if (pending_pos != m_pending_settings.end())
2221 {
2222 lldb::InstanceSettingsSP pending_settings_sp = pending_pos->second;
2223 live_settings->CopyInstanceSettings (pending_settings_sp, false);
2224 }
2225
2226 // Erase the old entry (under the old name) from live settings.
2227 m_live_settings.erase (pos);
2228
2229 // Add the new entry, with the new name, into live settings.
2230 m_live_settings[new_name_key] = live_settings;
2231 }
2232}
2233
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002234//----------------------------------------------------------------------
2235// class InstanceSettings
2236//----------------------------------------------------------------------
2237
Caroline Tice91123da2010-09-08 17:48:55 +00002238InstanceSettings::InstanceSettings (UserSettingsController &owner, const char *instance_name, bool live_instance) :
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002239 m_owner (owner),
2240 m_instance_name (instance_name)
2241{
Caroline Tice91123da2010-09-08 17:48:55 +00002242 if ((m_instance_name != InstanceSettings::GetDefaultName())
Caroline Tice9e41c152010-09-16 19:05:55 +00002243 && (m_instance_name != InstanceSettings::InvalidName())
Caroline Tice91123da2010-09-08 17:48:55 +00002244 && live_instance)
Caroline Tice3df9a8d2010-09-04 00:03:46 +00002245 m_owner.RegisterInstanceSettings (this);
2246}
2247
2248InstanceSettings::~InstanceSettings ()
2249{
2250 if (m_instance_name != InstanceSettings::GetDefaultName())
2251 m_owner.UnregisterInstanceSettings (this);
2252}
2253
2254const ConstString &
2255InstanceSettings::GetDefaultName ()
2256{
2257 static const ConstString g_default_settings_name ("[DEFAULT]");
2258
2259 return g_default_settings_name;
2260}
Caroline Ticeded2fa32010-09-15 05:35:14 +00002261
Caroline Tice9e41c152010-09-16 19:05:55 +00002262const ConstString &
2263InstanceSettings::InvalidName ()
2264{
2265 static const ConstString g_invalid_name ("Invalid instance name");
2266
2267 return g_invalid_name;
2268}
2269
Caroline Ticeded2fa32010-09-15 05:35:14 +00002270void
2271InstanceSettings::ChangeInstanceName (const std::string &new_instance_name)
2272{
2273 m_instance_name.SetCString (new_instance_name.c_str());
2274}
2275
2276