Index: .gitignore =================================================================== --- .gitignore +++ .gitignore @@ -38,7 +38,18 @@ clang-module-cache +# Skip ctags-style tags files +tags + # We should ignore Xcode-style embedding of llvm/ at lldb root dir. # Do not add trailing '/'s, they skip symlinks. /llvm /DerivedData + +# Ignore test trace directories. +20??-??-??-??_??_??/ + +# Ignore crashlog support files. +crashinfo.lock +crashinfo.so + Index: cmake/LLDBDependencies.cmake =================================================================== --- cmake/LLDBDependencies.cmake +++ cmake/LLDBDependencies.cmake @@ -46,6 +46,7 @@ lldbPluginObjectContainerMachOArchive lldbPluginObjectContainerBSDArchive lldbPluginPlatformMacOSX + lldbPluginStructuredDataDarwinLog lldbPluginDynamicLoaderMacOSXDYLD lldbPluginUnwindAssemblyInstEmulation lldbPluginUnwindAssemblyX86 Index: docs/structured_data/DarwinLog.md =================================================================== --- /dev/null +++ docs/structured_data/DarwinLog.md @@ -0,0 +1,160 @@ +# Change Notes + +## Summary + +This document describes the DarwinLog logging feature. + +## StructuredDataDarwinLog feature + +The DarwinLog feature supports logging os_log*() and NSLog() messages +to the command-line lldb console, as well as making those messages +available to LLDB clients via the event system. Starting with fall +2016 OSes, Apple platforms introduce a new fire-hose, stream-style +logging system where the bulk of the log processing happens on the log +consumer side. This reduces logging impact on the system when there +are no consumers, making it cheaper to include logging at all times. +However, it also increases the work needed on the consumer end when +log messages are desired. + +The debugserver binary has been modified to support collection of +os_log*()/NSLog() messages, selection of which messages appear in the +stream, and fine-grained filtering of what gets passed on to the LLDB +client. DarwinLog also tracks the activity chain (i.e. os_activity() +hierarchy) in effect at the time the log messages were issued. The +user is able to configure a number of aspects related to the +formatting of the log message header fields. + +The DarwinLog support is written in a way which should support the +lldb client side on non-Apple clients talking to an Apple device or +macOS system; hence, the plugin support is built into all LLDB +clients, not just those built on an Apple platform. + +StructuredDataDarwinLog implements the 'DarwinLog' feature type, and +the plugin name for it shows up as 'darwin-log'. + +The user interface to the darwin-log support is via the following: + +* 'plugin structured-data darwin-log enable' command + + This is the main entry point for enabling the command. It can be + set before launching a process or while the process is running. + If the user wants to squelch seeing info-level or debug-level + messages, which is the default behavior, then the enable command + must be made prior to launching the process; otherwise, the + info-level and debug-level messages will always show up. Also, + there is a similar "echo os_log()/NSLog() messages to target + process stderr" mechanism which is properly disabled when enabling + the DarwinLog support prior to launch. This cannot be squelched + if enabling DarwinLog after launch. + + See the help for this command. There are a number of options + to shrink or expand the number of messages that are processed + on the remote side and sent over to the client, and other + options to control the formatting of messages displayed. + + This command is sticky. Once enabled, it will stay enabled for + future process launches. + +* 'plugin structured-data darwin-log disable' command + + Executing this command disables os_log() capture in the currently + running process and signals LLDB to stop attempting to launch + new processes with DarwinLog support enabled. + +* 'settings set \ + plugin.structured-data.darwin-log.enable-on-startup' + + and + + 'settings set \ + plugin.structured-data.darwin-log.auto-enable-options -- {options}' + + When enable-on-startup is set to true, then LLDB will automatically + enable DarwinLog on startup of relevant processes. It will use the + content provided in the auto-enable-options settings as the + options to pass to the enable command. + + Note the '--' required after auto-enable-command. That is necessary + for raw commands like settings set. The '--' will not become part + of the options for the enable command. + +### Message flow and related performance considerations + +os_log()-style collection is not free. The more data that must be +processed, the slower it will be. There are several knobs available +to the developer to limit how much data goes through the pipe, and how +much data ultimately goes over the wire to the LLDB client. The +user's goal should be to ensure he or she only collects as many log +messages are needed, but no more. + +The flow of data looks like the following: + +1. Data comes into debugserver from the low-level OS facility that + receives log messages. The data that comes through this pipe can + be limited or expanded by the '--debug', '--info' and + '--all-processes' options of the 'plugin structured-data darwin-log + enable' command. options. Exclude as many categories as possible + here (also the default). The knobs here are very coarse - for + example, whether to include os_log_info()-level or + os_log_debug()-level info, or to include callstacks in the log + message event data. + +2. The debugserver process filters the messages that arrive through a + message log filter that may be fully customized by the user. It + works similar to a rules-based packet filter: a set of rules are + matched against the log message, each rule tried in sequential + order. The first rule that matches then either accepts or rejects + the message. If the log message does not match any rule, then the + message gets the no-match (i.e. fall-through) action. The no-match + action defaults to accepting but may be set to reject. + + Filters can be added via the enable command's '--filter + {filter-spec}' option. Filters are added in order, and multiple + --filter entries can be provided to the enable command. + + Filters take the following form: + + {action} {attribute} {op} + + {action} := + accept | + reject + + {attribute} := + category | // The log message category + subsystem | // The log message subsystem} + activity | // The child-most activity in force + // at the time the message was logged. + activity-chain | // The complete activity chain, specified + // as {parent-activity}:{child-activity}: + // {grandchild-activity} + message | // The fully expanded message contents. + // Note this one is expensive because it + // requires expanding the message. Avoid + // this if possible, or add it further + // down the filter chain. + + {op} := + match {exact-match-text} | + regex {search-regex} // uses C++ std::regex + // ECMAScript variant. + +e.g. + --filter "accept subsystem match com.example.mycompany.myproduct" + --filter "accept subsystem regex com.example.+" + --filter "reject category regex spammy-system-[[:digit:]]+" + +3. Messages that are accepted by the log message filter get sent to + the lldb client, where they are mapped to the + StructuredDataDarwinLog plugin. By default, command-line lldb will + issue a Process-level event containing the log message content, and + will request the plugin to print the message if the plugin is + enabled to do so. + +### Log message display + +Several settings control aspects of displaying log messages in +command-line LLDB. See the enable command's help for a description +of these. + + Index: docs/structured_data/StructuredDataPlugins.md =================================================================== --- /dev/null +++ docs/structured_data/StructuredDataPlugins.md @@ -0,0 +1,105 @@ +# Change Notes + +## Overview + +This document describes an infrastructural feature called Structured +Data plugins. See the DarwinLog.md doc for a description of one +such plugin that makes use of this feature. + +## StructuredDataPlugin + +StructuredDataPlugin instances have the following characteristics: + +* Each plugin instance is bound to a single Process instance. + +* Each StructuredData feature has a type name that identifies the + feature. The DarwinLog feature is named 'DarwinLog'. This feature + type name is used in various places. + +* Process-derived classes create the plugins through common Process + code. This happens when the process monitor reports the list of + supported StructuredData features advertised by the process + monitor. Process goes through the list of supported feature type + names, and asks each known StructuredDataPlugin if it can handle the + feature. The first plugin that supports the feature is mapped to + that Process instance for that feature. Plugins are only mapped + when the process monitor advertises that a feature is supported. + +* The feature may send asynchronous messages in StructuredData format + to the Process instance. In the case of the gdb-remote protocol, + these are $JSON-async: packets that can be received while the target + process is currently running. Process instances route the + asynchronous structured data messages to the plugin mapped to that + feature type, if one exists. Note currently these packets may only + arrive while the target process is running and we are thus waiting + for continue/stop/process-state events on the LLDB client side. + +* Plugins can request that the Process instance forward on + configuration data to the process monitor if the plugin needs/wants + to configure the feature. For gdb-remote, this translates to a + $QConfigure{FeatureName}: packet. Configuration data is provided as + StructuredData. + +* Plugins are notified when modules are loaded into the Process + instance. + +* Plugins may optionally broadcast their received structured data as + an LLDB process-level event. A new method has been added to Process + to handle this, and a new Process StructuredData event type has been + added. + +* In the case where a plugin chooses to broadcast a received + StructuredData event, the command-line LLDB Debugger instance + listens for them. The Debugger instance then gives the plugin an + opportunity to display info to either the debugger output or error + stream at a time that is safe to write to them. The plugin can + choose to display something appropriate regarding the structured + data that time. + +* Plugins can provide a ProcessLaunchInfo filter method when the + plugin is registered. If such a filter method is provided, then + when a process is about to be launched for debugging, the filter + callback is made, given both the launch info and the target. The + plugin may then alter the launch info if needed to better support + the feature of the plugin. (The DarwinLog plugin needs to insert + environment variables in some cases when enabled, and this is the + mechanism by which it can do that). + +* The plugin is entirely independent of the type of Process-derived + class that it is working with. The only requirements from the + process monitor (e.g. ProcessGDBRemote) are the following + feature-agnostic elements: + + * Provide a way to discover features supported by the process + monitor. ProcessGDBRemote does this with a new query packet to + debugserver/ lldb-server. + + * Specify the list of supported feature type names to Process. + + * Provide a way to forward on configuration data for a feature type + to the process monitor. This is the manner by which LLDB can + configure a feature, perhaps based on settings or commands from + the user. + + * Listen for asynchronous structured data packets from the process + monitor, and forward them on to Process. + + That has already been wired in for ProcessGDBRemote. gdb-remote + servers like debugserver and lldb-server just need to respond to the + supported features packet and the configuration packet to support + these types of features. The communication layer handles receipt of + the $J packets and forwards them on to the process, which will then + route them to the plugin that was previously set up to handle the + packet. + +* StructuredData producers must send their top-level data as a + Dictionary type, with a key called 'type' specifying a string value, + where the value is equal to the StructuredData feature name + previously advertised. Everything else about the content of the + dictionary is entirely up to the feature. + +* StructuredDataPlugin commands show up under 'plugin structured-data + plugin-name'. + +* StructuredDataPlugin settings show up under + 'plugin.structured-data.{plugin-name}. Index: include/lldb/API/SBProcess.h =================================================================== --- include/lldb/API/SBProcess.h +++ include/lldb/API/SBProcess.h @@ -32,7 +32,8 @@ eBroadcastBitInterrupt = (1 << 1), eBroadcastBitSTDOUT = (1 << 2), eBroadcastBitSTDERR = (1 << 3), - eBroadcastBitProfileData = (1 << 4) + eBroadcastBitProfileData = (1 << 4), + eBroadcastBitStructuredData = (1 << 5) }; SBProcess (); Index: include/lldb/Core/Broadcaster.h =================================================================== --- include/lldb/Core/Broadcaster.h +++ include/lldb/Core/Broadcaster.h @@ -274,7 +274,8 @@ /// eBroadcastBitInterrupt = (1 << 1), /// eBroadcastBitSTDOUT = (1 << 2), /// eBroadcastBitSTDERR = (1 << 3), -/// eBroadcastBitProfileData = (1 << 4) +/// eBroadcastBitProfileData = (1 << 4), +/// eBroadcastBitStructuredData = (1 << 5) /// }; /// \endcode //---------------------------------------------------------------------- Index: include/lldb/Core/Event.h =================================================================== --- include/lldb/Core/Event.h +++ include/lldb/Core/Event.h @@ -20,6 +20,7 @@ // Project includes #include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/StructuredData.h" #include "lldb/Host/Predicate.h" #include "lldb/Core/Broadcaster.h" @@ -159,6 +160,80 @@ }; //---------------------------------------------------------------------- +/// This class handles one or more StructuredData::Dictionary entries +/// that are raised for structured data events. +//---------------------------------------------------------------------- + +class EventDataStructuredData : public EventData +{ +public: + + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + EventDataStructuredData(); + + EventDataStructuredData(const lldb::ProcessSP &process_sp, + const StructuredData::ObjectSP &object_sp, + const lldb::StructuredDataPluginSP &plugin_sp); + + ~EventDataStructuredData() override; + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + const ConstString & + GetFlavor() const override; + + void + Dump(Stream *s) const override; + + const lldb::ProcessSP& + GetProcess() const; + + const StructuredData::ObjectSP& + GetObject() const; + + const lldb::StructuredDataPluginSP& + GetStructuredDataPlugin() const; + + void + SetProcess(const lldb::ProcessSP &process_sp); + + void + SetObject(const StructuredData::ObjectSP &object_sp); + + void + SetStructuredDataPlugin(const lldb::StructuredDataPluginSP &plugin_sp); + + //------------------------------------------------------------------ + // Static functions + //------------------------------------------------------------------ + static const EventDataStructuredData* + GetEventDataFromEvent(const Event *event_ptr); + + static lldb::ProcessSP + GetProcessFromEvent(const Event *event_ptr); + + static StructuredData::ObjectSP + GetObjectFromEvent(const Event *event_ptr); + + static lldb::StructuredDataPluginSP + GetPluginFromEvent(const Event *event_ptr); + + static const ConstString & + GetFlavorString (); + +private: + + lldb::ProcessSP m_process_sp; + StructuredData::ObjectSP m_object_sp; + lldb::StructuredDataPluginSP m_plugin_sp; + + DISALLOW_COPY_AND_ASSIGN(EventDataStructuredData); +}; + +//---------------------------------------------------------------------- // lldb::Event //---------------------------------------------------------------------- class Event Index: include/lldb/Core/PluginManager.h =================================================================== --- include/lldb/Core/PluginManager.h +++ include/lldb/Core/PluginManager.h @@ -328,6 +328,30 @@ CommandInterpreter &interpreter); //------------------------------------------------------------------ + // StructuredDataPlugin + //------------------------------------------------------------------ + static bool + RegisterPlugin(const ConstString &name, + const char *description, + StructuredDataPluginCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr, + StructuredDataFilterLaunchInfo filter_callback + = nullptr); + + static bool + UnregisterPlugin(StructuredDataPluginCreateInstance create_callback); + + static StructuredDataPluginCreateInstance + GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx); + + static StructuredDataPluginCreateInstance + GetStructuredDataPluginCreateCallbackForPluginName(const ConstString &name); + + static StructuredDataFilterLaunchInfo + GetStructuredDataFilterCallbackAtIndex(uint32_t idx, + bool &iteration_complete); + + //------------------------------------------------------------------ // SymbolFile //------------------------------------------------------------------ static bool @@ -531,6 +555,16 @@ static bool CreateSettingForOperatingSystemPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, const ConstString &description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForStructuredDataPlugin(Debugger &debugger, + const ConstString &setting_name); + + static bool + CreateSettingForStructuredDataPlugin(Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); }; } // namespace lldb_private Index: include/lldb/Interpreter/Args.h =================================================================== --- include/lldb/Interpreter/Args.h +++ include/lldb/Interpreter/Args.h @@ -439,6 +439,17 @@ LongestCommonPrefix (std::string &common_prefix); //------------------------------------------------------------------ + /// Add or replace an environment variable with the given value. + /// + /// This command adds the environment variable if it is not already + /// present using the given value. If the environment variable is + /// already in the list, it replaces the first such occurrence + /// with the new value. + //------------------------------------------------------------------ + void + AddOrReplaceEnvironmentVariable(const char *env_var_name, + const char *new_value); + /// Return whether a given environment variable exists. /// /// This command treats Args like a list of environment variables, @@ -448,12 +459,18 @@ /// @param[in] env_var_name /// Specifies the name of the environment variable to check. /// + /// @param[out] argument_index + /// If non-null, then when the environment variable is found, + /// the index of the argument position will be returned in + /// the size_t pointed to by this argument. + /// /// @return /// true if the specified env var name exists in the list in /// either of the above-mentioned formats; otherwise, false. //------------------------------------------------------------------ bool - ContainsEnvironmentVariable(const char *env_var_name) const; + ContainsEnvironmentVariable(const char *env_var_name, + size_t *argument_index = nullptr) const; protected: //------------------------------------------------------------------ Index: include/lldb/Interpreter/OptionGroupArchitecture.h =================================================================== --- include/lldb/Interpreter/OptionGroupArchitecture.h +++ include/lldb/Interpreter/OptionGroupArchitecture.h @@ -37,12 +37,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; bool GetArchitecture (Platform *platform, ArchSpec &arch); Index: include/lldb/Interpreter/OptionGroupBoolean.h =================================================================== --- include/lldb/Interpreter/OptionGroupBoolean.h +++ include/lldb/Interpreter/OptionGroupBoolean.h @@ -51,12 +51,12 @@ } Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; OptionValueBoolean & GetOptionValue () Index: include/lldb/Interpreter/OptionGroupFile.h =================================================================== --- include/lldb/Interpreter/OptionGroupFile.h +++ include/lldb/Interpreter/OptionGroupFile.h @@ -50,12 +50,12 @@ } Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; OptionValueFileSpec & GetOptionValue () @@ -105,12 +105,12 @@ } Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; OptionValueFileSpecList & GetOptionValue () Index: include/lldb/Interpreter/OptionGroupFormat.h =================================================================== --- include/lldb/Interpreter/OptionGroupFormat.h +++ include/lldb/Interpreter/OptionGroupFormat.h @@ -46,12 +46,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; lldb::Format GetFormat () const @@ -111,7 +111,7 @@ protected: bool - ParserGDBFormatLetter (CommandInterpreter &interpreter, + ParserGDBFormatLetter (CommandInterpreter *interpreter, char format_letter, lldb::Format &format, uint32_t &byte_size); Index: include/lldb/Interpreter/OptionGroupOutputFile.h =================================================================== --- include/lldb/Interpreter/OptionGroupOutputFile.h +++ include/lldb/Interpreter/OptionGroupOutputFile.h @@ -37,12 +37,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; const OptionValueFileSpec & GetFile () Index: include/lldb/Interpreter/OptionGroupPlatform.h =================================================================== --- include/lldb/Interpreter/OptionGroupPlatform.h +++ include/lldb/Interpreter/OptionGroupPlatform.h @@ -47,12 +47,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; lldb::PlatformSP CreatePlatformWithOptions (CommandInterpreter &interpreter, Index: include/lldb/Interpreter/OptionGroupString.h =================================================================== --- include/lldb/Interpreter/OptionGroupString.h +++ include/lldb/Interpreter/OptionGroupString.h @@ -49,12 +49,12 @@ } Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; OptionValueString & GetOptionValue () Index: include/lldb/Interpreter/OptionGroupUInt64.h =================================================================== --- include/lldb/Interpreter/OptionGroupUInt64.h +++ include/lldb/Interpreter/OptionGroupUInt64.h @@ -50,12 +50,12 @@ } Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; OptionValueUInt64 & GetOptionValue () Index: include/lldb/Interpreter/OptionGroupUUID.h =================================================================== --- include/lldb/Interpreter/OptionGroupUUID.h +++ include/lldb/Interpreter/OptionGroupUUID.h @@ -37,12 +37,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; const OptionValueUUID & GetOptionValue () const Index: include/lldb/Interpreter/OptionGroupValueObjectDisplay.h =================================================================== --- include/lldb/Interpreter/OptionGroupValueObjectDisplay.h +++ include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -37,12 +37,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_value) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; bool AnyOptionWasSet () const Index: include/lldb/Interpreter/OptionGroupVariable.h =================================================================== --- include/lldb/Interpreter/OptionGroupVariable.h +++ include/lldb/Interpreter/OptionGroupVariable.h @@ -37,12 +37,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; bool include_frame_options:1, show_args:1, // Frame option only (include_frame_options == true) Index: include/lldb/Interpreter/OptionGroupWatchpoint.h =================================================================== --- include/lldb/Interpreter/OptionGroupWatchpoint.h +++ include/lldb/Interpreter/OptionGroupWatchpoint.h @@ -39,12 +39,12 @@ GetDefinitions() override; Error - SetOptionValue(CommandInterpreter &interpreter, + SetOptionValue(CommandInterpreter *interpreter, uint32_t option_idx, const char *option_arg) override; void - OptionParsingStarting(CommandInterpreter &interpreter) override; + OptionParsingStarting(CommandInterpreter *interpreter) override; // Note: // eWatchRead == LLDB_WATCH_TYPE_READ; and Index: include/lldb/Interpreter/Options.h =================================================================== --- include/lldb/Interpreter/Options.h +++ include/lldb/Interpreter/Options.h @@ -117,7 +117,7 @@ class Options { public: - Options (CommandInterpreter &interpreter); + Options (CommandInterpreter *interpreter); virtual ~Options (); @@ -301,7 +301,7 @@ bool &word_complete, StringList &matches); - CommandInterpreter& + CommandInterpreter* GetInterpreter() { return m_interpreter; @@ -312,7 +312,8 @@ typedef std::set OptionSet; typedef std::vector OptionSetVector; - CommandInterpreter &m_interpreter; + // Figure out if this is really needed. + CommandInterpreter *m_interpreter; std::vector