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