blob: 05ba89cf6e2138ec1273a4936e42b062732efba9 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectLog.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
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner24943d22010-06-08 16:52:24 +000012#include "CommandObjectLog.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/lldb-private-log.h"
19
Jim Ingham84cdc152010-06-15 19:49:27 +000020#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Core/Debugger.h"
Greg Clayton5f54ac32011-02-08 05:05:52 +000022#include "lldb/Host/FileSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Core/Log.h"
24#include "lldb/Core/Module.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000025#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000026#include "lldb/Core/RegularExpression.h"
27#include "lldb/Core/Stream.h"
28#include "lldb/Core/StreamFile.h"
29#include "lldb/Core/Timer.h"
30
Greg Clayton63094e02010-06-23 01:19:29 +000031#include "lldb/Core/Debugger.h"
Sean Callanan705d6782010-06-23 21:28:25 +000032#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033#include "lldb/Interpreter/CommandReturnObject.h"
34
35#include "lldb/Symbol/LineTable.h"
36#include "lldb/Symbol/ObjectFile.h"
37#include "lldb/Symbol/SymbolFile.h"
38#include "lldb/Symbol/SymbolVendor.h"
39
40#include "lldb/Target/Process.h"
41#include "lldb/Target/Target.h"
42
43using namespace lldb;
44using namespace lldb_private;
45
46
Jim Inghamda26bd22012-06-08 21:56:10 +000047class CommandObjectLogEnable : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +000048{
49public:
50 //------------------------------------------------------------------
51 // Constructors and Destructors
52 //------------------------------------------------------------------
Greg Clayton238c0a12010-09-18 01:14:36 +000053 CommandObjectLogEnable(CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +000054 CommandObjectParsed (interpreter,
55 "log enable",
56 "Enable logging for a single log channel.",
57 NULL),
Greg Claytonf15996e2011-04-07 22:46:35 +000058 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +000059 {
Caroline Tice7826c882010-10-26 03:11:13 +000060
61 CommandArgumentEntry arg1;
62 CommandArgumentEntry arg2;
Caroline Tice43b014a2010-10-04 22:28:36 +000063 CommandArgumentData channel_arg;
Caroline Tice7826c882010-10-26 03:11:13 +000064 CommandArgumentData category_arg;
Caroline Tice43b014a2010-10-04 22:28:36 +000065
66 // Define the first (and only) variant of this arg.
67 channel_arg.arg_type = eArgTypeLogChannel;
68 channel_arg.arg_repetition = eArgRepeatPlain;
69
70 // There is only one variant this argument could be; put it into the argument entry.
Caroline Tice7826c882010-10-26 03:11:13 +000071 arg1.push_back (channel_arg);
Caroline Tice43b014a2010-10-04 22:28:36 +000072
Caroline Tice7826c882010-10-26 03:11:13 +000073 category_arg.arg_type = eArgTypeLogCategory;
74 category_arg.arg_repetition = eArgRepeatPlus;
75
76 arg2.push_back (category_arg);
77
Caroline Tice43b014a2010-10-04 22:28:36 +000078 // Push the data for the first argument into the m_arguments vector.
Caroline Tice7826c882010-10-26 03:11:13 +000079 m_arguments.push_back (arg1);
80 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +000081 }
82
83 virtual
84 ~CommandObjectLogEnable()
85 {
86 }
87
88 Options *
89 GetOptions ()
90 {
91 return &m_options;
92 }
93
Greg Clayton5e342f52011-04-13 22:47:15 +000094// int
95// HandleArgumentCompletion (Args &input,
96// int &cursor_index,
97// int &cursor_char_position,
98// OptionElementVector &opt_element_vector,
99// int match_start_point,
100// int max_return_elements,
101// bool &word_complete,
102// StringList &matches)
103// {
104// std::string completion_str (input.GetArgumentAtIndex(cursor_index));
105// completion_str.erase (cursor_char_position);
106//
107// if (cursor_index == 1)
108// {
109// //
110// Log::AutoCompleteChannelName (completion_str.c_str(), matches);
111// }
112// return matches.GetSize();
113// }
114//
Chris Lattner24943d22010-06-08 16:52:24 +0000115
116 class CommandOptions : public Options
117 {
118 public:
119
Greg Claytonf15996e2011-04-07 22:46:35 +0000120 CommandOptions (CommandInterpreter &interpreter) :
121 Options (interpreter),
Chris Lattner24943d22010-06-08 16:52:24 +0000122 log_file (),
123 log_options (0)
124 {
125 }
126
127
128 virtual
129 ~CommandOptions ()
130 {
131 }
132
133 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000134 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000135 {
136 Error error;
Greg Clayton6475c422012-12-04 00:32:51 +0000137 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner24943d22010-06-08 16:52:24 +0000138
139 switch (short_option)
140 {
141 case 'f': log_file = option_arg; break;
142 case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; break;
143 case 'v': log_options |= LLDB_LOG_OPTION_VERBOSE; break;
144 case 'g': log_options |= LLDB_LOG_OPTION_DEBUG; break;
145 case 's': log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE; break;
146 case 'T': log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP; break;
147 case 'p': log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
148 case 'n': log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; break;
Greg Claytonf737d372012-10-08 22:41:53 +0000149 case 'S': log_options |= LLDB_LOG_OPTION_BACKTRACE; break;
Chris Lattner24943d22010-06-08 16:52:24 +0000150 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000151 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000152 break;
153 }
154
155 return error;
156 }
157
158 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000159 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000160 {
Chris Lattner24943d22010-06-08 16:52:24 +0000161 log_file.clear();
162 log_options = 0;
163 }
164
Greg Claytonb3448432011-03-24 21:19:54 +0000165 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000166 GetDefinitions ()
167 {
168 return g_option_table;
169 }
170
171 // Options table: Required for subclasses of Options.
172
Greg Claytonb3448432011-03-24 21:19:54 +0000173 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000174
175 // Instance variables to hold the values for command options.
176
177 std::string log_file;
178 uint32_t log_options;
179 };
180
181protected:
Jim Inghamda26bd22012-06-08 21:56:10 +0000182 virtual bool
183 DoExecute (Args& args,
184 CommandReturnObject &result)
185 {
186 if (args.GetArgumentCount() < 2)
187 {
188 result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
189 }
190 else
191 {
192 std::string channel(args.GetArgumentAtIndex(0));
193 args.Shift (); // Shift off the channel
194 bool success = m_interpreter.GetDebugger().EnableLog (channel.c_str(),
195 args.GetConstArgumentVector(),
196 m_options.log_file.c_str(),
197 m_options.log_options,
198 result.GetErrorStream());
199 if (success)
200 result.SetStatus (eReturnStatusSuccessFinishNoResult);
201 else
202 result.SetStatus (eReturnStatusFailed);
203 }
204 return result.Succeeded();
205 }
206
Chris Lattner24943d22010-06-08 16:52:24 +0000207 CommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000208};
209
Greg Claytonb3448432011-03-24 21:19:54 +0000210OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000211CommandObjectLogEnable::CommandOptions::g_option_table[] =
212{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000213{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Set the destination file to log to."},
214{ LLDB_OPT_SET_1, false, "threadsafe", 't', no_argument, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
215{ LLDB_OPT_SET_1, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose logging." },
216{ LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable debug logging." },
217{ LLDB_OPT_SET_1, false, "sequence", 's', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
218{ LLDB_OPT_SET_1, false, "timestamp", 'T', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
219{ LLDB_OPT_SET_1, false, "pid-tid", 'p', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." },
220{ LLDB_OPT_SET_1, false, "thread-name",'n', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." },
Greg Claytonf737d372012-10-08 22:41:53 +0000221{ LLDB_OPT_SET_1, false, "stack", 'S', no_argument, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
Caroline Tice4d6675c2010-10-01 19:59:14 +0000222{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000223};
224
Jim Inghamda26bd22012-06-08 21:56:10 +0000225class CommandObjectLogDisable : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000226{
227public:
228 //------------------------------------------------------------------
229 // Constructors and Destructors
230 //------------------------------------------------------------------
Greg Clayton238c0a12010-09-18 01:14:36 +0000231 CommandObjectLogDisable(CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000232 CommandObjectParsed (interpreter,
233 "log disable",
234 "Disable one or more log channel categories.",
235 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000236 {
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000237 CommandArgumentEntry arg1;
238 CommandArgumentEntry arg2;
Caroline Tice43b014a2010-10-04 22:28:36 +0000239 CommandArgumentData channel_arg;
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000240 CommandArgumentData category_arg;
Caroline Tice43b014a2010-10-04 22:28:36 +0000241
242 // Define the first (and only) variant of this arg.
243 channel_arg.arg_type = eArgTypeLogChannel;
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000244 channel_arg.arg_repetition = eArgRepeatPlain;
Caroline Tice43b014a2010-10-04 22:28:36 +0000245
246 // There is only one variant this argument could be; put it into the argument entry.
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000247 arg1.push_back (channel_arg);
Caroline Tice43b014a2010-10-04 22:28:36 +0000248
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000249 category_arg.arg_type = eArgTypeLogCategory;
250 category_arg.arg_repetition = eArgRepeatPlus;
251
252 arg2.push_back (category_arg);
253
Caroline Tice43b014a2010-10-04 22:28:36 +0000254 // Push the data for the first argument into the m_arguments vector.
Caroline Tice6a9e5c22010-10-29 21:56:41 +0000255 m_arguments.push_back (arg1);
256 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000257 }
258
259 virtual
260 ~CommandObjectLogDisable()
261 {
262 }
263
Jim Inghamda26bd22012-06-08 21:56:10 +0000264protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000265 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000266 DoExecute (Args& args,
Chris Lattner24943d22010-06-08 16:52:24 +0000267 CommandReturnObject &result)
268 {
269 const size_t argc = args.GetArgumentCount();
270 if (argc == 0)
271 {
Jim Ingham9721fe92012-05-12 00:38:30 +0000272 result.AppendErrorWithFormat("%s takes a log channel and one or more log types.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000273 }
274 else
275 {
Caroline Tice926060e2010-10-29 21:48:37 +0000276 Log::Callbacks log_callbacks;
Chris Lattner24943d22010-06-08 16:52:24 +0000277
Caroline Tice926060e2010-10-29 21:48:37 +0000278 std::string channel(args.GetArgumentAtIndex(0));
279 args.Shift (); // Shift off the channel
280 if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
281 {
Jim Ingham6c530f22012-02-21 02:23:08 +0000282 log_callbacks.disable (args.GetConstArgumentVector(), &result.GetErrorStream());
Caroline Tice926060e2010-10-29 21:48:37 +0000283 result.SetStatus(eReturnStatusSuccessFinishNoResult);
284 }
285 else if (channel == "all")
286 {
287 Log::DisableAllLogChannels(&result.GetErrorStream());
288 }
289 else
290 {
Greg Clayton5e342f52011-04-13 22:47:15 +0000291 LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
Caroline Tice926060e2010-10-29 21:48:37 +0000292 if (log_channel_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000293 {
Jim Ingham6c530f22012-02-21 02:23:08 +0000294 log_channel_sp->Disable(args.GetConstArgumentVector(), &result.GetErrorStream());
Chris Lattner24943d22010-06-08 16:52:24 +0000295 result.SetStatus(eReturnStatusSuccessFinishNoResult);
296 }
Chris Lattner24943d22010-06-08 16:52:24 +0000297 else
Caroline Tice926060e2010-10-29 21:48:37 +0000298 result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
Chris Lattner24943d22010-06-08 16:52:24 +0000299 }
300 }
301 return result.Succeeded();
302 }
303};
304
Jim Inghamda26bd22012-06-08 21:56:10 +0000305class CommandObjectLogList : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000306{
307public:
308 //------------------------------------------------------------------
309 // Constructors and Destructors
310 //------------------------------------------------------------------
Greg Clayton238c0a12010-09-18 01:14:36 +0000311 CommandObjectLogList(CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000312 CommandObjectParsed (interpreter,
313 "log list",
314 "List the log categories for one or more log channels. If none specified, lists them all.",
315 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000316 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000317 CommandArgumentEntry arg;
318 CommandArgumentData channel_arg;
319
320 // Define the first (and only) variant of this arg.
321 channel_arg.arg_type = eArgTypeLogChannel;
322 channel_arg.arg_repetition = eArgRepeatStar;
323
324 // There is only one variant this argument could be; put it into the argument entry.
325 arg.push_back (channel_arg);
326
327 // Push the data for the first argument into the m_arguments vector.
328 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000329 }
330
331 virtual
332 ~CommandObjectLogList()
333 {
334 }
335
Jim Inghamda26bd22012-06-08 21:56:10 +0000336protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000337 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000338 DoExecute (Args& args,
Chris Lattner24943d22010-06-08 16:52:24 +0000339 CommandReturnObject &result)
340 {
341 const size_t argc = args.GetArgumentCount();
342 if (argc == 0)
343 {
344 Log::ListAllLogChannels (&result.GetOutputStream());
345 result.SetStatus(eReturnStatusSuccessFinishResult);
346 }
347 else
348 {
349 for (size_t i=0; i<argc; ++i)
350 {
351 Log::Callbacks log_callbacks;
352
353 std::string channel(args.GetArgumentAtIndex(i));
354 if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
355 {
356 log_callbacks.list_categories (&result.GetOutputStream());
357 result.SetStatus(eReturnStatusSuccessFinishResult);
358 }
359 else if (channel == "all")
360 {
361 Log::ListAllLogChannels (&result.GetOutputStream());
362 result.SetStatus(eReturnStatusSuccessFinishResult);
363 }
364 else
365 {
Greg Clayton5e342f52011-04-13 22:47:15 +0000366 LogChannelSP log_channel_sp (LogChannel::FindPlugin(channel.c_str()));
Chris Lattner24943d22010-06-08 16:52:24 +0000367 if (log_channel_sp)
368 {
369 log_channel_sp->ListCategories(&result.GetOutputStream());
370 result.SetStatus(eReturnStatusSuccessFinishNoResult);
371 }
372 else
373 result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
374 }
375 }
376 }
377 return result.Succeeded();
378 }
379};
380
Jim Inghamda26bd22012-06-08 21:56:10 +0000381class CommandObjectLogTimer : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000382{
383public:
384 //------------------------------------------------------------------
385 // Constructors and Destructors
386 //------------------------------------------------------------------
Greg Clayton238c0a12010-09-18 01:14:36 +0000387 CommandObjectLogTimer(CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000388 CommandObjectParsed (interpreter,
389 "log timers",
390 "Enable, disable, dump, and reset LLDB internal performance timers.",
391 "log timers < enable <depth> | disable | dump | increment <bool> | reset >")
Chris Lattner24943d22010-06-08 16:52:24 +0000392 {
393 }
394
395 virtual
396 ~CommandObjectLogTimer()
397 {
398 }
399
Jim Inghamda26bd22012-06-08 21:56:10 +0000400protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000401 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000402 DoExecute (Args& args,
Chris Lattner24943d22010-06-08 16:52:24 +0000403 CommandReturnObject &result)
404 {
405 const size_t argc = args.GetArgumentCount();
406 result.SetStatus(eReturnStatusFailed);
407
408 if (argc == 1)
409 {
410 const char *sub_command = args.GetArgumentAtIndex(0);
411
412 if (strcasecmp(sub_command, "enable") == 0)
413 {
414 Timer::SetDisplayDepth (UINT32_MAX);
415 result.SetStatus(eReturnStatusSuccessFinishNoResult);
416 }
417 else if (strcasecmp(sub_command, "disable") == 0)
418 {
419 Timer::DumpCategoryTimes (&result.GetOutputStream());
420 Timer::SetDisplayDepth (0);
421 result.SetStatus(eReturnStatusSuccessFinishResult);
422 }
423 else if (strcasecmp(sub_command, "dump") == 0)
424 {
425 Timer::DumpCategoryTimes (&result.GetOutputStream());
426 result.SetStatus(eReturnStatusSuccessFinishResult);
427 }
428 else if (strcasecmp(sub_command, "reset") == 0)
429 {
430 Timer::ResetCategoryTimes ();
431 result.SetStatus(eReturnStatusSuccessFinishResult);
432 }
433
434 }
Jim Ingham19e29a82010-11-04 23:08:26 +0000435 else if (argc == 2)
436 {
437 const char *sub_command = args.GetArgumentAtIndex(0);
438
439 if (strcasecmp(sub_command, "enable") == 0)
440 {
441 bool success;
442 uint32_t depth = Args::StringToUInt32(args.GetArgumentAtIndex(1), 0, 0, &success);
443 if (success)
444 {
445 Timer::SetDisplayDepth (depth);
446 result.SetStatus(eReturnStatusSuccessFinishNoResult);
447 }
448 else
449 result.AppendError("Could not convert enable depth to an unsigned integer.");
450 }
Jim Ingham4ba39992010-11-04 23:19:21 +0000451 if (strcasecmp(sub_command, "increment") == 0)
452 {
453 bool success;
454 bool increment = Args::StringToBoolean(args.GetArgumentAtIndex(1), false, &success);
455 if (success)
456 {
457 Timer::SetQuiet (!increment);
458 result.SetStatus(eReturnStatusSuccessFinishNoResult);
459 }
460 else
461 result.AppendError("Could not convert increment value to boolean.");
462 }
Jim Ingham19e29a82010-11-04 23:08:26 +0000463 }
464
Chris Lattner24943d22010-06-08 16:52:24 +0000465 if (!result.Succeeded())
466 {
467 result.AppendError("Missing subcommand");
468 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
469 }
470 return result.Succeeded();
471 }
472};
473
474//----------------------------------------------------------------------
475// CommandObjectLog constructor
476//----------------------------------------------------------------------
Greg Clayton63094e02010-06-23 01:19:29 +0000477CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000478 CommandObjectMultiword (interpreter,
479 "log",
Chris Lattner24943d22010-06-08 16:52:24 +0000480 "A set of commands for operating on logs.",
481 "log <command> [<command-options>]")
482{
Greg Clayton238c0a12010-09-18 01:14:36 +0000483 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectLogEnable (interpreter)));
484 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectLogDisable (interpreter)));
485 LoadSubCommand ("list", CommandObjectSP (new CommandObjectLogList (interpreter)));
486 LoadSubCommand ("timers", CommandObjectSP (new CommandObjectLogTimer (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +0000487}
488
489//----------------------------------------------------------------------
490// Destructor
491//----------------------------------------------------------------------
492CommandObjectLog::~CommandObjectLog()
493{
494}
495
496
497
498