/*
 * Interpreter.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Collections.Generic;

#if CAS_POLICY
using System.Configuration.Assemblies;
#endif

#if DATA
using System.Data;
#endif

using System.Globalization;
using System.IO;

#if NETWORK
using System.Net.Sockets;
#endif

using System.Reflection;
using System.Resources;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Security.Policy;
using System.Text;
using System.Threading;
using Eagle._Attributes;
using Eagle._Components.Private;
using Eagle._Components.Private.Delegates;

#if NATIVE && TCL
using Eagle._Components.Private.Tcl;
#endif

using Eagle._Components.Public.Delegates;
using Eagle._Constants;
using Eagle._Containers.Private;

#if NATIVE && TCL
using Eagle._Containers.Private.Tcl;
#endif

using Eagle._Containers.Public;
using Eagle._Encodings;
using Eagle._Interfaces.Private;

#if NATIVE && TCL
using Eagle._Interfaces.Private.Tcl;
#endif

using Eagle._Interfaces.Public;

#if !CONSOLE
using ConsoleColor = Eagle._Components.Public.ConsoleColor;
#endif

#if DEBUGGER
using _Private = Eagle._Components.Private;
#endif

using _Public = Eagle._Components.Public;

namespace Eagle._Components.Public
{
    [ObjectId("b98042f9-d66a-46db-81e9-a2f44c1f03fd")]
    public sealed class Interpreter :
#if ISOLATED_INTERPRETERS || ISOLATED_PLUGINS
        ScriptMarshalByRefObject,
#endif
#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        ICacheManager,
#endif
#if CALLBACK_QUEUE
        ICallbackQueueManager,
#endif
        IDisposable, IDebugManager, IEngineManager,
        IEntityManager, IErrorManager,
#if HISTORY
        IHistoryManager,
#endif
        IInteractiveManager, IInterpreter, IInterpreterManager,
#if NOTIFY || NOTIFY_OBJECT
        INotifyManager,
#endif
        IPackageManager,
        IPluginManager, IPropertyManager, IResolveManager,
        IResourceManager, IScriptManager, ISecurityManager,
#if SHELL
        IShellManager,
#endif
        ISynchronize,
#if NATIVE && TCL
        ITclEntityManager, ITclManager,
#endif
        IVariableManager
    {
        #region Global Read-Only Data (shared by all Interpreters)
        #region Static Data Lock -- Private
        private static readonly object staticSyncRoot = new object();
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Encodings -- Public
        //
        // WARNING: If any of these encodings are changed things may not work correctly.
        //
        public static readonly Encoding SystemEncoding = new UnicodeEncoding(false, false);
        public static readonly Encoding DefaultEncoding = new UTF8Encoding(false);
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Global Data (shared by all Interpreters) -- Private
        private static int breakCount = 0;

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Global Host Integration Data -- Private
        private static bool defaultQuiet = false;
        private static bool defaultTraceStack = false;

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static NewHostCallback newHostCallback;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Global Tcl/Tk Integration Data -- Private
        #region Zombie Tcl/Tk Object Tracking -- Private
#if NATIVE && TCL
        private static int deadTclThreadId;
        private static ITclApi deadTclApi;
        private static IntPtrDictionary deadTclInterps;
        private static TclBridgeDictionary deadTclBridges;

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TCL_THREADS
        private static TclThreadDictionary deadTclThreads;
#endif
#endif
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Constants
        #region Timeout Defaults
#if NETWORK
        //
        // HACK: This is no longer read-only.
        //
        private static int DefaultThreadStartTimeout = 3000;

        //
        // HACK: This is no longer read-only.
        //
        private static int MinimumSocketPollTimeout = 500; /* in milliseconds */
#endif

        //
        // HACK: This is no longer read-only.
        //
        private static int DefaultTimeout = _Timeout.Infinite; // NOTE: Never timeout.

        //
        // HACK: This is no longer read-only.
        //
        private static int DefaultFinallyTimeout = DefaultTimeout; // NOTE: Never timeout.

        //
        // HACK: This is no longer read-only.
        //
        private static int DefaultReadyTimeout = DefaultTimeout; // NOTE: Never timeout.
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region History & Caching
#if PARSE_CACHE || LIST_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        //
        // HACK: *PERF* This is no longer read-only.
        //
        private static int MaximumCacheSize =
            PlatformOps.Is32BitProcess() ? 8000 : 0; /* TODO: *PERF* Good default? */

#if PARSE_CACHE || LIST_CACHE
        //
        // HACK: *PERF* This is no longer read-only.
        //
        private static int MaximumCacheItemSize =
            PlatformOps.Is32BitProcess() ? 10485760 : 0; /* TODO: *PERF* Good default? */
#endif

#if CACHE_DICTIONARY
        //
        // HACK: *PERF* This is no longer read-only.
        //
        private static int MinimumCacheSize = MaximumCacheSize / 2; /* TODO: *PERF* Good default? */
#endif
#endif

#if HISTORY
        //
        // HACK: *PERF* This is no longer read-only.
        //
        private static int DefaultHistoryLimit = 100; /* TODO: Good default? */
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Error Messages
        #region Resource Error Messages (FIXED-STRING)
        //
        // NOTE: These six strings must be compile time constants because
        //       they are used before the cultureInfo and resourceManager
        //       objects are available to resolve runtime string resources.
        //
        private const string CultureInfoError =
            "could not interpret \"{0}\" as a culture name or identifier";

        private const string InvalidCultureInfoError =
            "invalid culture";

        private const string InvalidBaseResourceName =
            "invalid base resource name";

        private const string ResourceManagerError =
            "could not create resource manager \"{0}\"";
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Cancellation Error Messages
        private const string demandCancelResultFormat = "user canceled";

        private const string timeoutCancelPromptFormat =
            "possible runaway script ({0} milliseconds), cancel?";

        private const string timeoutCancelResultFormat =
            "runaway script unwound after {0} milliseconds";

        private const string finallyTimeoutCancelResultFormat =
            "runaway finally script unwound after {0} milliseconds";
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Procedure Declaration Error Messages
        //
        // NOTE: These two strings are used by the procedure declaration engine.
        //       For localization, we need to make them into properties and load
        //       them from a resource file.
        //
        internal const string ArgumentNotScalarError =
            "formal parameter \"{0}\" is an array element";

        internal const string ArgumentNotSimpleError =
            "formal parameter \"{0}\" is not a simple name";
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Opaque Handles
#if NATIVE && TCL
        #region Tcl Interpreters
        internal const string tclMasterInterpPrefix = "masterInterp";
        private const string tclSafeInterpPrefix = "safeInterp";
        private const string tclInterpPrefix = "interp";
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Threads (Isolated Worker Threads)
#if TCL_THREADS
        private const string tclThreadPrefix = "thread";
#endif
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Nesting Level Defaults
#if NATIVE && WINDOWS
        //
        // NOTE: The number of nesting levels before we start checking
        //       native stack space.
        //
        // TODO: We really need to adjust these numbers dynamically
        //       depending on the maximum stack size of the thread.
        //
        private static readonly int NoStackLevels = 100;
        private static readonly int NoStackParserLevels = 100;
        private static readonly int NoStackExpressionLevels = 100;
#endif

        private static readonly int DefaultReadyLimit = 0;
        private static readonly int DefaultRecursionLimit = 1000;
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Read-Only Data
        //
        // NOTE: The AppDomain-wide unique Id for this interpreter.
        //
        private readonly long id = GlobalState.NextInterpreterId();

        //
        // FIXME: Review and revise usage of locking in the interpreter object,
        //        paying careful attention to any routines whose primary purpose
        //        is to modify collections of data (e.g. commands, plugins, etc).
        //
        private readonly object syncRoot = new object();
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Context Data
#if THREADING
        private IContextManager contextManager;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Context Data (!THREADING, per-interpreter, per-thread)
        #region Private Engine Context Data (!THREADING, per-interpreter, per-thread)
#if !THREADING
        private int levels;           // evaluation nesting level
        private int previousLevels;   // previous evaluation nesting level (for [test*], etc.)
        private int parserLevels;     // parser nesting level
        private int expressionLevels; // expression nesting level
        private int unknownLevels;    // [unknown] nesting level
        private int traceLevels;      // variable trace nesting level

#if DEBUGGER
        private int watchpointLevels; // variable watch nesting level
#endif

#if NOTIFY || NOTIFY_OBJECT
        private int notifyLevels;     // notification nesting level
#endif

        private int policyLevels;     // policy checking nesting level
        private int testLevels;       // the nesting level of the test(s).

        private bool stackOverflow;   // stack overflow flag, always reset at level 0.

#if PREVIOUS_RESULT
        private Result previousResult;
#endif

        private IParseState parseState; // NOTE: For internal engine use only.
        private ReturnCode returnCode; // NOTE: For internal engine use only.

        private int errorLine;    // NOTE: For internal engine use only.
        private string errorCode; // NOTE: For internal engine use only.
        private string errorInfo; // NOTE: For internal engine use only.
        private int errorFrames;  // NOTE: For internal engine use only.

        private IScriptLocation scriptLocation; // used only when set by [info script ?fileName?]
        private StackList<IScriptLocation> scriptLocations;    // used by [info] command directly.

        private int previousProcessId;   // id of the previous Process to be [exec]'d

        private ArraySearchDictionary arraySearches;

#if HISTORY
        private IHistoryFilter historyEngineFilter;
        private ClientDataList _history;
#endif

        //
        // NOTE: This is written to by "DebugOps.Complain" for inclusion in
        //       the interactive debugger output.
        //
        private string complaint;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Interactive Context Data (!THREADING, per-interpreter, per-thread)
#if !THREADING
        private bool interactive;
        private string interactiveInput;
        private string previousInteractiveInput;
        private string interactiveMode;
        private int interactiveLoops;

#if HISTORY
        private IHistoryData historyLoadData;
        private IHistoryData historySaveData;

        private IHistoryFilter historyInfoFilter;
        private IHistoryFilter historyLoadFilter;
        private IHistoryFilter historySaveFilter;

        private string historyFileName;
#endif
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Test Context Data (!THREADING, per-interpreter, per-thread)
#if !THREADING
        //
        // NOTE: TclTest related state.
        //
        private int[] testStatistics; // total tests, passed, failed, etc.
        private StringList testConstraints;
        private StringList testSkipped;
        private StringList testFailures;
        private IntDictionary testCounts; // all tests that have been run.
        private StringList testMatch;
        private StringList testSkip;
        private ReturnCodeDictionary testReturnCodeMessages; // used by the test suite.

#if DEBUGGER
        private StringDictionary testBreakpoints;
#endif

        private string testPath;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Variable Context Data (!THREADING, per-interpreter, per-thread)
#if !THREADING
        private CallStack callStack;       // the script call stack.
        private ICallFrame procedureFrame; // current procedure call frame, if any.
        private ICallFrame uplevelFrame;   // current uplevel call frame, if any.
        private ICallFrame currentFrame;   // always the current call frame.
        private ITraceInfo traceInfo;      // current trace info, if any.
#endif

        //
        // NOTE: This always points to the global call frame; however, it cannot
        //       be used outside of this class.  Use the "GlobalFrame" property
        //       instead.
        //
        private ICallFrame globalFrame;
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Data (per-interpreter)
        #region Plugin Token Data
        private long corePluginToken;

#if NOTIFY || NOTIFY_OBJECT
        private long objectPluginToken;
#endif

#if DEBUG
        private long testPluginToken;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Cancellation Data
        //
        // NOTE: These cannot be per-thread because we allow script cancellation
        //       to occur from any thread.
        //
        private bool cancel;
        private bool unwind;
        private bool halt;

        private Result cancelResult;
        private Result haltResult;

        //
        // NOTE: This is the delegate to be called when the interpreter is
        //       interrupted for some reason, including script cancellations.
        //       Currently, this property is not exposed via the IInterpreter
        //       interface.  In order to take advantage of this feature, use
        //       of the [debug callback] sub-command is required.
        //
        private InterruptCallback interruptCallback;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Threading Data
        private Thread timeoutThread;
        private Thread finallyTimeoutThread;

#if SHELL && INTERACTIVE_COMMANDS
        private Thread testGcThread;
#endif

        private int threadId; // NOTE: The "primary" (i.e. creation) thread for this interpreter.
        private Thread thread;
        private EventWaitHandle variableEvent;

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL
        private Thread interactiveThread; // NOTE: The current interactive thread for this interpreter, if any.
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Extensibility Data
        private object applicationObject;
        private object policyObject;
        private object resolverObject;
        private object userObject;
        private StringDictionary runtimeOptions;
        private bool throwOnFeatureNotSupported;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Xml Data
#if XML
        private bool validateXml;
        private bool allXml;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Host Integration Data
#if ISOLATED_PLUGINS
        private IHost coreHost;
#endif

        private IHost host;
        private bool quiet;

#if POLICY_TRACE
        private bool policyTrace;
#endif

#if NETWORK
        //
        // NOTE: This is used when creating new WebClient object instances from
        //       within the Engine and the SocketOps classes.
        //
        private NewWebClientCallback newWebClientCallback;
#endif

        //
        // NOTE: This is not currently used.
        //
        private TextWriter traceTextWriter;

        //
        // NOTE: This is written to by "DebugOps.Complain" for persisting the error information
        //       to a stream (e.g. a file on disk).
        //
        private TextWriter debugTextWriter;

        //
        // NOTE: The system default foreground and background colors for this interpreter.  Right
        //       now, these are only used in certain circumstances (i.e. when GetColors is called
        //       and cannot determine from the interpreter host what color settings to use).
        //
        private ConsoleColor defaultForegroundColor;
        private ConsoleColor defaultBackgroundColor;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Library Initialization Data
        private bool preInitialized;           // has the pre-init script been evaluated?
        private string preInitializeText;      // the saved copy of the pre-init script.

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private string libraryPath;            // the location of the "init" script.
        private StringList autoPathList;       // the list of additional dirs to check for packages.

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Lifecycle Flags & Data
        private bool preSetup;                 // has the PreSetup() method completed?
        private bool setup;                    // has the Setup() method completed?

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool initialized;              // is the core script library initialized?
        private string initializedPath;        // path actually used for the "init" script.

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool initializedShell;         // is the shell script library initialized?
        private string initializedShellPath;   // path actually used for the "shell" script.
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Trusted Paths & Types (When "Safe" Only)
        private StringList trustedPaths;       // paths trusted when "safe".

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This is the list of managed types considered to be trusted [by
        //       this interpreter only] if it has been marked as "safe".  This
        //       list is only used when invoking static methods.  Managed types
        //       for non-static methods are checked for trust on a per-instance
        //       basis, via the ObjectFlags associated with the IObject wrapper.
        //
        private ObjectDictionary trustedTypes; // managed types trusted when "safe".
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region CLR Integration Data
        private AppDomain appDomain;
        private IBinder binder;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Entity Manager Data
        #region Tcl/Tk Integration Data
#if NATIVE && TCL
        private readonly object tclSyncRoot = new object();
        private ITclApi tclApi;

        private IntPtrDictionary tclInterps; // TODO: per-thread?

#if TCL_THREADS
        private TclThreadDictionary tclThreads;
#endif

        private TclBridgeDictionary tclBridges; // TODO: per-thread?
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region CLR Integration Entity Data
        private StringDictionary objectTypes;
        private StringDictionary objectNamespaces;
        private TypePairDictionary<string, long> objectInterfaces;
        private StringDictionary objectAliasNamespaces;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Core Entity Data
#if DATA
        private DbConnectionDictionary connections;
        private DbTransactionDictionary transactions;
#endif

        private PolicyWrapperDictionary policies;
        private TraceWrapperDictionary traces;
        private ChannelDictionary channels;
        private CallFrameDictionary scopes;
        private ObjectWrapperDictionary objects;

#if APPDOMAINS
        private AppDomainDictionary appDomains;
#endif

        private List<IResolve> resolvers;

        private INamespace globalNamespace;
        private Dictionary<string, INamespace> pendingNamespaces;

        private StringDictionary pluginArguments;
        private PluginWrapperDictionary plugins;
        private FunctionWrapperDictionary functions;
        private OperatorWrapperDictionary operators;
        private AliasWrapperDictionary aliases;
        private CommandWrapperDictionary commands;
        private CommandWrapperDictionary hiddenCommands;
        private CallbackDictionary callbacks;

#if CALLBACK_QUEUE
        private CallbackQueue callbackQueue;
#endif

        private ProcedureWrapperDictionary procedures;
        private ProcedureWrapperDictionary hiddenProcedures;
        private ExecuteWrapperDictionary executes;
        private ExecuteWrapperDictionary hiddenExecutes;

        #region Dead Code
#if DEAD_CODE
        private LambdaWrapperDictionary lambdas;
#endif
        #endregion

        private PackageIndexDictionary packageIndexes;
        private PackageWrapperDictionary packages;
        private EncodingDictionary encodings;

#if NATIVE && LIBRARY
        private ModuleWrapperDictionary modules;
        private DelegateWrapperDictionary delegates;
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Core Trace Lists
        private TraceList autoPathTraceList;
        private TraceList environmentTraceList;
        private TraceList linkedVariableTraceList;
        private TraceList systemArrayTraceList;
        private TraceList objectTraceList;
        private TraceList precisionTraceList;
        private TraceList testsTraceList;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Cache Data
#if PARSE_CACHE
        private ParseStateDictionary parseStateCache;

        #region Dead Code
#if DEAD_CODE
        private ExpressionStateDictionary expressionStateCache;
#endif
        #endregion
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE
        private StringListDictionary stringListCache;
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if EXECUTE_CACHE
        private ExecuteCache executeCache;
        private ExecuteCache hiddenExecuteCache;
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TYPE_CACHE
        private TypeDictionary typeCache;
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if COM_TYPE_CACHE
        private IntPtrTypeListDictionary comTypeListCache;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Slave Interpreter Data
        private Interpreter masterInterpreter;
        private string slaveName;

#if APPDOMAINS && ISOLATED_INTERPRETERS
        private string slaveAppDomainName;
#endif

        private InterpreterDictionary slaveInterpreters;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Resource Data
        private CultureInfo cultureInfo;
        private ResourceManager resourceManager;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Shell Data
#if SHELL && !THREADING
        private ArgumentCallback argumentCallback;
        private EvaluateScriptCallback evaluateScriptCallback;
        private EvaluateFileCallback evaluateFileCallback;
        private EvaluateEncodedFileCallback evaluateEncodedFileCallback;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Debugger Data
#if DEBUGGER && !THREADING
        private IDebugger debugger;

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This is used by the Debugger class when it needs to break into
        //       the interactive loop.
        //
        private InteractiveLoopCallback interactiveLoopCallback;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Data Type Conversion Data
        private string dateTimeFormat;
        private DateTimeKind dateTimeKind;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Expression Engine Data
        private Random random;
        private RandomNumberGenerator randomNumberGenerator;
        private int precision; // COMPAT: Tcl.
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Event Data
        private IEventManager eventManager;
        private int waitCount;
        private int waitSpinCount;

#if NETWORK
        private int serverSockets;
#endif

        private int sleepTime;
        private int timeout;
        private int finallyTimeout;
        private int threadStackSize;
        private int extraStackSpace;

        private string backgroundError; // NOTE: Background error handler.
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Finalization Data
        private event DisposeCallback preDisposeCallbacks;
        private event DisposeCallback postDisposeCallbacks;
        private int disposeCount;
        private bool disposed;
        private bool deleted;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Engine Data
        private long nextId;
        private bool readOnly;
        private bool immutable;

        private PolicyDecision commandDecision;
        private PolicyDecision scriptDecision;
        private PolicyDecision fileDecision;
        private PolicyDecision streamDecision;

        private long operationCount;
        private long commandCount; // COMPAT: Tcl.
        private int readyCount;
        private int readyLimit;
        private int recursionLimit; // COMPAT: Tcl.

        private bool exit;
        private ExitCode exitCode;

#if HISTORY
        private bool history;
        private int historyLimit;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Flags Data
        private CreateFlags createFlags;
        private ScriptFlags scriptFlags;

#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        private CacheFlags cacheFlags;
#endif

        private InterpreterFlags interpreterFlags;
        private ReadyFlags readyFlags;
        private EngineFlags engineFlags;
        private SubstitutionFlags substitutionFlags;
        private ExpressionFlags expressionFlags;
        private EventFlags afterEventFlags;
        private EventFlags engineEventFlags;
        private EventFlags queueEventFlags;
        private EventFlags serviceEventFlags;
        private EventFlags updateEventFlags;
        private EventFlags waitEventFlags;

#if DEBUGGER || SHELL
        private HeaderFlags headerFlags;
#endif

#if SHELL && INTERACTIVE_COMMANDS
        private EngineFlags interactiveEngineFlags;
        private SubstitutionFlags interactiveSubstitutionFlags;
        private EventFlags interactiveEventFlags;
        private ExpressionFlags interactiveExpressionFlags;
#endif

        private VariableFlags newGlobalVariableFlags;
        private VariableFlags newLocalVariableFlags;
        private ProcedureFlags procedureFlags;
        private PluginFlags pluginFlags;

#if NOTIFY || NOTIFY_OBJECT
        private NotifyType notifyTypes;
        private NotifyFlags notifyFlags;
        private bool notify;
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Unknown Handler Data
        private string unknown;          // NOTE: Unknown command handler.
        private string packageUnknown;   // NOTE: Unknown package handler.
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICacheManager Members
#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        public int ClearCaches(
            CacheFlags cacheFlags
            )
        {
            CheckDisposed();

            int result = 0;

            lock (syncRoot)
            {
                #region StringList Cache
#if LIST_CACHE
                if ((stringListCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.StringList, true))
                {
                    result += stringListCache.Count;
                    stringListCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref stringListCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

#if PARSE_CACHE
                #region ParseState Cache
                if ((parseStateCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.ParseState, true))
                {
                    result += parseStateCache.Count;
                    parseStateCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref parseStateCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region ExpressionState Cache
                #region Dead Code
#if DEAD_CODE
                if ((expressionStateCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.ExpressionState, true))
                {
                    result += expressionStateCache.Count;
                    expressionStateCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref expressionStateCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
#endif
                #endregion
                #endregion
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

                #region IExecute Cache
#if EXECUTE_CACHE
                if ((executeCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.IExecute, true))
                {
                    result += executeCache.Count;
                    executeCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref executeCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }

                if ((hiddenExecuteCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.IExecute, true))
                {
                    result += hiddenExecuteCache.Count;
                    hiddenExecuteCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref hiddenExecuteCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Type Cache
#if TYPE_CACHE
                if ((typeCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.Type, true))
                {
                    result += typeCache.Count;
                    typeCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref typeCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region ComTypeList Cache
#if COM_TYPE_CACHE
                if ((comTypeListCache != null) &&
                    FlagOps.HasFlags(cacheFlags, CacheFlags.ComTypeList, true))
                {
                    result += comTypeListCache.Count;
                    comTypeListCache.Clear();

#if CACHE_STATISTICS
                    Interlocked.Increment(
                        ref comTypeListCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
                }
#endif
                #endregion
            }

            return result;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if EXECUTE_CACHE
        private void ClearExecuteCache()
        {
            if (hiddenExecuteCache != null)
            {
                hiddenExecuteCache.Clear();

#if CACHE_STATISTICS
                Interlocked.Increment(
                    ref hiddenExecuteCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
            }

            if (executeCache != null)
            {
                executeCache.Clear();

#if CACHE_STATISTICS
                Interlocked.Increment(
                    ref executeCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDebugManager Members
        public bool Debug
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return FlagOps.HasFlags(createFlags, CreateFlags.Debug, true);
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    if (value)
                        createFlags |= CreateFlags.Debug;
                    else
                        createFlags &= ~CreateFlags.Debug;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER
        public bool SingleStep
        {
            get
            {
                CheckDisposed();

#if !THREADING
                lock (syncRoot)
#endif
                {
                    IDebugger debugger = Debugger;

                    return (debugger != null) ?
                        debugger.SingleStep : false;
                }
            }
            set
            {
                CheckDisposed();

#if !THREADING
                lock (syncRoot)
#endif
                {
                    IDebugger debugger = Debugger;

                    if (debugger != null)
                        debugger.SingleStep = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsDebuggerAvailable()
        {
            CheckDisposed();

#if !THREADING
            lock (syncRoot)
#endif
            {
                return (Debugger != null);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsDebuggerActive()
        {
            CheckDisposed();

            return PrivateIsDebuggerActive();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public InteractiveLoopCallback InteractiveLoopCallback
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.InteractiveLoopCallback;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return interactiveLoopCallback;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.InteractiveLoopCallback = value;
#else
                lock (syncRoot)
                {
                    interactiveLoopCallback = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public TextWriter TraceTextWriter /* WARNING: NOT USED */
        {
            get { CheckDisposed(); lock (syncRoot) { return traceTextWriter; } }
            set { CheckDisposed(); lock (syncRoot) { traceTextWriter = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public TextWriter DebugTextWriter
        {
            get { CheckDisposed(); lock (syncRoot) { return debugTextWriter; } }
            set { CheckDisposed(); lock (syncRoot) { debugTextWriter = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
#if DEBUGGER
        private bool PrivateIsDebuggerActive()
        {
#if !THREADING
            lock (syncRoot)
#endif
            {
                IDebugger debugger = Debugger;

                return ((debugger != null) && (debugger.Active > 0));
            }
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IEngineManager Members
        #region Script Cancellation
        public ReturnCode IsCanceled(
            bool updateResult,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.IsCanceled(
                this, updateResult, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CancelEvaluate(
            bool unwind,
            Result result,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.CancelEvaluate(
                this, unwind, result, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CancelAnyEvaluate(
            bool unwind,
            bool strict,
            Result result,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code;
            Result localError = null;

            //
            // NOTE: Cancel any outstanding script in the interpreter.
            //
            code = Engine.CancelEvaluate(this, unwind, result, ref localError);

            if (code != ReturnCode.Ok)
            {
                if (strict)
                {
                    error = localError;
                    return code;
                }
                else
                {
                    DebugOps.Complain(this, code, localError);

                    code = ReturnCode.Ok;
                }
            }

            //
            // NOTE: Attempt to cancel any outstanding Tcl scripts in the Tcl
            //       interpreters for this interpreter.
            //
#if NATIVE && TCL
            ITclApi tclApi = null;
            IntPtrList interps = null;

            lock (tclSyncRoot)
            {
                //
                // NOTE: Get the Tcl API object from the interpreter.
                //
                tclApi = this.tclApi;

                //
                // NOTE: Get the list of Tcl interpreters from the interpreter.
                //
                if (HasTclInterpreters())
                    interps = new IntPtrList(tclInterps.Values);
            }

            //
            // NOTE: If the interpreter has a Tcl API object and a list of
            //       interpreters, try to cancel them all now.  It must also
            //       support script cancellation (via TIP 285).
            //
            if ((tclApi != null) && (tclApi.CancelEval != null) && (interps != null))
            {
                IClientData clientData = null;

                foreach (IntPtr interp in interps)
                {
                    code = TclWrapper.CancelEvaluate(tclApi, interp, unwind,
                        result, ref clientData, ref localError);

                    if (code != ReturnCode.Ok)
                    {
                        if (strict)
                        {
                            error = localError;
                            return code;
                        }
                        else
                        {
                            DebugOps.Complain(this, code, localError);

                            code = ReturnCode.Ok;
                        }
                    }
                }
            }
#endif

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        #region Cancel Flags & Results
        internal bool Cancel
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return cancel;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    cancel = value;

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Interpreter, NotifyFlags.Canceled,
                        cancel, this,
                        null, null, null);
#endif
                //}
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void ResetCancel(
            bool notify
            ) /* NO-LOCK */
        {
            if (cancel)
            {
                cancel = false;

#if NOTIFY
                if (notify)
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Interpreter, NotifyFlags.Reset | NotifyFlags.Canceled,
                        cancel, this,
                        null, null, null);
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool Unwind
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return unwind;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    unwind = value;

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Interpreter, NotifyFlags.Unwound,
                        unwind, this,
                        null, null, null);
#endif
                //}
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool Halt
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return halt;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    halt = value;

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Interpreter, NotifyFlags.Halted,
                        halt, this,
                        null, null, null);
#endif
                //}
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal Result CancelResult
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return cancelResult;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    cancelResult = value;
                //}
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal Result HaltResult
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return haltResult;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    haltResult = value;
                //}
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interrupt Callback Handling
        internal InterruptCallback InterruptCallback
        {
            get
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    return interruptCallback;
                //}
            }
            set
            {
                // CheckDisposed();

                //lock (syncRoot)
                //{
                    interruptCallback = value;
                //}
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode FireInterruptCallback(
            InterruptType interruptType,
            IClientData clientData,
            ref Result error
            )
        {
            // CheckDisposed();

            InterruptCallback interruptCallback;

            lock (syncRoot)
            {
                interruptCallback = this.interruptCallback;
                this.interruptCallback = null;
            }

            try
            {
                if (interruptCallback != null)
                {
                    try
                    {
                        return interruptCallback(
                            this, interruptType, clientData, ref error);
                    }
                    catch (Exception e)
                    {
                        error = e;
                    }

                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            finally
            {
                lock (syncRoot)
                {
                    this.interruptCallback = interruptCallback;
                    interruptCallback = null;
                }
            }
        }
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Evaluation
        public ReturnCode EvaluateScript(
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateScript(
            string text,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, ref result,
                ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateScript(
            IScript script,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateScript(
                script, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateScript(
            IScript script,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, script, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalScript(
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalScript(
            string text,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateFile(
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateFile(
                fileName, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateFile(
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(
                this, fileName, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, ref result,
                ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateFile(
            Encoding encoding,
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateFile(
                encoding, fileName, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateFile(
            Encoding encoding,
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(
                this, encoding, fileName, engineFlags,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalFile(
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateGlobalFile(
                fileName, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalFile(
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(
                this, fileName, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalFile(
            Encoding encoding,
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateGlobalFile(
                encoding, fileName, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalFile(
            Encoding encoding,
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(this, encoding, fileName,
                engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateStream(
                this, name, textReader, startIndex, characters,
                engineFlags, substitutionFlags, engineEventFlags,
                expressionFlags, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            return Engine.EvaluateStream(
                this, name, textReader, startIndex, characters,
                engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedScript(
            string text,
            bool force,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateTrustedScript(
                text, force, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedScript(
            string text,
            bool force,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            //
            // NOTE: Use of this method is currently limited to "safe" slave
            //       interpreters only.  Issue an error message if called for
            //       an "unsafe" interpreter.
            //
            if (!force && !IsSafe())
            {
                result = "unsafe interpreter cannot evaluate trusted script";
                return ReturnCode.Error;
            }

            //
            // HACK: If necessary, add the "IgnoreHidden" engine flag to the
            //       per-thread engine flags for this interpreter so that the
            //       script specified by the caller can run with full trust.
            //       The per-thread engine flags must be used in this case;
            //       otherwise, other scripts being evaluated on other threads
            //       in this interpreter would also gain full trust.
            //
            bool added = false;

            if (!Engine.HasIgnoreHidden(this.ContextEngineFlags))
            {
                added = true;
                this.ContextEngineFlags |= EngineFlags.IgnoreHidden;
            }

            try
            {
                return Engine.EvaluateScript(
                    this, text, engineFlags, substitutionFlags,
                    engineEventFlags, expressionFlags, ref result,
                    ref errorLine);
            }
            finally
            {
                if (added)
                {
                    this.ContextEngineFlags &= ~EngineFlags.IgnoreHidden;
                    added = false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedFile(
            Encoding encoding,
            string fileName,
            bool force,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateTrustedFile(
                encoding, fileName, force, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedFile(
            Encoding encoding,
            string fileName,
            bool force,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            //
            // NOTE: Use of this method is currently limited to "safe" slave
            //       interpreters only.  Issue an error message if called for
            //       an "unsafe" interpreter.
            //
            if (!force && !IsSafe())
            {
                result = "unsafe interpreter cannot evaluate trusted file";
                return ReturnCode.Error;
            }

            //
            // HACK: If necessary, add the "IgnoreHidden" engine flag to the
            //       per-thread engine flags for this interpreter so that the
            //       script specified by the caller can run with full trust.
            //       The per-thread engine flags must be used in this case;
            //       otherwise, other scripts being evaluated on other threads
            //       in this interpreter would also gain full trust.
            //
            bool added = false;

            if (!Engine.HasIgnoreHidden(this.ContextEngineFlags))
            {
                added = true;
                this.ContextEngineFlags |= EngineFlags.IgnoreHidden;
            }

            try
            {
                return Engine.EvaluateFile(
                    this, encoding, fileName, engineFlags,
                    substitutionFlags, engineEventFlags,
                    expressionFlags, ref result, ref errorLine);
            }
            finally
            {
                if (added)
                {
                    this.ContextEngineFlags &= ~EngineFlags.IgnoreHidden;
                    added = false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            bool force,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            ReturnCode code = EvaluateTrustedStream(
                name, textReader, startIndex, characters,
                force, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTrustedStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            bool force,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            //
            // NOTE: Use of this method is currently limited to "safe" slave
            //       interpreters only.  Issue an error message if called for
            //       an "unsafe" interpreter.
            //
            if (!force && !IsSafe())
            {
                result = "unsafe interpreter cannot evaluate trusted stream";
                return ReturnCode.Error;
            }

            //
            // HACK: If necessary, add the "IgnoreHidden" engine flag to the
            //       per-thread engine flags for this interpreter so that the
            //       script specified by the caller can run with full trust.
            //       The per-thread engine flags must be used in this case;
            //       otherwise, other scripts being evaluated on other threads
            //       in this interpreter would also gain full trust.
            //
            bool added = false;

            if (!Engine.HasIgnoreHidden(this.ContextEngineFlags))
            {
                added = true;
                this.ContextEngineFlags |= EngineFlags.IgnoreHidden;
            }

            try
            {
                return Engine.EvaluateStream(
                    this, name, textReader, startIndex, characters,
                    engineFlags, substitutionFlags, engineEventFlags,
                    expressionFlags, ref result, ref errorLine);
            }
            finally
            {
                if (added)
                {
                    this.ContextEngineFlags &= ~EngineFlags.IgnoreHidden;
                    added = false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ReturnCode EvaluateScript(
            string text,
            IScriptLocation location,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(location);

            try
            {
#endif
                return EvaluateScript(text, ref result);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(location);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Dead Code
#if DEAD_CODE
        internal ReturnCode EvaluateScript(
            string text,
            IScriptLocation location,
            ref Result result,
            ref int errorLine
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(location);

            try
            {
#endif
                return EvaluateScript(text, ref result, ref errorLine);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(location);
            }
#endif
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateScript( /* CORE COMMAND USE ONLY */
            Argument argument,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(argument);

            try
            {
#endif
                return EvaluateScript((string)argument, ref result);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(argument);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateScript( /* FOR [catch] USE ONLY */
            Argument argument,
            EngineFlags engineFlags,
            ref Result result,
            ref int errorLine
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(argument);

            try
            {
#endif
                return Engine.EvaluateScript(
                    this, argument, engineFlags, substitutionFlags,
                    engineEventFlags, expressionFlags, ref result,
                    ref errorLine);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(argument);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateScript(
            ArgumentList arguments,
            int startIndex,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

            int errorLine = 0;

            ReturnCode code = EvaluateScript(
                arguments, startIndex, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(this, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateScript(
            ArgumentList arguments,
            int startIndex,
            ref Result result,
            ref int errorLine
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            IScriptLocation location = null;

            if (ScriptOps.GetLocation(
                    this, arguments, startIndex, ref location,
                    ref result) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            PushScriptLocation(location);

            try
            {
#endif
                return EvaluateScript(
                    ListOps.Concat(arguments, startIndex), ref result,
                    ref errorLine);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(location);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluatePromptScript(
            string text,
            ref Result result,
            ref int errorLine
            )
        {
            return Engine.EvaluateScript(
                this, text, engineFlags | EngineFlags.ResetCancel,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result, ref errorLine);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Expression Evaluation
        public ReturnCode EvaluateExpression(
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.EvaluateExpression(
                this, text, engineFlags,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal static bool HasTraceResult(
            InterpreterFlags interpreterFlags
            )
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.TraceResult, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateExpression(
            Argument argument,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(argument);

            try
            {
#endif
                return EvaluateExpression((string)argument, ref result);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(argument);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateExpression(
            ArgumentList arguments,
            int startIndex,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            IScriptLocation location = null;

            if (ScriptOps.GetLocation(
                    this, arguments, startIndex, ref location,
                    ref result) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            PushScriptLocation(location);

            try
            {
#endif
                return EvaluateExpression(
                    ListOps.Concat(arguments, startIndex), ref result);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(location);
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode EvaluateExpressionWithErrorInfo(
            Argument argument,
            string errorInfo,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

#if DEBUGGER && BREAKPOINTS
            PushScriptLocation(argument);

            try
            {
#endif
                return Engine.EvaluateExpressionWithErrorInfo(
                    this, argument, engineFlags, substitutionFlags,
                    engineEventFlags, expressionFlags, errorInfo,
                    ref result);
#if DEBUGGER && BREAKPOINTS
            }
            finally
            {
                PopScriptLocation(argument);
            }
#endif
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Substitution Processing
        public ReturnCode SubstituteString(
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteString(text, substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteString(
            string text,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteString(
                this, text, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalString(
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteGlobalString(text, substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalString(
            string text,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteString(
                this, text, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteFile(
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteFile(
                fileName, substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteFile(
            string fileName,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteFile(
                this, fileName, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalFile(
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteGlobalFile(
                fileName, substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalFile(
            string fileName,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteFile(
                this, fileName, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteStream(
                name, textReader, startIndex, characters,
                substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteStream(
                this, name, textReader, startIndex, characters,
                engineFlags, substitutionFlags, engineEventFlags,
                expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteGlobalStream(
                name, textReader, startIndex, characters,
                substitutionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalStream(
            string name,
            TextReader textReader,
            int startIndex,
            int characters,
            SubstitutionFlags substitutionFlags,
            ref Result result
            )
        {
            CheckDisposed();

            return Engine.SubstituteStream(
                this, name, textReader, startIndex, characters,
                engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Asynchronous Script Evaluation
        public ReturnCode EvaluateScript(
            string text,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags, substitutionFlags, engineEventFlags,
                expressionFlags, callback, clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateFile(
            string fileName,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(
                this, fileName, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, callback,
                clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalScript(
            string text,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.EvaluateScript(
                this, text, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                callback, clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateGlobalFile(
            string fileName,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.EvaluateFile(
                this, fileName, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                callback, clientData, ref error);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Asynchronous Substitution Processing
        public ReturnCode SubstituteString(
            string text,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return SubstituteString(
                text, substitutionFlags, callback, clientData,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteString(
            string text,
            SubstitutionFlags substitutionFlags,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.SubstituteString(
                this, text, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, callback,
                clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalString(
            string text,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return SubstituteGlobalString(
                text, substitutionFlags, callback, clientData,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalString(
            string text,
            SubstitutionFlags substitutionFlags,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.SubstituteString(
                this, text, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                callback, clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteFile(
            string fileName,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return SubstituteFile(
                fileName, substitutionFlags,
                callback, clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteFile(
            string fileName,
            SubstitutionFlags substitutionFlags,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.SubstituteFile(
                this, fileName, engineFlags, substitutionFlags,
                engineEventFlags, expressionFlags, callback,
                clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalFile(
            string fileName,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return SubstituteGlobalFile(
                fileName, substitutionFlags,
                callback, clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteGlobalFile(
            string fileName,
            SubstitutionFlags substitutionFlags,
            AsynchronousCallback callback, /* NOTE: May be null for "fire-and-forget" type scripts. */
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            return Engine.SubstituteFile(
                this, fileName, engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, engineEventFlags, expressionFlags,
                callback, clientData, ref error);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Command Execution
        public ReturnCode Invoke(
            string name,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            CheckDisposed();

            EngineFlags engineFlags = GetResolveEngineFlags(true);
            IExecute execute = null;

            if (GetIExecuteViaResolvers(
                    engineFlags, name, arguments, LookupFlags.Default,
                    ref execute, ref result) == ReturnCode.Ok)
            {
                return Engine.Execute(
                    name, execute, this, clientData, arguments,
                    engineFlags, substitutionFlags, engineEventFlags,
                    expressionFlags, ref result);
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal long OperationCount
        {
            get
            {
                lock (syncRoot)
                {
                    return operationCount;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal long CommandCount
        {
            get
            {
                lock (syncRoot)
                {
                    return commandCount;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void IncrementOperationCount()
        {
            Interlocked.Increment(ref operationCount);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void IncrementCommandCount()
        {
            Interlocked.Increment(ref commandCount);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode Execute(
            string name,
            IExecute execute,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

            return Engine.Execute(
                name, execute, this, clientData, arguments, engineFlags,
                substitutionFlags, engineEventFlags, expressionFlags,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Hidden IProcedure, IExecute, ICommand
        internal ReturnCode ExecuteHidden(
            string name,
            IExecute execute,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            // CheckDisposed(); /* NON-PUBLIC, SANITY */

            return Engine.Execute(
                name, execute, this, clientData, arguments,
                engineFlags | EngineFlags.InvokeHidden,
                substitutionFlags, engineEventFlags,
                expressionFlags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This method cannot currently fail.
        //
        internal ReturnCode MoveExposedAndHiddenCommands(
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if ((procedures != null) && (hiddenProcedures != null))
                {
                    ProcedureWrapperDictionary localProcedures;

                    ///////////////////////////////////////////////////////////////////////////////////

                    localProcedures = new ProcedureWrapperDictionary(procedures);

                    foreach (KeyValuePair<string, _Wrappers.Procedure> pair in localProcedures)
                    {
                        if ((pair.Value != null) && EntityOps.IsHidden(pair.Value))
                        {
                            hiddenProcedures.Add(pair.Key, pair.Value);
                            procedures.Remove(pair.Key);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(pair.Key, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(pair.Key, false);
#endif
                        }
                    }

                    ///////////////////////////////////////////////////////////////////////////////////

                    localProcedures = new ProcedureWrapperDictionary(hiddenProcedures);

                    foreach (KeyValuePair<string, _Wrappers.Procedure> pair in localProcedures)
                    {
                        if ((pair.Value != null) && !EntityOps.IsHidden(pair.Value))
                        {
                            procedures.Add(pair.Key, pair.Value);
                            hiddenProcedures.Remove(pair.Key);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(pair.Key, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(pair.Key, false);
#endif
                        }
                    }
                }

                if ((commands != null) && (hiddenCommands != null))
                {
                    CommandWrapperDictionary localCommands;

                    ///////////////////////////////////////////////////////////////////////////////////

                    localCommands = new CommandWrapperDictionary(commands);

                    foreach (KeyValuePair<string, _Wrappers.Command> pair in localCommands)
                    {
                        if ((pair.Value != null) && EntityOps.IsHidden(pair.Value))
                        {
                            hiddenCommands.Add(pair.Key, pair.Value);
                            commands.Remove(pair.Key);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(pair.Key, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(pair.Key, false);
#endif
                        }
                    }

                    ///////////////////////////////////////////////////////////////////////////////////

                    localCommands = new CommandWrapperDictionary(hiddenCommands);

                    foreach (KeyValuePair<string, _Wrappers.Command> pair in localCommands)
                    {
                        if ((pair.Value != null) && !EntityOps.IsHidden(pair.Value))
                        {
                            commands.Add(pair.Key, pair.Value);
                            hiddenCommands.Remove(pair.Key);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(pair.Key, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(pair.Key, false);
#endif
                        }
                    }
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ExposeCommand(
            string name,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                IExecute execute = null;

                if (GetIExecuteViaResolvers(
                        GetResolveEngineFlags(true) | EngineFlags.UseHidden, name,
                        null, LookupFlags.NoVerbose, ref execute) == ReturnCode.Ok)
                {
                    if (execute is _Wrappers._Execute)
                    {
                        if (HasIExecutes(ref error) && HasHiddenIExecutes(ref error))
                        {
                            _Wrappers._Execute executeWrapper = (_Wrappers._Execute)execute;

                            string newName = ScriptOps.MakeCommandName(name);

                            executes.Add(newName, executeWrapper);
                            hiddenExecutes.Remove(newName);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(newName, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(newName, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else if (execute is _Wrappers.Procedure)
                    {
                        if (HasProcedures(ref error) && HasHiddenProcedures(ref error))
                        {
                            _Wrappers.Procedure procedureWrapper = (_Wrappers.Procedure)execute;

                            procedures.Add(procedureWrapper.Name, procedureWrapper);
                            hiddenProcedures.Remove(procedureWrapper.Name);

                            procedureWrapper.Flags &= ~ProcedureFlags.Hidden;

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(procedureWrapper.Name, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(procedureWrapper.Name, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else if (execute is _Wrappers.Command)
                    {
                        if (HasCommands(ref error) && HasHiddenCommands(ref error))
                        {
                            _Wrappers.Command commandWrapper = (_Wrappers.Command)execute;

                            commands.Add(commandWrapper.Name, commandWrapper);
                            hiddenCommands.Remove(commandWrapper.Name);

                            commandWrapper.Flags &= ~CommandFlags.Hidden;

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(commandWrapper.Name, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(commandWrapper.Name, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        error = String.Format(
                            "unknown execution type for \"{0}\"",
                            name);
                    }
                }
                else
                {
                    error = String.Format(
                        "unknown hidden command \"{0}\"",
                        name);
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode HideCommand(
            string name,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                IExecute execute = null;

                if (GetIExecuteViaResolvers(
                        GetResolveEngineFlags(true), name, null,
                        LookupFlags.NoVerbose, ref execute) == ReturnCode.Ok)
                {
                    if (execute is _Wrappers._Execute)
                    {
                        if (HasIExecutes(ref error) && HasHiddenIExecutes(ref error))
                        {
                            _Wrappers._Execute executeWrapper = (_Wrappers._Execute)execute;

                            string newName = ScriptOps.MakeCommandName(name);

                            hiddenExecutes.Add(newName, executeWrapper);
                            executes.Remove(newName);

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(newName, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(newName, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else if (execute is _Wrappers.Procedure)
                    {
                        if (HasProcedures(ref error) && HasHiddenProcedures(ref error))
                        {
                            _Wrappers.Procedure procedureWrapper = (_Wrappers.Procedure)execute;

                            hiddenProcedures.Add(procedureWrapper.Name, procedureWrapper);
                            procedures.Remove(procedureWrapper.Name);

                            procedureWrapper.Flags |= ProcedureFlags.Hidden;

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(procedureWrapper.Name, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(procedureWrapper.Name, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else if (execute is _Wrappers.Command)
                    {
                        if (HasCommands(ref error) && HasHiddenCommands(ref error))
                        {
                            _Wrappers.Command commandWrapper = (_Wrappers.Command)execute;

                            hiddenCommands.Add(commandWrapper.Name, commandWrapper);
                            commands.Remove(commandWrapper.Name);

                            commandWrapper.Flags |= CommandFlags.Hidden;

#if EXECUTE_CACHE
                            if (executeCache != null)
                                executeCache.Remove(commandWrapper.Name, false);

                            if (hiddenExecuteCache != null)
                                hiddenExecuteCache.Remove(commandWrapper.Name, false);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        error = String.Format(
                            "unknown execution type for \"{0}\"",
                            name);
                    }
                }
                else
                {
                    error = String.Format(
                        "unknown command \"{0}\"",
                        name);
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallbackQueueManager Members
#if CALLBACK_QUEUE
        public bool HasCallbackQueue(ref Result error)
        {
            CheckDisposed();

            bool result = (callbackQueue != null);

            if (!result)
                error = "callback queue not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ClearCallbackQueue(
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCallbackQueue(ref error))
                {
                    callbackQueue.Clear();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EnqueueCallback(
            ICallback callback,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCallbackQueue(ref error))
                {
                    CommandCallback commandCallback =
                        callback as CommandCallback;

                    if (commandCallback != null)
                    {
                        callbackQueue.Enqueue(commandCallback);

                        code = ReturnCode.Ok;
                    }
                    else
                    {
                        error = "invalid command callback";
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DequeueCallback(
            ref ICallback callback,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCallbackQueue(ref error))
                {
                    if (callbackQueue.Count > 0)
                    {
                        callback = callbackQueue.Dequeue();

                        code = ReturnCode.Ok;
                    }
                    else
                    {
                        error = "callback queue is empty";
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ReturnCode CountCallbacks(
            ref int count,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCallbackQueue(ref error))
                {
                    count = callbackQueue.Count;
                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListCallbacks(
            string pattern,
            bool noCase,
            ref StringList list,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCallbackQueue(ref error))
                {
                    StringList inputList = new StringList(
                        callbackQueue.ToArray());

                    StringList outputList = new StringList();

                    code = GenericOps<string>.FilterList(
                        inputList, outputList, Index.Invalid, Index.Invalid,
                        ToStringFlags.None, pattern, noCase, ref error);

                    if (code == ReturnCode.Ok)
                        list = outputList;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DequeueCallback(
            ref CommandCallback callback
            )
        {
            ICallback localCallback = null;
            Result error = null;

            if (DequeueCallback(ref localCallback, ref error) == ReturnCode.Ok)
            {
                if (localCallback is CommandCallback)
                {
                    callback = (CommandCallback)localCallback;

                    return ReturnCode.Ok;
                }
                else
                {
                    error = "invalid command callback";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ExecuteCallbackQueue(
            ref Result result
            )
        {
            return Engine.ExecuteCallbackQueue(
                this, engineFlags, substitutionFlags, engineEventFlags,
                expressionFlags, ref result);
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IEntityManager Members
        #region Entity Checking
        public bool HasAliases(ref Result error)
        {
            CheckDisposed();

            bool result = (aliases != null);

            if (!result)
                error = "aliases not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasCallbacks(ref Result error)
        {
            CheckDisposed();

            bool result = (callbacks != null);

            if (!result)
                error = "callbacks not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasChannels(ref Result error)
        {
            CheckDisposed();

            bool result = (channels != null);

            if (!result)
                error = "channels not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasCommands(ref Result error)
        {
            CheckDisposed();

            bool result = (commands != null);

            if (!result)
                error = "commands not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasFunctions(ref Result error)
        {
            CheckDisposed();

            bool result = (functions != null);

            if (!result)
                error = "functions not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasIExecutes(ref Result error)
        {
            CheckDisposed();

            bool result = (executes != null);

            if (!result)
                error = "executes not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasObjects(ref Result error)
        {
            CheckDisposed();

            bool result = (objects != null);

            if (!result)
                error = "objects not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasOperators(ref Result error)
        {
            CheckDisposed();

            bool result = (operators != null);

            if (!result)
                error = "operators not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasPackageIndexes(ref Result error)
        {
            CheckDisposed();

            bool result = (packageIndexes != null);

            if (!result)
                error = "package indexes not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasPackages(ref Result error)
        {
            CheckDisposed();

            bool result = (packages != null);

            if (!result)
                error = "packages not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasPlugins(ref Result error)
        {
            CheckDisposed();

            bool result = (plugins != null);

            if (!result)
                error = "plugins not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasPolicies(ref Result error)
        {
            CheckDisposed();

            bool result = (policies != null);

            if (!result)
                error = "policies not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasProcedures(ref Result error)
        {
            CheckDisposed();

            bool result = (procedures != null);

            if (!result)
                error = "procedures not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasScopes(ref Result error)
        {
            CheckDisposed();

            bool result = (scopes != null);

            if (!result)
                error = "scopes not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasTraces(ref Result error)
        {
            CheckDisposed();

            bool result = (traces != null);

            if (!result)
                error = "traces not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DATA
        public bool HasDbConnections(ref Result error)
        {
            CheckDisposed();

            bool result = (connections != null);

            if (!result)
                error = "database connections not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasDbTransactions(ref Result error)
        {
            CheckDisposed();

            bool result = (transactions != null);

            if (!result)
                error = "database transactions not available";

            return result;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && LIBRARY
        public bool HasDelegates(ref Result error)
        {
            CheckDisposed();

            bool result = (delegates != null);

            if (!result)
                error = "delegates not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasModules(ref Result error)
        {
            CheckDisposed();

            bool result = (modules != null);

            if (!result)
                error = "modules not available";

            return result;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Entity Detection
        public ReturnCode DoesAliasExist(string name)
        {
            CheckDisposed();

            IAlias alias = null;
            Result error = null;

            return GetAlias(name, LookupFlags.Exists, ref alias, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesCallbackExist(string name)
        {
            CheckDisposed();

            ICallback callback = null;
            Result error = null;

            return GetCallback(name, LookupFlags.Exists, ref callback, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesChannelExist(string name)
        {
            CheckDisposed();

            Result error = null;
            Channel channel = GetChannel(name, ref error);

            if (channel != null)
                return ReturnCode.Ok;
            else
                return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesCommandExist(string name)
        {
            CheckDisposed();

            ICommand command = null;
            Result error = null;

            return GetCommand(name, LookupFlags.Exists, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesFunctionExist(string name)
        {
            CheckDisposed();

            IFunction function = null;
            Result error = null;

            return GetFunction(name, LookupFlags.Exists, ref function, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesIExecuteExist(string name)
        {
            CheckDisposed();

            IExecute execute = null;
            Result error = null;

            return GetIExecute(name, LookupFlags.Exists, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesObjectExist(string name)
        {
            CheckDisposed();

            IObject @object = null;
            Result error = null;

            return GetObject(name, LookupFlags.Exists, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesOperatorExist(string name)
        {
            CheckDisposed();

            IOperator @operator = null;
            Result error = null;

            return GetOperator(name, LookupFlags.Exists, ref @operator, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesPackageExist(string name)
        {
            CheckDisposed();

            IPackage package = null;
            Result error = null;

            return GetPackage(name, LookupFlags.Exists, ref package, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesPluginExist(string name)
        {
            CheckDisposed();

            IPlugin plugin = null;
            Result error = null;

            return GetPlugin(name, LookupFlags.Exists, ref plugin, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesPolicyExist(string name)
        {
            CheckDisposed();

            IPolicy policy = null;
            Result error = null;

            return GetPolicy(name, LookupFlags.Exists, ref policy, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesProcedureExist(string name)
        {
            CheckDisposed();

            IProcedure procedure = null;
            Result error = null;

            return GetProcedure(name, LookupFlags.Exists, ref procedure, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesScopeExist(string name)
        {
            CheckDisposed();

            ICallFrame frame = null;
            Result error = null;

            return GetScope(name, LookupFlags.Exists, ref frame, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesTraceExist(string name)
        {
            CheckDisposed();

            ITrace trace = null;
            Result error = null;

            return GetTrace(name, LookupFlags.Exists, ref trace, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && LIBRARY
        public ReturnCode DoesDelegateExist(string name)
        {
            CheckDisposed();

            IDelegate @delegate = null;
            Result error = null;

            return GetDelegate(name, LookupFlags.Exists, ref @delegate, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesModuleExist(string name)
        {
            CheckDisposed();

            IModule module = null;
            Result error = null;

            return GetModule(name, LookupFlags.Exists, ref module, ref error);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode DoesCommandExist(long token)
        {
            string name = null;
            ICommand command = null;
            Result error = null;

            return GetCommand(token, LookupFlags.Exists, ref name, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode DoesFunctionExist(long token)
        {
            string name = null;
            IFunction function = null;
            Result error = null;

            return GetFunction(token, LookupFlags.Exists, ref name, ref function, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode DoesPolicyExist(long token)
        {
            string name = null;
            IPolicy policy = null;
            Result error = null;

            return GetPolicy(token, LookupFlags.Exists, ref name, ref policy, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode DoesTraceExist(long token)
        {
            string name = null;
            ITrace trace = null;
            Result error = null;

            return GetTrace(token, LookupFlags.Exists, ref name, ref trace, ref error);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Entity Management
        #region IIdentifier
        public ReturnCode GetIdentifier(
            IdentifierKind kind,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref IIdentifier identifier,
            ref Result error
            )
        {
            CheckDisposed();

            switch (kind)
            {
                case IdentifierKind.Policy:
                    {
                        IPolicy policy = null;

                        if (GetPolicy(
                                name, lookupFlags, ref policy,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = policy;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Trace:
                    {
                        ITrace trace = null;

                        if (GetTrace(
                                name, lookupFlags, ref trace,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = trace;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.AnyIExecute: /* NOTE: IExecute may or may not derive from IIdentifier. */
                    {
                        IExecute execute = null;

                        if (GetIExecuteViaResolvers(
                                GetResolveEngineFlags(true), name,
                                arguments, lookupFlags, ref execute,
                                ref error) == ReturnCode.Ok)
                        {
                            if (execute is IIdentifier)
                            {
                                identifier = (IIdentifier)execute;
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = "invalid identifier";
                            }
                        }
                        break;
                    }
                case IdentifierKind.Command:
                    {
                        ICommand command = null;

                        if (GetCommand(
                                name, lookupFlags, ref command,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = command;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.HiddenCommand:
                    {
                        ICommand command = null;

                        if (GetHiddenCommand(
                                name, lookupFlags, ref command,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = command;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Ensemble: /* NOTE: ICommand may or may not derive from _Commands.Ensemble. */
                    {
                        ICommand command = null;
                        Result localError = null;

                        if (GetCommand(
                                name, lookupFlags, ref command,
                                ref localError) == ReturnCode.Ok)
                        {
                            if (command is _Commands.Ensemble)
                            {
                                identifier = command;
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = "invalid ensemble";
                            }
                        }
                        else
                        {
                            ResultList errors = new ResultList();

                            errors.Add(localError);

                            if (GetHiddenCommand(
                                    name, lookupFlags, ref command,
                                    ref localError) == ReturnCode.Ok)
                            {
                                if (command is _Commands.Ensemble)
                                {
                                    identifier = command;
                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    errors.Add("invalid ensemble");
                                }
                            }
                            else
                            {
                                errors.Add(localError);
                            }

                            error = errors;
                        }
                        break;
                    }
                case IdentifierKind.Procedure:
                    {
                        IProcedure procedure = null;

                        if (GetProcedure(
                                name, lookupFlags, ref procedure,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = procedure;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.HiddenProcedure:
                    {
                        IProcedure procedure = null;

                        if (GetHiddenProcedure(
                                name, lookupFlags, ref procedure,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = procedure;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.IExecute: /* NOTE: IExecute may or may not derive from IIdentifier. */
                    {
                        IExecute execute = null;

                        if (GetIExecute(
                                name, lookupFlags, ref execute,
                                ref error) == ReturnCode.Ok)
                        {
                            if (execute is IIdentifier)
                            {
                                identifier = (IIdentifier)execute;
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = "invalid identifier";
                            }
                        }
                        break;
                    }
                case IdentifierKind.HiddenIExecute:
                    {
                        IExecute execute = null;

                        if (GetHiddenIExecute(
                                name, lookupFlags, ref execute,
                                ref error) == ReturnCode.Ok)
                        {
                            if (execute is IIdentifier)
                            {
                                identifier = (IIdentifier)execute;
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = "invalid identifier";
                            }
                        }
                        break;
                    }
                case IdentifierKind.Lambda:
                    {
                        #region Dead Code
#if DEAD_CODE
                        ILambda lambda = null;

                        if (GetLambda(
                                name, lookupFlags, ref lambda,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = lambda;
                            return ReturnCode.Ok;
                        }
#else
                        error = "not implemented";
#endif
                        #endregion
                        break;
                    }
                case IdentifierKind.Operator:
                    {
                        IOperator @operator = null;

                        if (GetOperator(
                                name, lookupFlags, ref @operator,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = @operator;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Function:
                    {
                        IFunction function = null;

                        if (GetFunction(
                                name, lookupFlags, ref function,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = function;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Variable:
                    {
                        VariableFlags flags = VariableFlags.NoElement;
                        IVariable variable = null;

                        if (GetVariableViaResolversWithSplit(
                                name, ref flags, ref variable,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = variable;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.CallFrame:
                    {
                        FrameResult frameResult;
                        ICallFrame frame = null;

                        frameResult = GetCallFrame(
                            name, ref frame, ref error);

                        if (frameResult != FrameResult.Invalid)
                        {
                            identifier = frame;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Package:
                    {
                        IPackage package = null;

                        if (GetPackage(
                                name, lookupFlags, ref package,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = package;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Plugin:
                    {
                        IPlugin plugin = null;

                        if (GetPlugin(
                                name, lookupFlags, ref plugin,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = plugin;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Object:
                    {
                        IObject @object = null;

                        if (GetObject(
                                name, lookupFlags, ref @object,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = @object;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.NativeModule:
                    {
#if NATIVE && LIBRARY
                        IModule module = null;

                        if (GetModule(
                                name, lookupFlags, ref module,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = module;
                            return ReturnCode.Ok;
                        }
#else
                        error = "not implemented";
#endif
                        break;
                    }
                case IdentifierKind.NativeDelegate:
                    {
#if NATIVE && LIBRARY
                        IDelegate @delegate = null;

                        if (GetDelegate(
                                name, lookupFlags, ref @delegate,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = @delegate;
                            return ReturnCode.Ok;
                        }
#else
                        error = "not implemented";
#endif
                        break;
                    }
                case IdentifierKind.Host:
                    {
                        if (String.IsNullOrEmpty(name))
                        {
                            identifier = this.Host;
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = "unsupported host type";
                        }
                        break;
                    }
                case IdentifierKind.Alias:
                    {
                        IAlias alias = null;

                        if (GetAlias(
                                name, lookupFlags, ref alias,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = alias;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Callback:
                    {
                        ICallback callback = null;

                        if (GetCallback(
                                name, lookupFlags, ref callback,
                                ref error) == ReturnCode.Ok)
                        {
                            identifier = callback;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.Resolve:
                    {
                        object enumValue = EnumOps.TryParseEnum(
                            typeof(Priority), name, true, ref error);

                        if (enumValue is Priority)
                        {
                            IResolve resolve = null;

                            if (GetResolver(
                                    (Priority)enumValue, ref resolve,
                                    ref error) == ReturnCode.Ok)
                            {
                                identifier = resolve;
                                return ReturnCode.Ok;
                            }
                        }
                        break;
                    }
                case IdentifierKind.Namespace:
                    {
                        INamespace @namespace = NamespaceOps.Lookup(
                            this, name, false, false, ref error);

                        if (@namespace != null)
                        {
                            identifier = @namespace;
                            return ReturnCode.Ok;
                        }
                        break;
                    }
                case IdentifierKind.PolicyData:
                case IdentifierKind.TraceData:
                case IdentifierKind.CommandData:
                case IdentifierKind.ProcedureData:
                case IdentifierKind.OperatorData:
                case IdentifierKind.FunctionData:
                case IdentifierKind.EnsembleData:
                case IdentifierKind.PackageData:
                case IdentifierKind.PluginData:
                case IdentifierKind.ObjectData:
                case IdentifierKind.ObjectTypeData:
                case IdentifierKind.ObjectType:
                case IdentifierKind.Option:
                case IdentifierKind.HostData:
                case IdentifierKind.AliasData:
                case IdentifierKind.DelegateData:
                case IdentifierKind.Delegate:
                case IdentifierKind.ResolveData:
                case IdentifierKind.ClockData:
                case IdentifierKind.Script:
                case IdentifierKind.ScriptBuilder:
                case IdentifierKind.NamespaceData:
                    {
                        error = "identifier kind not supported";
                        break;
                    }
                default:
                    {
                        error = "unknown identifier kind";
                        break;
                    }
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallback
        public ReturnCode GetCallback(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ICallback callback,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetCallback(
                        name, lookupFlags, ref token, ref callback,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid callback name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid callback name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddCallback(
            ICallback callback,
            IClientData clientData,
            ref long token, /* IGNORED */
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (callback == null)
                {
                    result = "invalid callback";
                    return ReturnCode.Error;
                }

                if (callback.Name == null)
                {
                    result = "invalid callback name";
                    return ReturnCode.Error;
                }

                if (!HasCallbacks(ref result))
                    return ReturnCode.Error;

                if (DoesCallbackExist(callback.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": callback already exists",
                        callback.Name);

                    return ReturnCode.Error;
                }

                callbacks.Add(callback.Name, callback);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Callback, NotifyFlags.Added,
                    callback, this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveCallback(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasCallbacks(ref result))
                {
                    long token = 0;
                    ICallback callback = null;

                    if (GetCallback(name, LookupFlags.Remove, ref token,
                            ref callback, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(callback))
                        {
                            callbacks.Remove(name);

#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Callback, NotifyFlags.Removed,
                                new ObjectPair(callback, token), this,
                                clientData, null, null, ref result);
#endif

                            return ReturnCode.Ok;
                        }
                        else
                        {
                            result = "callback is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string CallbacksToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (callbacks != null)
                    return callbacks.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetCallback(
            string name,
            LookupFlags lookupFlags,
            ref long token, /* IGNORED */
            ref ICallback callback,
            ref Result error
            )
        {
            if (!HasCallbacks(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid callback name";
                return ReturnCode.Error;
            }

            if (!callbacks.TryGetValue(name, out callback))
            {
                error = "callback not found";
                return ReturnCode.Error;
            }

            if ((callback == null) &&
                FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
            {
                error = "invalid callback";
                return ReturnCode.Error;
            }
            else
            {
                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // TODO: Make sure this method needs to be public.
        //       This is marked as internal for now.
        //
        internal ReturnCode GetCallback(
            string name,
            LookupFlags lookupFlags,
            ref ICallback callback
            )
        {
            // CheckDisposed();

            Result error = null;

            return GetCallback(name, lookupFlags, ref callback, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCallback(
            string name,
            LookupFlags lookupFlags,
            ref ICallback callback,
            ref Result error
            )
        {
            long token = 0;

            return GetCallback(name, lookupFlags, ref token, ref callback, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddCallback(
            ICallback callback,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddCallback(callback, clientData, ref token, ref result);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IExecute
        public ReturnCode GetIExecute(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IExecute execute,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetIExecute(
                        token, lookupFlags, ref name, ref execute,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid execute token \"{0}\"",
                            token) :
                        "invalid execute token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetIExecute(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetIExecute(
                        name, lookupFlags, ref token, ref execute,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid execute name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid execute name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ListIExecutes(
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasIExecutes(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        bool simple = NamespaceOps.ShouldUseSimpleMatching(
                            this, currentNamespace, pattern, false);

                        bool qualified = NamespaceOps.IsQualifiedName(pattern);

                        if ((code == ReturnCode.Ok) && simple)
                        {
                            code = NamespaceOps.MatchItems(
                                this, null, executes.Keys, pattern,
                                noCase, !qualified, qualified, false, ref list,
                                ref error);
                        }

                        if ((code == ReturnCode.Ok) && !simple)
                        {
                            code = NamespaceOps.MatchItems(
                                this, currentNamespace, executes.Keys, pattern,
                                noCase, !qualified, qualified, false, ref list,
                                ref error);
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = executes.ToList(
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddIExecute(
            string name,
            IExecute execute,
            IClientData clientData, /* NOT USED */
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (execute == null)
                {
                    result = "invalid execute";
                    return ReturnCode.Error;
                }

                if (name == null)
                {
                    result = "invalid execute name";
                    return ReturnCode.Error;
                }

                if (!HasIExecutes(ref result))
                    return ReturnCode.Error;

                //
                // WARNING: Currently, if somebody adds an IExecute that shadows a
                //          command or procedure (by name), it will take priority.
                //          This behavior could be prevented here by changing this
                //          check to be DoesAnyExecuteExist instead of DoesExecuteExist;
                //          however, I am not convinced that task should be the
                //          responsibility of this method (i.e. why should a method
                //          that deals with IExecute objects need to know about command
                //          or procedure objects?).  The spirit of this check is basically
                //          "can we physically add the object in question?".
                //
                if (DoesIExecuteExist(name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": execute already exists",
                        name);

                    return ReturnCode.Error;
                }

                Result localError = null;

                if (AreNamespacesEnabled() && (NamespaceOps.LookupParent(
                        this, name, false, true, true, ref localError) == null))
                {
                    result = String.Format(
                        "can't add execute \"{0}\": {1}",
                        name, localError);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers._Execute executeWrapper = new _Wrappers._Execute(id, execute);

                executes.Add(name, executeWrapper);
                token = EntityOps.GetToken(executeWrapper);

#if EXECUTE_CACHE
                if (executeCache != null)
                    executeCache.AddOrUpdate(name, executeWrapper, false);
#endif

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.IExecute, NotifyFlags.Added,
                    new ObjectPair(execute, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RenameIExecute(
            string oldName,
            string newName,
            bool delete,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasIExecutes(ref result))
                {
                    if (!delete || !String.IsNullOrEmpty(newName))
                    {
                        IExecute oldExecute = null;

                        if (GetIExecute(oldName, LookupFlags.Default, ref oldExecute, ref result) == ReturnCode.Ok)
                        {
                            _Wrappers._Execute oldWrapper = oldExecute as _Wrappers._Execute;

                            if (oldWrapper != null)
                            {
                                IAlias oldAlias = oldWrapper.execute as IAlias;

                                if (PreventAliasLoop(oldAlias, newName, ref result) == ReturnCode.Ok)
                                {
                                    if (IsValidCommandName(newName, ref result) == ReturnCode.Ok)
                                    {
                                        if (!AreNamespacesEnabled() ||
                                            RenameImportInNamespaces(oldName, newName, ref result) == ReturnCode.Ok)
                                        {
                                            /* IGNORED */
                                            executes.Rename(oldName, newName);

#if EXECUTE_CACHE
                                            if (executeCache != null)
                                                executeCache.Rename(oldName, newName, oldWrapper, false);
#endif

#if NOTIFY
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.IExecute, NotifyFlags.Renamed,
                                                new ObjectTriplet(oldExecute, oldName, newName), this,
                                                null, null, null, ref result);
#endif

                                            result = String.Empty;
                                            return ReturnCode.Ok;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                result = String.Format(
                                    "can't rename \"{0}\": invalid execute wrapper",
                                    oldName);
                            }
                        }
                        else
                        {
                            result = String.Format(
                                "can't rename \"{0}\": execute doesn't exist",
                                oldName);
                        }
                    }
                    else
                    {
                        return RemoveIExecute(oldName, null, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveIExecute(
            long token,
            IClientData clientData, /* NOT USED */
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasIExecutes(ref result))
                {
                    string name = null;
                    IExecute execute = null;

                    if (GetIExecute(token, LookupFlags.Remove, ref name,
                            ref execute, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveIExecute(
                            name, token, execute, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveIExecute(
            string name,
            IClientData clientData /* NOT USED */,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasIExecutes(ref result))
                {
                    long token = 0;
                    IExecute execute = null;

                    if (GetIExecute(name, LookupFlags.Remove, ref token,
                            ref execute, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveIExecute(
                            name, token, execute, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MatchIExecute(
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                bool useHidden = Engine.HasUseHidden(engineFlags);

                ExecuteWrapperDictionary localExecutes =
                    useHidden ? hiddenExecutes : executes;

                if (localExecutes != null)
                {
                    //
                    // NOTE: *WARNING* Empty command/procedure names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (localExecutes.Count > 0)
                        {
                            _Wrappers._Execute localExecute;
                            string exactName = null;
                            StringList list = new StringList();

                            if (localExecutes.TryGetValue(name, out localExecute))
                            {
                                //
                                // NOTE: Exact execute match.
                                //
                                exactName = name;

                                //
                                // NOTE: Store the exact execute match in the result
                                //       list.
                                //
                                list.Add(name);
                            }
                            else
                            {
                                foreach (KeyValuePair<string, _Wrappers._Execute> pair in localExecutes)
                                {
                                    if (String.Compare(
                                            pair.Key, 0, name, 0, name.Length,
                                            StringOps.SystemStringComparisonType) == 0)
                                    {
                                        //
                                        // NOTE: Was the key valid (this should always succeed).
                                        //
                                        if (pair.Key != null)
                                        {
                                            //
                                            // NOTE: It was a match; however, was it an exact match?
                                            //
                                            if (pair.Key.Length == name.Length)
                                                //
                                                // NOTE: Preserve match, it may differ in case.
                                                //
                                                exactName = pair.Key;

                                            //
                                            // NOTE: Was it an exact match or did we match at least one
                                            //       character in a partial match?
                                            //
                                            if ((pair.Key.Length == name.Length) || (name.Length > 0))
                                                //
                                                // NOTE: Store the exact or partial match in the results
                                                //       dictionary.
                                                //
                                                list.Add(pair.Key);
                                        }
                                    }
                                }
                            }

                            //
                            // NOTE: If there was an exact match, just use it.
                            //
                            if (exactName != null)
                            {
                                //
                                // NOTE: No need to change the caller's variable,
                                //       it already contains the correct value.
                                //
                                if (PrivateGetIExecute(
                                        exactName, lookupFlags, ref token,
                                        ref execute, ref error) == ReturnCode.Ok)
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenIExecute : NotifyType.IExecute,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, execute, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count == 1)
                            {
                                //
                                // NOTE: Normal case, exactly one command matched.
                                //
                                if (PrivateGetIExecute(
                                        list[0], lookupFlags, ref token,
                                        ref execute, ref error) == ReturnCode.Ok)
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenIExecute : NotifyType.IExecute,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, list[0], execute, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count > 1)
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        "ambiguous", "execute", name, list,
                                        null, null) :
                                    (Result)"ambiguous execute";

                                ambiguous = true;
                            }
                            else
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        null, "execute", name, localExecutes.Keys,
                                        null, null) :
                                    (Result)"bad execute";
                            }
                        }
                        else
                        {
                            error = "no executes defined";
                        }
                    }
                    else
                    {
                        error = "invalid execute name";
                    }
                }
                else
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "{0}executes not available",
                            useHidden ? "hidden " : String.Empty) :
                        "executes not available";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode PrivateGetIExecute(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IExecute execute,
            ref Result error
            )
        {
            if (!HasIExecutes(ref error))
                return ReturnCode.Error;

            _Wrappers._Execute wrapper;

            if (!executes.TryGetValue(token, out wrapper))
            {
                error = "execute not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                execute = wrapper;
                name = EntityOps.GetName(execute as IIdentifier);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid execute wrapper";
                    return ReturnCode.Error;
                }

                execute = wrapper.execute;
                name = EntityOps.GetName(execute as IIdentifier);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetIExecute(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            if (!HasIExecutes(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid execute name";
                return ReturnCode.Error;
            }

            _Wrappers._Execute wrapper;

            if (!executes.TryGetValue(name, out wrapper))
            {
                error = "execute not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                execute = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid execute wrapper";
                    return ReturnCode.Error;
                }

                execute = wrapper.execute;

                //
                // WARNING: Cannot grab the token from the IExecute here
                //          because that interface does not inherit from
                //          IWrapperData.
                //
                token = EntityOps.GetToken(wrapper);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetIExecute(
            string name,
            LookupFlags lookupFlags,
            ref IExecute execute
            )
        {
            Result error = null;

            return GetIExecute(name, lookupFlags, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetIExecute(
            string name,
            LookupFlags lookupFlags,
            ref IExecute execute,
            ref Result error
            )
        {
            long token = 0;

            return GetIExecute(name, lookupFlags, ref token, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListIExecutes(
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListIExecutes(
                pattern, noCase, strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenIExecutes(
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListHiddenIExecutes(
                pattern, noCase, strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenIExecutes(
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasHiddenIExecutes(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        bool simple = NamespaceOps.ShouldUseSimpleMatching(
                            this, currentNamespace, pattern, false);

                        bool qualified = NamespaceOps.IsQualifiedName(pattern);

                        if ((code == ReturnCode.Ok) && simple)
                        {
                            code = NamespaceOps.MatchItems(
                                this, null, hiddenExecutes.Keys, pattern,
                                noCase, !qualified, qualified, false, ref list,
                                ref error);
                        }

                        if ((code == ReturnCode.Ok) && !simple)
                        {
                            code = NamespaceOps.MatchItems(
                                this, currentNamespace, hiddenExecutes.Keys, pattern,
                                noCase, !qualified, qualified, false, ref list,
                                ref error);
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = hiddenExecutes.ToList(
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveIExecute(
            string name,
            long token,
            IExecute execute,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid execute name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if (AreNamespacesEnabled() &&
                    RemoveImportFromNamespaces(name, ref result) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }

#if NATIVE && TCL
                if ((execute == null) ||
                    (DisposeTclBridges(IntPtr.Zero, execute, null, false, ref result) == ReturnCode.Ok))
#endif
                {
                    executes.Remove(name, token);

#if EXECUTE_CACHE
                    if (executeCache != null)
                        executeCache.Remove(name, false);
#endif

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.IExecute, NotifyFlags.Removed,
                        new ObjectTriplet(execute, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

#if NATIVE && TCL
                return ReturnCode.Error;
#endif
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating execute: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IObject
        public ReturnCode GetObject(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IObject @object,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetObject(
                        token, lookupFlags, ref name, ref @object,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid object token \"{0}\"",
                            token) :
                        "invalid object token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetObject(
            string name,
            LookupFlags lookupFlags,
            ref IObject @object
            )
        {
            CheckDisposed();

            Result error = null;

            return GetObject(name, lookupFlags, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetObject(
            string name,
            LookupFlags lookupFlags,
            ref IObject @object,
            ref Result error
            )
        {
            CheckDisposed();

            long token = 0;

            return GetObject(name, lookupFlags, ref token, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetObject(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IObject @object,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetObject(
                        name, lookupFlags, ref token, ref @object,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid object name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid object name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetObject(
            object value,
            LookupFlags lookupFlags,
            ref string name,
            ref long token,
            ref IObject @object,
            ref Result error
            )
        {
            CheckDisposed();

            return GetObject(
                value, lookupFlags, ObjectFlags.None, ObjectFlags.None,
                false, false, ref name, ref token, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddObject(
            string name,
            Type type,
            ObjectFlags flags,
            IClientData clientData,
            int referenceCount,
#if NATIVE && TCL
            string interpName,
#endif
#if DEBUGGER && DEBUGGER_ARGUMENTS
            ArgumentList executeArguments,
#endif
            object value,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            return AddObject(new _Objects.Default(new ObjectData(
                name, null, null, clientData, type, flags, referenceCount,
#if NATIVE && TCL
                interpName,
#endif
#if DEBUGGER && DEBUGGER_ARGUMENTS
                executeArguments,
#endif
                0), value, null), null, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddObject(
            IObject @object,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (@object == null)
                {
                    result = "invalid object";
                    return ReturnCode.Error;
                }

                if (@object.Name == null)
                {
                    result = "invalid object name";
                    return ReturnCode.Error;
                }

                if (!HasObjects(ref result))
                    return ReturnCode.Error;

                if (DoesObjectExist(@object.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": object already exists",
                        @object.Name);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers._Object objectWrapper = new _Wrappers._Object(id, @object);

                objects.Add(@object.Name, objectWrapper);
                token = EntityOps.GetToken(objectWrapper);
                EntityOps.SetToken(@object, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Object, NotifyFlags.Added,
                    new ObjectPair(@object, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveObject(
            long token,
            IClientData clientData,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            CheckDisposed();

            return RemoveObject(
                token, clientData, synchronous, true, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveObject(
            string name,
            IClientData clientData,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            CheckDisposed();

            return RemoveObject(
                name, clientData, synchronous, true, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string ObjectsToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (objects != null)
                    return objects.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TEST
        internal void SaveObjects(
            ref ObjectWrapperDictionary savedObjects
            )
        {
            savedObjects = objects;
            objects = null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void RestoreObjects(
            ref ObjectWrapperDictionary savedObjects
            )
        {
            objects = savedObjects;
            savedObjects = null;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetObject(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IObject @object,
            ref Result error
            )
        {
            if (!HasObjects(ref error))
                return ReturnCode.Error;

            _Wrappers._Object wrapper;

            if (!objects.TryGetValue(token, out wrapper))
            {
                error = "object not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @object = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((@object == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid object";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid object wrapper";
                    return ReturnCode.Error;
                }

                @object = wrapper.@object;
                name = EntityOps.GetName(@object);

                if ((@object == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid object";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetObject(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IObject @object,
            ref Result error
            )
        {
            if (!HasObjects(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid object name";
                return ReturnCode.Error;
            }

            _Wrappers._Object wrapper;

            if (!objects.TryGetValue(name, out wrapper))
            {
                error = "object not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @object = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((@object == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid object";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid object wrapper";
                    return ReturnCode.Error;
                }

                @object = wrapper.@object;
                token = EntityOps.GetToken(@object);

                if ((@object == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid object";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetObject(
            object value,
            LookupFlags lookupFlags,
            ObjectFlags hasFlags,
            ObjectFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            ref string name
            )
        {
            IObject @object = null;

            return GetObject(
                value, lookupFlags, hasFlags, notHasFlags, hasAll,
                notHasAll, ref name, ref @object);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetObject(
            object value,
            LookupFlags lookupFlags,
            ObjectFlags hasFlags,
            ObjectFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            ref string name,
            ref IObject @object
            )
        {
            Result error = null;

            return GetObject(
                value, lookupFlags, hasFlags, notHasFlags, hasAll,
                notHasAll, ref name, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetObject(
            object value,
            LookupFlags lookupFlags,
            ObjectFlags hasFlags,
            ObjectFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            ref string name,
            ref IObject @object,
            ref Result error
            )
        {
            long token = 0;

            return GetObject(
                value, lookupFlags, hasFlags, notHasFlags, hasAll, notHasAll,
                ref name, ref token, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetObject( /* FOR USE BY [sql] ONLY */
            object value,
            LookupFlags lookupFlags
            )
        {
            string name = null;

            return GetObject(value, lookupFlags, ref name);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetObject( /* FOR USE BY MarshalOps.WrapHandle ONLY */
            object value,
            LookupFlags lookupFlags,
            ref string name
            )
        {
            long token = 0;
            IObject @object = null;
            Result error = null;

            return GetObject(
                value, lookupFlags, ObjectFlags.None, ObjectFlags.None,
                false, false, ref name, ref token, ref @object, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetObject(
            object value,
            LookupFlags lookupFlags,
            ObjectFlags hasFlags,
            ObjectFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            ref string name,
            ref long token,
            ref IObject @object,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasObjects(ref error))
                {
                    if (objects.Count > 0)
                    {
                        foreach (KeyValuePair<string, _Wrappers._Object> pair in objects)
                        {
                            _Wrappers._Object wrapper = pair.Value;

                            if (wrapper == null)
                                continue;

                            if (Object.ReferenceEquals(wrapper.Value, value))
                            {
                                if (((hasFlags == ObjectFlags.None) ||
                                        FlagOps.HasFlags(wrapper.Flags, hasFlags, hasAll)) &&
                                    ((notHasFlags == ObjectFlags.None) ||
                                        !FlagOps.HasFlags(wrapper.Flags, notHasFlags, notHasAll)))
                                {
                                    name = pair.Key;

                                    if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
                                        @object = wrapper;
                                    else
                                        @object = wrapper.@object;

                                    token = EntityOps.GetToken(wrapper);

                                    if ((@object != null) ||
                                        !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                    {
                                        code = ReturnCode.Ok;
                                    }
                                    break;
                                }
                            }
                        }
                    }

                    if (code != ReturnCode.Ok)
                    {
                        //
                        // HACK: Prevent ToString method from throwing any
                        //       exceptions here (e.g. proxy).
                        //
                        try
                        {
                            if (!AppDomainOps.IsTransparentProxy(value))
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    String.Format(
                                        "invalid object value \"{0}\"",
                                        value) :
                                    "invalid object value";
                            }
                            else
                            {
                                error = "invalid object value";
                            }
                        }
                        catch (Exception e)
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "invalid object value: {0}",
                                    e) :
                                "invalid object value";
                        }
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddObject(
            string name,
            Type type,
            ObjectFlags flags,
            IClientData clientData,
            int referenceCount,
#if NATIVE && TCL
            string interpName,
#endif
#if DEBUGGER && DEBUGGER_ARGUMENTS
            ArgumentList executeArguments,
#endif
            object value,
            ref Result result
            )
        {
            long token = 0;

            return AddObject(
                name, type, flags, clientData, referenceCount,
#if NATIVE && TCL
                interpName,
#endif
#if DEBUGGER && DEBUGGER_ARGUMENTS
                executeArguments,
#endif
                value, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveObject(
            string name,
            long token,
            IObject @object,
            IClientData clientData,
            bool synchronous,
            bool alias,
            ref bool dispose,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid object name";
                return ReturnCode.Error;
            }

            string aliasName = GetObjectAliasName(@object, name);

            if (dispose)
            {
                if (@object != null)
                {
                    if (!FlagOps.HasFlags(@object.Flags, ObjectFlags.Locked, true))
                    {
#if NATIVE && TCL
                        //
                        // NOTE: Remove the Tcl command for this object, if it exists.
                        //
                        string bridgeName = FormatOps.TclBridgeName(
                            @object.InterpName, @object.Name);

                        if ((DoesTclBridgeExist(bridgeName) != ReturnCode.Ok) ||
                            (RemoveTclBridge(@object.InterpName, @object.Name,
                                    null, ref result) == ReturnCode.Ok))
#endif
                        {
                            if (@object.Value != null)
                            {
                                if (!Object.ReferenceEquals(@object.Value, this) &&
                                    !IsMasterOrSlaveInterpreter(@object.Value) &&
                                    !FlagOps.HasFlags(@object.Flags, ObjectFlags.NoDispose, true))
                                {
                                    GlobalState.PushActiveInterpreter(this);

                                    try
                                    {
                                        if (ObjectOps.TryDispose(@object.Value,
                                                ref dispose, ref result) == ReturnCode.Ok)
                                        {
#if NOTIFY
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.Object, NotifyFlags.Disposed,
                                                new ObjectTriplet(@object.Value, name, token), this,
                                                clientData, null, null, ref result);
#endif

                                            @object.Value = null;
                                            @object = null;

                                            if (synchronous)
                                                ObjectOps.CollectGarbage(); /* throw */
                                        }
                                        else
                                        {
                                            return ReturnCode.Error;
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        result = String.Format(
                                            "caught exception while disposing object: {0}",
                                            e);

                                        return ReturnCode.Error;
                                    }
                                    finally
                                    {
                                        /* IGNORED */
                                        GlobalState.PopActiveInterpreter();
                                    }
                                }
                                else
                                {
                                    //
                                    // NOTE: We did not dispose the object because
                                    //       it was prohibited.
                                    //
                                    dispose = false;
                                }
                            }
                            else
                            {
                                //
                                // NOTE: We did not dispose the object because
                                //       it was invalid.
                                //
                                dispose = false;
                            }
                        }
#if NATIVE && TCL
                        else
                        {
                            //
                            // NOTE: Failed to remove the Tcl bridge.
                            //
                            return ReturnCode.Error;
                        }
#endif
                    }
                    else
                    {
                        result = "cannot dispose or remove a locked object";

                        return ReturnCode.Error;
                    }
                }
                else
                {
                    //
                    // NOTE: We did not dispose the object because the wrapper
                    //       was invalid.
                    //
                    dispose = false;
                }
            }

            //
            // NOTE: Remove the command alias for this object, if it exists.
            //       We cannot use the token here because it is the object
            //       token, not the command (alias) token.
            //
            if (alias && (DoesAliasExist(aliasName) == ReturnCode.Ok) &&
                (RemoveAliasAndCommand(aliasName, clientData, false, ref result) != ReturnCode.Ok))
            {
                return ReturnCode.Error;
            }

            objects.Remove(name, token);

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Object, NotifyFlags.Removed,
                new ObjectTriplet(@object, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveObject(
            long token,
            IClientData clientData,
            bool synchronous,
            ref Result result
            )
        {
            bool dispose = true;

            return RemoveObject(token, clientData, synchronous, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObject(
            string name,
            IClientData clientData,
            bool synchronous,
            ref Result result
            )
        {
            bool dispose = true;

            return RemoveObject(name, clientData, synchronous, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveObject(
            long token,
            IClientData clientData,
            bool synchronous,
            bool alias,
            ref Result result
            )
        {
            bool dispose = true;

            return RemoveObject(token, clientData, synchronous, alias, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveObject(
            long token,
            IClientData clientData,
            bool synchronous,
            bool alias,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasObjects(ref result))
                {
                    string name = null;
                    IObject @object = null;

                    if (GetObject(token, LookupFlags.Remove, ref name,
                            ref @object, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveObject(
                            name, token, @object, clientData, synchronous,
                            alias, ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveObject(
            string name,
            IClientData clientData,
            bool synchronous,
            bool alias,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasObjects(ref result))
                {
                    long token = 0;
                    IObject @object = null;

                    if (GetObject(name, LookupFlags.Remove, ref token,
                            ref @object, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveObject(
                            name, token, @object, clientData, synchronous,
                            alias, ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjects(
            IClientData clientData,
            bool stopOnError,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasObjects(ref result))
                {
                    StringList keys = new StringList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the objects collection in the containing interpreter.
                    //
                    foreach (KeyValuePair<string, _Wrappers._Object> pair in objects)
                        if (pair.Value != null)
                            if (pair.Value.ReferenceCount == 0)
                                if (!FlagOps.HasFlags(pair.Value.Flags, ObjectFlags.Locked, true))
                                    keys.Add(pair.Key);

                    int disposed = 0;

                    //
                    // NOTE: Cleanup, PASS #2, dispose and remove all the objects we found
                    //       from PASS #1 (above).
                    //
                    foreach (string key in keys)
                    {
                        bool localDispose = dispose;

                        if ((RemoveObject(key, clientData, synchronous,
                                ref localDispose, ref result) != ReturnCode.Ok) && stopOnError)
                        {
                            return ReturnCode.Error;
                        }

                        //
                        // NOTE: At least one object has been disposed.
                        //
                        if (localDispose)
                            disposed++;
                    }

                    //
                    // NOTE: Inform the caller if any of the objects were disposed.
                    //
                    dispose = (disposed > 0);

                    //
                    // NOTE: Return the number of objects we disposed and removed.
                    //
                    result = StringList.MakeList(
                        "disposed", disposed, "removed", keys.Count);

                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPackage
        public ReturnCode GetPackage(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPackage package,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPackage(
                        token, lookupFlags, ref name, ref package,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid package token \"{0}\"",
                            token) :
                        "invalid package token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetPackage(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPackage package,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPackage(
                        name, lookupFlags, ref token, ref package,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid package name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid package name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddPackage(
            IPackage package,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (package == null)
                {
                    result = "invalid package";
                    return ReturnCode.Error;
                }

                if (package.Name == null)
                {
                    result = "invalid package name";
                    return ReturnCode.Error;
                }

                if (!HasPackages(ref result))
                    return ReturnCode.Error;

                if (DoesPackageExist(package.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": package already exists",
                        package.Name);

                    return ReturnCode.Error;
                }

                ReturnCode code = ReturnCode.Ok;

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    try
                    {
                        code = package.Initialize(this,
                            (clientData != null) ? clientData : package.ClientData,
                            ref result);
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while initializing package: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        bool savedImmutable = BeginMutableExecution();

                        ReturnCode terminateCode;
                        Result terminateResult = null;

                        try
                        {
                            terminateCode = package.Terminate(this,
                                (clientData != null) ? clientData : package.ClientData,
                                ref terminateResult);
                        }
                        catch (Exception e)
                        {
                            terminateResult = String.Format(
                                "caught exception while terminating package: {0}",
                                e);

                            terminateCode = ReturnCode.Error;
                        }
                        finally
                        {
                            EndMutableExecution(savedImmutable);
                        }

                        if (terminateCode != ReturnCode.Ok)
                            DebugOps.Complain(this, terminateCode, terminateResult);
                    }
                }

                if (code != ReturnCode.Ok)
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                    return code;
                }

                long id = NextId();
                _Wrappers.Package packageWrapper = new _Wrappers.Package(id, package);

                packages.Add(package.Name, packageWrapper);
                token = EntityOps.GetToken(packageWrapper);
                EntityOps.SetToken(package, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Package, NotifyFlags.Added,
                    new ObjectPair(package, token), this,
                    clientData, null, null, ref result);
#endif

                /* IGNORED */
                GlobalState.PopActiveInterpreter();
                return code;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePackage(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPackages(ref result))
                {
                    string name = null;
                    IPackage package = null;

                    if (GetPackage(token, LookupFlags.Remove, ref name,
                            ref package, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemovePackage(
                            name, token, package, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePackage(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPackages(ref result))
                {
                    long token = 0;
                    IPackage package = null;

                    if (GetPackage(name, LookupFlags.Remove, ref token,
                            ref package, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemovePackage(
                            name, token, package, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode PrivateGetPackage(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPackage package,
            ref Result error
            )
        {
            if (!HasPackages(ref error))
                return ReturnCode.Error;

            _Wrappers.Package wrapper;

            if (!packages.TryGetValue(token, out wrapper))
            {
                error = "package not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                package = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((package == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid package";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid package wrapper";
                    return ReturnCode.Error;
                }

                package = wrapper.package;
                name = EntityOps.GetName(package);

                if ((package == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid package";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetPackage(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPackage package,
            ref Result error
            )
        {
            if (!HasPackages(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid package name";
                return ReturnCode.Error;
            }

            _Wrappers.Package wrapper;

            if (!packages.TryGetValue(name, out wrapper))
            {
                error = "package not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                package = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((package == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid package";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid package wrapper";
                    return ReturnCode.Error;
                }

                package = wrapper.package;
                token = EntityOps.GetToken(package);

                if ((package == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid package";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetPackage(
            string name,
            LookupFlags lookupFlags,
            ref IPackage package
            )
        {
            Result error = null;

            return GetPackage(name, lookupFlags, ref package, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetPackage(
            string name,
            LookupFlags lookupFlags,
            ref IPackage package,
            ref Result error
            )
        {
            long token = 0;

            return GetPackage(name, lookupFlags, ref token, ref package, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddPackage(
            IPackage package,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddPackage(package, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemovePackage(
            string name,
            long token,
            IPackage package,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid package name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if ((package == null) ||
                    (package.Terminate(this, (clientData != null) ?
                            clientData : package.ClientData, ref result) == ReturnCode.Ok))
                {
                    packages.Remove(name, token);

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Package, NotifyFlags.Removed,
                        new ObjectTriplet(package, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

                return ReturnCode.Error;
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating package: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPlugin
        public ReturnCode GetPlugin(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPlugin plugin,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPlugin(
                        token, lookupFlags, ref name, ref plugin,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid plugin token \"{0}\"",
                            token) :
                        "invalid plugin token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetPlugin(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPlugin plugin,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPlugin(
                        name, lookupFlags, ref token, ref plugin,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid plugin name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid plugin name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetPlugin(
            Assembly assembly,
            LookupFlags lookupFlags,
            ref string name,
            ref long token,
            ref IPlugin plugin,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasPlugins(ref error))
                {
                    if (plugins.Count > 0)
                    {
                        foreach (KeyValuePair<string, _Wrappers.Plugin> pair in plugins)
                        {
                            _Wrappers.Plugin wrapper = pair.Value;

                            if (wrapper == null)
                                continue;

                            if (Object.ReferenceEquals(wrapper.Assembly, assembly))
                            {
                                name = pair.Key;

                                if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
                                    plugin = wrapper;
                                else
                                    plugin = wrapper.plugin;

                                token = EntityOps.GetToken(wrapper);

                                if ((plugin != null) ||
                                    !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                {
                                    code = ReturnCode.Ok;
                                }
                                break;
                            }
                        }
                    }

                    if (code != ReturnCode.Ok)
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            String.Format(
                                "invalid plugin assembly \"{0}\"",
                                FormatOps.AssemblyName(assembly, 0)) :
                            "invalid plugin assembly";
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MatchPlugin(
            string name,
            LookupFlags lookupFlags,
            ref IPlugin plugin,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasPlugins(ref error))
                {
                    if (plugins.Count > 0)
                    {
                        foreach (KeyValuePair<string, _Wrappers.Plugin> pair in plugins)
                        {
                            if (pair.Value != null)
                            {
                                if (StringOps.Match(this, MatchMode.Glob, pair.Key, name, false))
                                {
                                    if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
                                        plugin = pair.Value;
                                    else
                                        plugin = pair.Value.plugin;

                                    if ((plugin != null) ||
                                        !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                    {
                                        code = ReturnCode.Ok;
                                    }
                                    break;
                                }
                            }
                        }
                    }

                    if (code != ReturnCode.Ok)
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            String.Format(
                                "invalid plugin name \"{0}\"",
                                FormatOps.DisplayName(name)) :
                            "invalid plugin name";
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddPlugin(
            IPlugin plugin,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (plugin == null)
                {
                    result = "invalid plugin";
                    return ReturnCode.Error;
                }

                if (plugin.Name == null)
                {
                    result = "invalid plugin name";
                    return ReturnCode.Error;
                }

                if (!HasPlugins(ref result))
                    return ReturnCode.Error;

                if (DoesPluginExist(plugin.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": plugin already exists",
                        plugin.Name);

                    return ReturnCode.Error;
                }

                ReturnCode code = ReturnCode.Ok;

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    try
                    {
                        IClientData addClientData;

                        GetClientDataForAddPlugin(
                            plugin, clientData, out addClientData);

                        code = plugin.Initialize(
                            this, addClientData, ref result);
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while initializing plugin: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        bool savedImmutable = BeginMutableExecution();

                        ReturnCode terminateCode;
                        Result terminateResult = null;

                        try
                        {
                            terminateCode = plugin.Terminate(this,
                                (clientData != null) ? clientData : plugin.ClientData,
                                ref terminateResult);
                        }
                        catch (Exception e)
                        {
                            terminateResult = String.Format(
                                "caught exception while terminating plugin: {0}",
                                e);

                            terminateCode = ReturnCode.Error;
                        }
                        finally
                        {
                            EndMutableExecution(savedImmutable);
                        }

                        if (terminateCode != ReturnCode.Ok)
                            DebugOps.Complain(this, terminateCode, terminateResult);
                    }
                }

                if (code != ReturnCode.Ok)
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                    return code;
                }

                long id = NextId();
                _Wrappers.Plugin pluginWrapper = new _Wrappers.Plugin(id, plugin);

                plugins.Add(plugin.Name, pluginWrapper);
                token = EntityOps.GetToken(pluginWrapper);
                EntityOps.SetToken(plugin, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Plugin, NotifyFlags.Added,
                    new ObjectPair(plugin, token), this,
                    clientData, null, null, ref result);
#endif

                /* IGNORED */
                GlobalState.PopActiveInterpreter();
                return code;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePlugin(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPlugins(ref result))
                {
                    string name = null;
                    IPlugin plugin = null;

                    if (GetPlugin(token, LookupFlags.Remove, ref name,
                            ref plugin, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemovePlugin(
                            name, token, plugin, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePlugin(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPlugins(ref result))
                {
                    long token = 0;
                    IPlugin plugin = null;

                    if (GetPlugin(name, LookupFlags.Remove, ref token,
                            ref plugin, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemovePlugin(
                            name, token, plugin, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private void GetClientDataForAddPlugin(
            IPlugin plugin,
            IClientData oldClientData,
            out IClientData newClientData
            )
        {
            if (plugin != null)
            {
                StringList arguments = null;

                if (GetPluginArguments(plugin.Name, false, ref arguments))
                {
                    //
                    // NOTE: There are plugin arguments to pass.  Now, check
                    //       if there is more client data available as well.
                    //
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetClientDataForAddPlugin: interpreter = {1}, " +
                        "plugin = {2}, oldClientData = {3}, arguments = {4}{5}",
                        GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(this),
                        FormatOps.WrapOrNull(plugin), FormatOps.WrapOrNull(true, true,
                        oldClientData), FormatOps.WrapOrNull(true, true, arguments),
                        Environment.NewLine), typeof(Interpreter).Name);

                    newClientData = ClientData.WrapOrReplace(
                        (oldClientData != null) ? oldClientData :
                        plugin.ClientData, (arguments != null) ?
                        arguments.ToString() : null);
                }
                else if (oldClientData != null)
                {
                    //
                    // NOTE: There are no plugin arguments; however, there is
                    //       some client data provided by the caller.
                    //
                    newClientData = oldClientData;
                }
                else
                {
                    //
                    // NOTE: There are no plugin arguments.  There is also no
                    //       client data provided by the caller; therefore,
                    //       use the client data associated with this plugin
                    //       context (which may be null).
                    //
                    newClientData = plugin.ClientData;
                }
            }
            else
            {
                //
                // NOTE: We have no plugin context, there is no other
                //       option.
                //
                newClientData = oldClientData;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool GetPluginArguments(
            string name,
            bool strict,
            ref StringList arguments
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (String.IsNullOrEmpty(name))
                    return false;

                if (pluginArguments != null)
                {
                    int count = 0;
                    string localValue;

                    if (pluginArguments.TryGetValue(name, out localValue))
                    {
                        if (arguments == null)
                            arguments = new StringList();

                        arguments.Add(localValue);
                        count++;
                    }

                    if (!strict)
                    {
                        foreach (KeyValuePair<string, string> pair in pluginArguments)
                        {
                            if (StringOps.Match(
                                    this, MatchMode.Glob, name, pair.Key, false))
                            {
                                if (arguments == null)
                                    arguments = new StringList();

                                arguments.Add(pair.Value);
                                count++;
                            }
                        }
                    }

                    return (count > 0);
                }

                return false;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool AddPluginArguments(
            string name,
            string value,
            bool strict
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true))
                    return false;

                if (String.IsNullOrEmpty(name))
                    return false;

                if (pluginArguments != null)
                {
                    if (strict)
                    {
                        if (!pluginArguments.ContainsKey(name)) /* EXEMPT */
                        {
                            pluginArguments.Add(name, value);
                            return true;
                        }
                    }
                    else
                    {
                        pluginArguments[name] = value;
                        return true;
                    }
                }

                return false;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool RemovePluginArguments(
            string name,
            bool strict
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false))
                    return false;

                if (String.IsNullOrEmpty(name))
                    return false;

                if (pluginArguments != null)
                {
                    if (strict)
                    {
                        if (pluginArguments.ContainsKey(name)) /* EXEMPT */
                            return pluginArguments.Remove(name);
                    }
                    else
                    {
                        return pluginArguments.Remove(name);
                    }
                }

                return false;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string PluginsToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (plugins != null)
                    return plugins.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList CopyPluginKeys()
        {
            lock (syncRoot)
            {
                if (plugins != null)
                    return new StringList(plugins.Keys);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal PluginWrapperDictionary CopyPlugins()
        {
            lock (syncRoot)
            {
                if (plugins != null)
                    return new PluginWrapperDictionary(plugins);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetPlugin(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPlugin plugin,
            ref Result error
            )
        {
            if (!HasPlugins(ref error))
                return ReturnCode.Error;

            _Wrappers.Plugin wrapper;

            if (!plugins.TryGetValue(token, out wrapper))
            {
                error = "plugin not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                plugin = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((plugin == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid plugin";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid plugin wrapper";
                    return ReturnCode.Error;
                }

                plugin = wrapper.plugin;
                name = EntityOps.GetName(plugin);

                if ((plugin == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid plugin";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetPlugin(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPlugin plugin,
            ref Result error
            )
        {
            if (!HasPlugins(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid plugin name";
                return ReturnCode.Error;
            }

            _Wrappers.Plugin wrapper;

            if (!plugins.TryGetValue(name, out wrapper))
            {
                error = "plugin not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                plugin = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((plugin == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid plugin";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid plugin wrapper";
                    return ReturnCode.Error;
                }

                plugin = wrapper.plugin;
                token = EntityOps.GetToken(plugin);

                if ((plugin == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid plugin";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the [unload] command only.
        //
        internal IPlugin GetPlugin(
            string name
            )
        {
            if (name != null)
            {
                lock (syncRoot)
                {
                    if (plugins != null)
                    {
                        _Wrappers.Plugin plugin;

                        if (plugins.TryGetValue(name, out plugin))
                            return plugin;
                    }
                }
            }

            return null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetPlugin(
            long token,
            LookupFlags lookupFlags,
            ref IPlugin plugin,
            ref Result error
            )
        {
            string name = null;

            return GetPlugin(token, lookupFlags, ref name, ref plugin, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetPlugin(
            string name,
            LookupFlags lookupFlags,
            ref IPlugin plugin,
            ref Result error
            )
        {
            long token = 0;

            return GetPlugin(name, lookupFlags, ref token, ref plugin, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemovePlugin(
            string name,
            long token,
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid plugin name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if ((plugin == null) ||
                    (plugin.Terminate(this, (clientData != null) ?
                            clientData : plugin.ClientData, ref result) == ReturnCode.Ok))
                {
                    plugins.Remove(name, token);

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Plugin, NotifyFlags.Removed,
                        new ObjectTriplet(plugin, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

                return ReturnCode.Error;
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating plugin: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICommand
        public ReturnCode GetCommand(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ICommand command,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetCommand(
                        token, lookupFlags, ref name, ref command,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid command token \"{0}\"",
                            token) :
                        "invalid command token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetCommand(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetCommand(
                        name, lookupFlags, ref token, ref command,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid command name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid command name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ListCommands(
            CommandFlags hasFlags,
            CommandFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasCommands(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        if (code == ReturnCode.Ok)
                        {
                            StringList localList = null;

                            code = commands.ToList(
                                hasFlags, notHasFlags, hasAll, notHasAll,
                                null, false, ref localList, ref error);

                            bool simple = NamespaceOps.ShouldUseSimpleMatching(
                                this, currentNamespace, pattern, false);

                            bool qualified = NamespaceOps.IsQualifiedName(pattern);

                            if ((code == ReturnCode.Ok) && simple)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, null, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }

                            if ((code == ReturnCode.Ok) && !simple)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, currentNamespace, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = commands.ToList(
                            hasFlags, notHasFlags, hasAll, notHasAll,
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddExecuteCallback(
            string name,
            ExecuteCallback callback,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            //
            // NOTE: Synthesize a command out of the clear blue sky and
            //       populate it with the callback supplied by the user.  We do
            //       not bother checking if the supplied callback is valid
            //       because we do not actually care.  The worst case is that
            //       the engine will call the Execute method of the default
            //       command created here, which does nothing.
            //
            ICommand command = new _Commands.Default(
                new CommandData(name, null, null, clientData,
                    typeof(_Commands.Default).FullName,
                    CommandFlags.None, null, 0));

            command.Callback = callback;

            return AddCommand(command, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddCommand(
            ICommand command,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (command == null)
                {
                    result = "invalid command";
                    return ReturnCode.Error;
                }

                if (command.Name == null)
                {
                    result = "invalid command name";
                    return ReturnCode.Error;
                }

                if (!HasCommands(ref result))
                    return ReturnCode.Error;

                //
                // WARNING: Currently, if somebody adds an ICommand that shadows an
                //          IExecute or procedure (by name), it will basically be
                //          ignored in favor of the IExecute or procedure, which
                //          have higher priority.  This behavior could be prevented
                //          here by changing this check to be DoesAnyExecuteExist
                //          instead of DoesCommandExist; however, I am not convinced
                //          that task should be the responsibility of this method
                //          (i.e. why should a method that deals with commands need
                //          to know about IExecute or procedure objects?).  The spirit
                //          of this check is basically "can we physically add the
                //          object in question?".
                //
                if (DoesCommandExist(command.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": command already exists",
                        command.Name);

                    return ReturnCode.Error;
                }

                Result localError = null;

                if (AreNamespacesEnabled() && (NamespaceOps.LookupParent(
                        this, command.Name, false, true, true, ref localError) == null))
                {
                    result = String.Format(
                        "can't add command \"{0}\": {1}",
                        command.Name, localError);

                    return ReturnCode.Error;
                }

                ReturnCode code = ReturnCode.Ok;

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    try
                    {
                        code = command.Initialize(this,
                            (clientData != null) ? clientData : command.ClientData,
                            ref result);
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while initializing command: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        bool savedImmutable = BeginMutableExecution();

                        ReturnCode terminateCode;
                        Result terminateResult = null;

                        try
                        {
                            terminateCode = command.Terminate(this,
                                (clientData != null) ? clientData : command.ClientData,
                                ref terminateResult);
                        }
                        catch (Exception e)
                        {
                            terminateResult = String.Format(
                                "caught exception while terminating command: {0}",
                                e);

                            terminateCode = ReturnCode.Error;
                        }
                        finally
                        {
                            EndMutableExecution(savedImmutable);
                        }

                        if (terminateCode != ReturnCode.Ok)
                            DebugOps.Complain(this, terminateCode, terminateResult);
                    }
                }

                if (code != ReturnCode.Ok)
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                    return code;
                }

                long id = NextId();
                _Wrappers.Command commandWrapper = new _Wrappers.Command(id, command);
                long newToken = EntityOps.GetToken(commandWrapper);

                //
                // NOTE: Are we allowed to assist in managing the command
                //       token via the associated plugin?
                //
                if (!EntityOps.IsNoToken(command))
                {
                    //
                    // NOTE: Store the command token so that we can remove
                    //       them later without using their names (which
                    //       can change).
                    //
                    IPlugin plugin = command.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.CommandTokens;

                        if ((tokens != null) && !tokens.Contains(newToken))
                        {
                            tokens.Add(newToken);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the command tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.CommandTokens = tokens;
#endif
                        }
                    }
                }

                EntityOps.SetToken(command, newToken);
                commands.Add(command.Name, commandWrapper);
                token = newToken;

#if EXECUTE_CACHE
                if (executeCache != null)
                    executeCache.AddOrUpdate(command.Name, commandWrapper, false);
#endif

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Command, NotifyFlags.Added,
                    new ObjectPair(command, token), this,
                    clientData, null, null, ref result);
#endif

                /* IGNORED */
                GlobalState.PopActiveInterpreter();
                return code;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RenameCommand(
            string oldName,
            string newName,
            bool delete,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasCommands(ref result))
                {
                    if (!delete || !String.IsNullOrEmpty(newName))
                    {
                        ICommand oldCommand = null;

                        if (GetCommand(oldName, LookupFlags.Default, ref oldCommand, ref result) == ReturnCode.Ok)
                        {
                            if (!EntityOps.IsReadOnly(oldCommand))
                            {
                                _Wrappers.Command oldWrapper = oldCommand as _Wrappers.Command;

                                if (oldWrapper != null)
                                {
                                    IAlias oldAlias = oldWrapper.command as IAlias;

                                    if (PreventAliasLoop(oldAlias, newName, ref result) == ReturnCode.Ok)
                                    {
                                        if (IsValidCommandName(newName, ref result) == ReturnCode.Ok)
                                        {
                                            if (!AreNamespacesEnabled() ||
                                                RenameImportInNamespaces(oldName, newName, ref result) == ReturnCode.Ok)
                                            {
                                                //
                                                // NOTE: New name, same token.
                                                //
                                                oldWrapper.Name = newName;

                                                /* IGNORED */
                                                commands.Rename(oldName, newName);

#if EXECUTE_CACHE
                                                if (executeCache != null)
                                                    executeCache.Rename(oldName, newName, oldWrapper, false);
#endif

#if NOTIFY
                                                /* IGNORED */
                                                CheckNotifications(
                                                    NotifyType.Command, NotifyFlags.Renamed,
                                                    new ObjectTriplet(oldCommand, oldName, newName), this,
                                                    null, null, null, ref result);
#endif

                                                result = String.Empty;
                                                return ReturnCode.Ok;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    result = String.Format(
                                        "can't rename \"{0}\": invalid command wrapper",
                                        oldName);
                                }
                            }
                            else
                            {
                                result = String.Format(
                                    "can't rename \"{0}\": command is read-only",
                                    oldName);
                            }
                        }
                        else
                        {
                            result = String.Format(
                                "can't rename \"{0}\": command doesn't exist",
                                oldName);
                        }
                    }
                    else
                    {
                        return RemoveCommand(oldName, null, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveCommand(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasCommands(ref result))
                {
                    string name = null;
                    ICommand command = null;

                    if (GetCommand(token, LookupFlags.Remove, ref name,
                            ref command, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(command))
                        {
                            return PrivateRemoveCommand(
                                name, token, command, clientData, ref result);
                        }
                        else
                        {
                            result = "command is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveCommand(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasCommands(ref result))
                {
                    long token = 0;
                    ICommand command = null;

                    if (GetCommand(name, LookupFlags.Remove, ref token,
                            ref command, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(command))
                        {
                            return PrivateRemoveCommand(
                                name, token, command, clientData, ref result);
                        }
                        else
                        {
                            result = "command is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MatchCommand(
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                bool useHidden = Engine.HasUseHidden(engineFlags);
                bool matchHidden = Engine.HasMatchHidden(engineFlags);

                CommandWrapperDictionary localCommands =
                    useHidden ? hiddenCommands : commands;

                if (localCommands != null)
                {
                    //
                    // NOTE: *WARNING* Empty command/procedure names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (localCommands.Count > 0)
                        {
                            _Wrappers.Command localCommand;
                            string exactName = null;
                            StringList list = new StringList();

                            if (localCommands.TryGetValue(name, out localCommand) &&
                                (matchHidden || !EntityOps.IsHidden(localCommand)))
                            {
                                //
                                // NOTE: Exact command match.
                                //
                                exactName = name;

                                //
                                // NOTE: Store the exact command match in the result
                                //       list.
                                //
                                list.Add(name);
                            }
                            else
                            {
                                foreach (KeyValuePair<string, _Wrappers.Command> pair in localCommands)
                                {
                                    if (String.Compare(
                                            pair.Key, 0, name, 0, name.Length,
                                            StringOps.SystemStringComparisonType) == 0)
                                    {
                                        //
                                        // NOTE: Is the command visible or are we allowed to
                                        //       find hidden command?
                                        //
                                        if (matchHidden || !EntityOps.IsHidden(pair.Value))
                                        {
                                            //
                                            // NOTE: Was the key valid (this should always succeed).
                                            //
                                            if (pair.Key != null)
                                            {
                                                //
                                                // NOTE: It was a match; however, was it an exact match?
                                                //
                                                if (pair.Key.Length == name.Length)
                                                    //
                                                    // NOTE: Preserve match, it may differ in case.
                                                    //
                                                    exactName = pair.Key;

                                                //
                                                // NOTE: Was it an exact match or did we match at least one
                                                //       character in a partial match?
                                                //
                                                if ((pair.Key.Length == name.Length) || (name.Length > 0))
                                                    //
                                                    // NOTE: Store the exact or partial match in the results
                                                    //       dictionary.
                                                    //
                                                    list.Add(pair.Key);
                                            }
                                        }
                                    }
                                }
                            }

                            //
                            // NOTE: If there was an exact match, just use it.
                            //
                            if (exactName != null)
                            {
                                //
                                // NOTE: No need to change the caller's variable,
                                //       it already contains the correct value.
                                //
                                if ((useHidden && PrivateGetHiddenCommand(
                                        exactName, lookupFlags, ref token,
                                        ref command, ref error) == ReturnCode.Ok) ||
                                    (!useHidden && PrivateGetCommand(
                                        exactName, lookupFlags, ref token,
                                        ref command, ref error) == ReturnCode.Ok))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenCommand : NotifyType.Command,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, command, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count == 1)
                            {
                                //
                                // NOTE: Normal case, exactly one command matched.
                                //
                                if ((useHidden && PrivateGetHiddenCommand(
                                        list[0], lookupFlags, ref token,
                                        ref command, ref error) == ReturnCode.Ok) ||
                                    (!useHidden && PrivateGetCommand(
                                        list[0], lookupFlags, ref token,
                                        ref command, ref error) == ReturnCode.Ok))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenCommand : NotifyType.Command,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, list[0], command, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count > 1)
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        "ambiguous", "command", name, list,
                                        null, null) :
                                    (Result)"ambiguous command";

                                ambiguous = true;
                            }
                            else
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        null, "command", name, localCommands.Keys,
                                        null, null) :
                                    (Result)"bad command";
                            }
                        }
                        else
                        {
                            error = "no commands defined";
                        }
                    }
                    else
                    {
                        error = "invalid command name";
                    }
                }
                else
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "{0}commands not available",
                            useHidden ? "hidden " : String.Empty) :
                        "commands not available";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ReturnCode ListEnsembleCommands(
            string pattern,
            bool noCase,
            ref StringList list,
            ref Result error
            )
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                if (commands != null)
                {
                    StringList localList = new StringList();

                    foreach (KeyValuePair<string, _Wrappers.Command> pair in commands)
                    {
                        ICommand command = pair.Value;

                        if (command == null)
                            continue;

                        EnsembleDictionary subCommands = command.SubCommands;

                        if ((subCommands != null) && (subCommands.Count > 0))
                            localList.Add(pair.Key);
                    }

                    bool absolute = false;

                    pattern = NamespaceOps.TrimLeading(pattern, ref absolute);

                    if (absolute || !AreNamespacesEnabled())
                    {
                        if (pattern == null)
                        {
                            list = localList;
                        }
                        else
                        {
                            if (list == null)
                                list = new StringList();

                            foreach (string element in localList)
                            {
                                if (StringOps.Match(
                                        this, MatchMode.Glob, element,
                                        pattern, noCase))
                                {
                                    list.Add(element);
                                }
                            }
                        }

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        bool qualified = NamespaceOps.IsQualifiedName(pattern);

                        return NamespaceOps.MatchItems(
                            this, null, localList, pattern,
                            noCase, !qualified, qualified, false, ref list,
                            ref error);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int SetCommandsReadOnly(
            string pattern,
            bool noCase,
            bool readOnly
            )
        {
            int result = 0;

            lock (syncRoot)
            {
                if (commands != null)
                {
                    foreach (KeyValuePair<string, _Wrappers.Command> pair in commands)
                    {
                        ICommand command = pair.Value;

                        if (command == null)
                            continue;

                        if ((pattern != null) && !StringOps.Match(
                                this, StringOps.DefaultMatchMode, pair.Key,
                                pattern, noCase))
                        {
                            continue;
                        }

                        if (EntityOps.SetReadOnly(command, readOnly))
                            result++;
                    }
                }
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetCommand(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ICommand command,
            ref Result error
            )
        {
            if (!HasCommands(ref error))
                return ReturnCode.Error;

            _Wrappers.Command wrapper;

            if (!commands.TryGetValue(token, out wrapper))
            {
                error = "command not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                command = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid command wrapper";
                    return ReturnCode.Error;
                }

                command = wrapper.command;
                name = EntityOps.GetName(command);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetCommand(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            if (!HasCommands(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid command name";
                return ReturnCode.Error;
            }

            _Wrappers.Command wrapper;

            if (!commands.TryGetValue(name, out wrapper))
            {
                error = "command not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                command = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid command wrapper";
                    return ReturnCode.Error;
                }

                command = wrapper.command;
                token = EntityOps.GetToken(command);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCommand(
            long token,
            LookupFlags lookupFlags,
            ref ICommand command
            )
        {
            Result error = null;

            return GetCommand(token, lookupFlags, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetCommand(
            long token,
            LookupFlags lookupFlags,
            ref ICommand command,
            ref Result error
            )
        {
            string name = null;

            return GetCommand(token, lookupFlags, ref name, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCommand(
            string name,
            LookupFlags lookupFlags,
            ref ICommand command
            )
        {
            Result error = null;

            return GetCommand(name, lookupFlags, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCommand(
            string name,
            LookupFlags lookupFlags,
            ref ICommand command,
            ref Result error
            )
        {
            long token = 0;

            return GetCommand(name, lookupFlags, ref token, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCommand(
            Type type,
            LookupFlags lookupFlags,
            ref ICommand command
            )
        {
            Result error = null;

            return GetCommand(type, lookupFlags, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCommand(
            Type type,
            LookupFlags lookupFlags,
            ref ICommand command,
            ref Result error
            )
        {
            string name = null;

            return GetCommand(type, lookupFlags, ref name, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetCommand(
            Type type,
            LookupFlags lookupFlags,
            ref string name,
            ref ICommand command,
            ref Result error
            )
        {
            long token = 0;

            return GetCommand(type, lookupFlags, ref name, ref token, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetCommand(
            Type type,
            LookupFlags lookupFlags,
            ref string name,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                if (HasCommands(ref error))
                {
                    if ((commands.Count > 0) && (type != null))
                    {
                        foreach (KeyValuePair<string, _Wrappers.Command> pair in commands)
                        {
                            _Wrappers.Command wrapper = pair.Value;

                            if (wrapper == null)
                                continue;

                            if (type.IsInstanceOfType(wrapper.command))
                            {
                                name = pair.Key;

                                if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
                                    command = wrapper;
                                else
                                    command = wrapper.command;

                                token = EntityOps.GetToken(wrapper);

                                if ((command != null) ||
                                    !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                {
                                    code = ReturnCode.Ok;
                                }
                                break;
                            }
                        }

                        if ((code != ReturnCode.Ok) && HasHiddenCommands())
                        {
                            if ((hiddenCommands.Count > 0) && (type != null))
                            {
                                foreach (KeyValuePair<string, _Wrappers.Command> pair in hiddenCommands)
                                {
                                    _Wrappers.Command wrapper = pair.Value;

                                    if (wrapper == null)
                                        continue;

                                    if (type.IsInstanceOfType(wrapper.command))
                                    {
                                        name = pair.Key;

                                        if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
                                            command = wrapper;
                                        else
                                            command = wrapper.command;

                                        token = EntityOps.GetToken(wrapper);

                                        if ((command != null) ||
                                            !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                        {
                                            code = ReturnCode.Ok;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (code != ReturnCode.Ok)
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            String.Format(
                                "invalid command type \"{0}\"",
                                FormatOps.TypeName(type)) :
                            "invalid command type";
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode IsValidCommandName(
            string newName,
            ref Result error
            )
        {
            IExecute execute = null;

            if (GetIExecute(
                    newName, LookupFlags.Exists, ref execute) == ReturnCode.Ok)
            {
                error = String.Format(
                    "can't rename to \"{0}\": execute already exists",
                    newName);

                return ReturnCode.Error;
            }

            IProcedure procedure = null;

            if (GetProcedure(
                    newName, LookupFlags.Exists, ref procedure) == ReturnCode.Ok)
            {
                error = String.Format(
                    "can't rename to \"{0}\": procedure already exists",
                    newName);

                return ReturnCode.Error;
            }

            ICommand command = null;

            if (GetCommand(
                    newName, LookupFlags.Exists, ref command) == ReturnCode.Ok)
            {
                error = String.Format(
                    "can't rename to \"{0}\": command already exists",
                    newName);

                return ReturnCode.Error;
            }

            Result localError = null;

            if (AreNamespacesEnabled() && (NamespaceOps.LookupParent(
                    this, newName, false, true, false, ref localError) == null))
            {
                error = String.Format(
                    "can't rename to \"{0}\": {1}",
                    newName, localError);

                return ReturnCode.Error;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RenameAnyIExecute(
            string oldName,
            string newName,
            string varName,
            IdentifierKind kind,
            bool delete,
            ref Result result
            )
        {
            // CheckDisposed();

            lock (syncRoot) /* TRANSACTIONAL */
            {
                bool useNamespaces = AreNamespacesEnabled();

                ///////////////////////////////////////////////////////////////////////////////////////

                if (!useNamespaces || (NamespaceOps.GetIExecuteName(
                        this, ref oldName, ref result) == ReturnCode.Ok))
                {
                    oldName = ScriptOps.MakeCommandName(oldName);
                }
                else
                {
                    return ReturnCode.Error;
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (!useNamespaces || (NamespaceOps.NormalizeName(
                        this, ref newName, ref result) == ReturnCode.Ok))
                {
                    newName = ScriptOps.MakeCommandName(newName);
                }
                else
                {
                    return ReturnCode.Error;
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                switch (kind)
                {
                    case IdentifierKind.None:
                        {
                            if (DoesIExecuteExist(oldName) == ReturnCode.Ok)
                            {
                                if (RenameIExecute(
                                        oldName, newName, delete,
                                        ref result) != ReturnCode.Ok)
                                {
                                    return ReturnCode.Error;
                                }
                            }
                            else if (DoesProcedureExist(oldName) == ReturnCode.Ok)
                            {
                                if (RenameProcedure(
                                        oldName, newName, delete,
                                        ref result) != ReturnCode.Ok)
                                {
                                    return ReturnCode.Error;
                                }
                            }
                            else
                            {
                                if (RenameCommand(
                                        oldName, newName, delete,
                                        ref result) != ReturnCode.Ok)
                                {
                                    return ReturnCode.Error;
                                }
                            }
                            break;
                        }
                    case IdentifierKind.Command:
                        {
                            if (RenameCommand(
                                    oldName, newName, delete,
                                    ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                            break;
                        }
                    case IdentifierKind.Procedure:
                        {
                            if (RenameProcedure(
                                    oldName, newName, delete,
                                    ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                            break;
                        }
                    case IdentifierKind.IExecute:
                        {
                            if (RenameIExecute(
                                    oldName, newName, delete,
                                    ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                            break;
                        }
                    default:
                        {
                            result = "identifier kind not supported";
                            return ReturnCode.Error;
                        }
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (varName != null)
                {
                    if (SetVariableValue(
                            VariableFlags.None, varName, newName,
                            ref result) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListCommands(
            CommandFlags hasFlags,
            CommandFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListCommands(
                hasFlags, notHasFlags, hasAll, notHasAll, pattern, noCase,
                strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenCommands(
            CommandFlags hasFlags,
            CommandFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListHiddenCommands(
                hasFlags, notHasFlags, hasAll, notHasAll, pattern, noCase,
                strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenCommands(
            CommandFlags hasFlags,
            CommandFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasHiddenCommands(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        if (code == ReturnCode.Ok)
                        {
                            StringList localList = null;

                            code = hiddenCommands.ToList(
                                hasFlags, notHasFlags, hasAll, notHasAll,
                                null, false, ref localList, ref error);

                            bool simple = NamespaceOps.ShouldUseSimpleMatching(
                                this, currentNamespace, pattern, false);

                            bool qualified = NamespaceOps.IsQualifiedName(pattern);

                            if ((code == ReturnCode.Ok) && simple)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, null, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }

                            if ((code == ReturnCode.Ok) && !simple)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, currentNamespace, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = hiddenCommands.ToList(
                            hasFlags, notHasFlags, hasAll, notHasAll,
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddCommand(
            ICommand command,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddCommand(command, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveCommand(
            string name,
            long token,
            ICommand command,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid command name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if (AreNamespacesEnabled() &&
                    RemoveImportFromNamespaces(name, ref result) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }

                if (
#if NATIVE && TCL
                    ((command == null) ||
                    (DisposeTclBridges(IntPtr.Zero, command, null, false, ref result) == ReturnCode.Ok)) &&
#endif
                    ((command == null) ||
                    (command.Terminate(this, (clientData != null) ?
                            clientData : command.ClientData, ref result) == ReturnCode.Ok)))
                {
                    /* IGNORED */
                    commands.Remove(name, token);

#if EXECUTE_CACHE
                    if (executeCache != null)
                        executeCache.Remove(name, false);
#endif

                    if (command != null)
                    {
                        //
                        // NOTE: Are we allowed to assist in managing the command
                        //       token via the associated plugin?
                        //
                        bool noToken = EntityOps.IsNoToken(command);

                        if (!noToken)
                        {
                            //
                            // NOTE: If this command is being managed by a plugin,
                            //       remove the associated token from said plugin.
                            //
                            IPlugin plugin = command.Plugin;

                            if (plugin != null)
                            {
                                LongList tokens = plugin.CommandTokens;

                                if ((tokens != null) && tokens.Contains(token))
                                {
                                    tokens.Remove(token);

#if ISOLATED_PLUGINS
                                    //
                                    // HACK: Force the command tokens for the
                                    //       isolated plugin to be updated.
                                    //
                                    if (AppDomainOps.IsIsolated(plugin))
                                        plugin.CommandTokens = tokens;
#endif
                                }
                            }
                        }
                    }

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Command, NotifyFlags.Removed,
                        new ObjectTriplet(command, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

                return ReturnCode.Error;
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating command: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPolicy
        public ReturnCode GetPolicy(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPolicy policy,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPolicy(
                        token, lookupFlags, ref name, ref policy,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid policy token \"{0}\"",
                            token) :
                        "invalid policy token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetPolicy(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPolicy policy,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetPolicy(
                        name, lookupFlags, ref token, ref policy,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid policy name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid policy name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddPolicy(
            ExecuteCallback callback,
            IPlugin plugin,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            IPolicy policy = PolicyOps.NewCorePolicy(
                callback, clientData, plugin, ref result);

            if (policy != null)
            {
                if (AddPolicy(
                        policy, clientData, ref token,
                        ref result) == ReturnCode.Ok)
                {
                    result = policy.Name;
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddPolicy(
            IPolicy policy,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (policy == null)
                {
                    result = "invalid policy";
                    return ReturnCode.Error;
                }

                if (policy.Name == null)
                {
                    result = "invalid policy name";
                    return ReturnCode.Error;
                }

                if (!HasPolicies(ref result))
                    return ReturnCode.Error;

                if (DoesPolicyExist(policy.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": policy already exists",
                        policy.Name);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers.Policy policyWrapper = new _Wrappers.Policy(id, policy);
                long newToken = EntityOps.GetToken(policyWrapper);

                //
                // NOTE: Are we allowed to assist in managing the policy
                //       token via the associated plugin?
                //
                if (!EntityOps.IsNoToken(policy))
                {
                    //
                    // NOTE: Store the policy token so that we can remove
                    //       them later without using their names (which
                    //       can change).
                    //
                    IPlugin plugin = policy.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.PolicyTokens;

                        if ((tokens != null) && !tokens.Contains(newToken))
                        {
                            tokens.Add(newToken);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the policy tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.PolicyTokens = tokens;
#endif
                        }
                    }
                }

                EntityOps.SetToken(policy, newToken);
                policies.Add(policy.Name, policyWrapper);
                token = newToken;

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Policy, NotifyFlags.Added,
                    new ObjectPair(policy, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddScriptPolicy(
            IScriptPolicy scriptPolicy,
            IPlugin plugin,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            if (scriptPolicy != null)
                return AddPolicy(scriptPolicy.Execute, plugin, clientData, ref token, ref result);
            else
                result = "invalid script policy";

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePolicy(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPolicies(ref result))
                {
                    string name = null;
                    IPolicy policy = null;

                    if (GetPolicy(token, LookupFlags.Remove, ref name,
                            ref policy, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(policy))
                        {
                            return PrivateRemovePolicy(
                                name, token, policy, clientData, ref result);
                        }
                        else
                        {
                            result = "policy is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePolicy(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasPolicies(ref result))
                {
                    long token = 0;
                    IPolicy policy = null;

                    if (GetPolicy(name, LookupFlags.Remove, ref token,
                            ref policy, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(policy))
                        {
                            return PrivateRemovePolicy(
                                name, token, policy, clientData, ref result);
                        }
                        else
                        {
                            result = "policy is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string PoliciesToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (policies != null)
                    return policies.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal PolicyWrapperDictionary CopyPolicies()
        {
            lock (syncRoot)
            {
                if (policies != null)
                    return new PolicyWrapperDictionary(policies);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetPolicy(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IPolicy policy,
            ref Result error
            )
        {
            if (!HasPolicies(ref error))
                return ReturnCode.Error;

            _Wrappers.Policy wrapper;

            if (!policies.TryGetValue(token, out wrapper))
            {
                error = "policy not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                policy = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((policy == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid policy";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid policy wrapper";
                    return ReturnCode.Error;
                }

                policy = wrapper.policy;
                name = EntityOps.GetName(policy);

                if ((policy == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid policy";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetPolicy(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IPolicy policy,
            ref Result error
            )
        {
            if (!HasPolicies(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid policy name";
                return ReturnCode.Error;
            }

            _Wrappers.Policy wrapper;

            if (!policies.TryGetValue(name, out wrapper))
            {
                error = "policy not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                policy = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((policy == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid policy";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid policy wrapper";
                    return ReturnCode.Error;
                }

                policy = wrapper.policy;
                token = EntityOps.GetToken(policy);

                if ((policy == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid policy";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetPolicy(
            string name,
            LookupFlags lookupFlags,
            ref IPolicy policy,
            ref Result error
            )
        {
            long token = 0;

            return GetPolicy(name, lookupFlags, ref token, ref policy, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddPolicy(
            ExecuteCallback callback,
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddPolicy(callback, plugin, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddScriptPolicy(
            PolicyFlags flags,
            Type commandType,
            long commandToken,
            Interpreter policyInterpreter,
            string text,
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddScriptPolicy(
                ScriptPolicy.Create(flags, commandType, commandToken, policyInterpreter, text),
                plugin, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemovePolicy(
            string name,
            long token,
            IPolicy policy,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid policy name";
                return ReturnCode.Error;
            }

            policies.Remove(name, token);

            if (policy != null)
            {
                //
                // NOTE: Are we allowed to assist in managing the policy
                //       token via the associated plugin?
                //
                bool noToken = EntityOps.IsNoToken(policy);

                if (!noToken)
                {
                    //
                    // NOTE: If this policy is being managed by a plugin,
                    //       remove the associated token from said plugin.
                    //
                    IPlugin plugin = policy.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.PolicyTokens;

                        if ((tokens != null) && tokens.Contains(token))
                        {
                            tokens.Remove(token);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the policy tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.PolicyTokens = tokens;
#endif
                        }
                    }
                }
            }

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Policy, NotifyFlags.Removed,
                new ObjectTriplet(policy, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ITrace
        public ReturnCode GetTrace(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ITrace trace,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetTrace(
                        token, lookupFlags, ref name, ref trace,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid trace token \"{0}\"",
                            token) :
                        "invalid trace token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetTrace(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ITrace trace,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetTrace(
                        name, lookupFlags, ref token, ref trace,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid trace name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid trace name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: All traces added via this method overload are global (i.e.
        //       interpreter-wide).
        //
        public ReturnCode AddTrace(
            TraceCallback callback,
            IPlugin plugin,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                ITrace trace = ScriptOps.NewCoreTrace(
                    callback, clientData, TraceFlags.Global, plugin,
                    ref result);

                if (traces != null)
                {
                    if (AddTrace(
                            trace, clientData, ref token,
                            ref result) == ReturnCode.Ok)
                    {
                        result = trace.Name;
                        return ReturnCode.Ok;
                    }
                }

                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddTrace(
            ITrace trace,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (trace == null)
                {
                    result = "invalid trace";
                    return ReturnCode.Error;
                }

                if (trace.Name == null)
                {
                    result = "invalid trace name";
                    return ReturnCode.Error;
                }

                if (!HasTraces(ref result))
                    return ReturnCode.Error;

                if (DoesTraceExist(trace.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": trace already exists",
                        trace.Name);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers.Trace traceWrapper = new _Wrappers.Trace(id, trace);
                long newToken = EntityOps.GetToken(traceWrapper);

                //
                // NOTE: Are we allowed to assist in managing the trace
                //       token via the associated plugin?
                //
                if (!EntityOps.IsNoToken(trace))
                {
                    //
                    // NOTE: Store the trace token so that we can remove
                    //       them later without using their names (which
                    //       can change).
                    //
                    IPlugin plugin = trace.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.TraceTokens;

                        if ((tokens != null) && !tokens.Contains(newToken))
                        {
                            tokens.Add(newToken);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the trace tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.TraceTokens = tokens;
#endif
                        }
                    }
                }

                EntityOps.SetToken(trace, newToken);
                traces.Add(trace.Name, traceWrapper);
                token = newToken;

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Trace, NotifyFlags.Added,
                    new ObjectPair(trace, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveTrace(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasTraces(ref result))
                {
                    string name = null;
                    ITrace trace = null;

                    if (GetTrace(token, LookupFlags.Remove, ref name,
                            ref trace, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(trace))
                        {
                            return PrivateRemoveTrace(
                                name, token, trace, clientData, ref result);
                        }
                        else
                        {
                            result = "trace is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveTrace(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasTraces(ref result))
                {
                    long token = 0;
                    ITrace trace = null;

                    if (GetTrace(name, LookupFlags.Remove, ref token,
                            ref trace, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(trace))
                        {
                            return PrivateRemoveTrace(
                                name, token, trace, clientData, ref result);
                        }
                        else
                        {
                            result = "trace is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode PrivateGetTrace(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ITrace trace,
            ref Result error
            )
        {
            if (!HasTraces(ref error))
                return ReturnCode.Error;

            _Wrappers.Trace wrapper;

            if (!traces.TryGetValue(token, out wrapper))
            {
                error = "trace not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                trace = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((trace == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid trace";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid trace wrapper";
                    return ReturnCode.Error;
                }

                trace = wrapper.trace;
                name = EntityOps.GetName(trace);

                if ((trace == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid trace";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetTrace(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ITrace trace,
            ref Result error
            )
        {
            if (!HasTraces(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid trace name";
                return ReturnCode.Error;
            }

            _Wrappers.Trace wrapper;

            if (!traces.TryGetValue(name, out wrapper))
            {
                error = "trace not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                trace = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((trace == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid trace";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid trace wrapper";
                    return ReturnCode.Error;
                }

                trace = wrapper.trace;
                token = EntityOps.GetToken(trace);

                if ((trace == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid trace";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetTrace(
            string name,
            LookupFlags lookupFlags,
            ref ITrace trace,
            ref Result error
            )
        {
            long token = 0;

            return GetTrace(name, lookupFlags, ref token, ref trace, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddTrace(
            ITrace trace,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddTrace(trace, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveTrace(
            string name,
            long token,
            ITrace trace,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid trace name";
                return ReturnCode.Error;
            }

            traces.Remove(name, token);

            if (trace != null)
            {
                //
                // NOTE: Are we allowed to assist in managing the trace
                //       token via the associated plugin?
                //
                bool noToken = EntityOps.IsNoToken(trace);

                if (!noToken)
                {
                    //
                    // NOTE: If this trace is being managed by a plugin,
                    //       remove the associated token from said plugin.
                    //
                    IPlugin plugin = trace.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.TraceTokens;

                        if ((tokens != null) && tokens.Contains(token))
                        {
                            tokens.Remove(token);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the trace tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.TraceTokens = tokens;
#endif
                        }
                    }
                }
            }

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Trace, NotifyFlags.Removed,
                new ObjectTriplet(trace, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IAlias
        public ReturnCode GetAlias(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IAlias alias,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetAlias(
                        token, lookupFlags, ref name, ref alias,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid alias token \"{0}\"",
                            token) :
                        "invalid alias token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetAlias(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IAlias alias,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetAlias(
                        name, lookupFlags, ref token, ref alias,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid alias name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid alias name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddAlias(
            string name,
            CommandFlags flags,
            AliasFlags aliasFlags,
            IClientData clientData,
            Interpreter targetInterpreter,
            IExecute target,
            ArgumentList arguments,
            OptionDictionary options,
            int startIndex,
            ref long token,
            ref IAlias alias,
            ref Result result
            )
        {
            CheckDisposed();

            INamespace currentNamespace = null;

            if (AreNamespacesEnabled())
            {
                if (GetCurrentNamespaceViaResolvers(
                        null, LookupFlags.Default, ref currentNamespace,
                        ref result) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }
            }

            //
            // NOTE: Create the new alias with a unique name token (which may
            //       be the same as the name).
            //
            IAlias newAlias = RuntimeOps.NewAlias(
                ScriptOps.MakeCommandName(name), flags, aliasFlags, clientData,
                GetAliasNameToken(name), this, targetInterpreter,
                currentNamespace, currentNamespace, target, arguments, options,
                startIndex);

            //
            // NOTE: For now, rely entirely upon the logic in AddCommand.
            //       Eventually, we may want to perform some specialized
            //       argument validation here, especially if safe interpreters
            //       are going to be implemented.
            //
            ReturnCode code = AddAliasAndCommand(
                newAlias, null, ref token, ref result);

            if (code == ReturnCode.Ok)
            {
                alias = newAlias;
                result = newAlias.NameToken;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddAlias(
            IAlias alias,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (alias == null)
                {
                    result = "invalid alias";
                    return ReturnCode.Error;
                }

                if (alias.NameToken == null)
                {
                    result = "invalid alias name";
                    return ReturnCode.Error;
                }

                if (!HasAliases(ref result))
                    return ReturnCode.Error;

                if (DoesAliasExist(alias.NameToken) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": alias already exists",
                        alias.NameToken);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers.Alias aliasWrapper = new _Wrappers.Alias(id, alias);

                aliases.Add(alias.NameToken, aliasWrapper);
                token = EntityOps.GetToken(aliasWrapper);
                EntityOps.SetToken(alias, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Alias, NotifyFlags.Added,
                    new ObjectPair(alias, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ReturnCode ListAliases(
            string pattern,
            bool noCase,
            bool all,
            ref StringList list,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (HasAliases(ref error))
                {
                    AliasFlags notHasFlags = all ?
                        AliasFlags.None : AliasFlags.Namespace;

                    return aliases.ToList(
                        AliasFlags.None, notHasFlags, false, false, pattern,
                        noCase, ref list, ref error);
                }

                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetAlias(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IAlias alias,
            ref Result error
            )
        {
            if (!HasAliases(ref error))
                return ReturnCode.Error;

            _Wrappers.Alias wrapper;

            if (!aliases.TryGetValue(token, out wrapper))
            {
                error = "alias not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                alias = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((alias == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid alias";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid alias wrapper";
                    return ReturnCode.Error;
                }

                alias = wrapper.alias;
                name = EntityOps.GetName(alias);

                if ((alias == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid alias";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetAlias(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IAlias alias,
            ref Result error
            )
        {
            if (!HasAliases(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid alias name";
                return ReturnCode.Error;
            }

            _Wrappers.Alias wrapper;

            if (!aliases.TryGetValue(name, out wrapper))
            {
                error = "alias not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                alias = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((alias == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid alias";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid alias wrapper";
                    return ReturnCode.Error;
                }

                alias = wrapper.alias;
                token = EntityOps.GetToken(alias);

                if ((alias == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid alias";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetAlias(
            string name,
            LookupFlags lookupFlags,
            ref IAlias alias
            )
        {
            Result error = null;

            return GetAlias(name, lookupFlags, ref alias, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetAlias(
            string name,
            LookupFlags lookupFlags,
            ref IAlias alias,
            ref Result error
            )
        {
            long token = 0;

            return GetAlias(name, lookupFlags, ref token, ref alias, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddAlias(
            string name,
            CommandFlags flags,
            AliasFlags aliasFlags,
            IClientData clientData,
            Interpreter targetInterpreter,
            IExecute target,
            ArgumentList arguments,
            OptionDictionary options,
            int startIndex,
            ref Result result
            )
        {
            long token = 0;

            return AddAlias(
                name, flags, aliasFlags, clientData, targetInterpreter, target,
                arguments, options, startIndex, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddAlias(
            string name,
            CommandFlags flags,
            AliasFlags aliasFlags,
            IClientData clientData,
            Interpreter targetInterpreter,
            IExecute target,
            ArgumentList arguments,
            OptionDictionary options,
            int startIndex,
            ref long token,
            ref Result result
            )
        {
            IAlias alias = null;

            return AddAlias(
                name, flags, aliasFlags, clientData, targetInterpreter, target,
                arguments, options, startIndex, ref token, ref alias, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddAlias(
            string name,
            CommandFlags flags,
            AliasFlags aliasFlags,
            IClientData clientData,
            Interpreter targetInterpreter,
            IExecute target,
            ArgumentList arguments,
            OptionDictionary options,
            int startIndex,
            ref IAlias alias,
            ref Result result
            )
        {
            long token = 0;

            return AddAlias(
                name, flags, aliasFlags, clientData, targetInterpreter, target,
                arguments, options, startIndex, ref token, ref alias, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveAlias(
            string name,
            long token,
            IAlias alias,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid alias name";
                return ReturnCode.Error;
            }

            if ((alias != null) &&
                FlagOps.HasFlags(alias.AliasFlags, AliasFlags.Reference, true))
            {
                if (RemoveObjectReference(
                        ReturnCode.Ok, name, false, ref result) == ReturnCode.Ok)
                {
                    alias.AliasFlags &= ~AliasFlags.Reference;
                }
                else
                {
                    return ReturnCode.Error;
                }
            }

            //
            // BUGFIX: Remove the interpreter disposal callback delegate for this
            //         alias from the list of interpreter disposal callbacks in
            //         the target interpreter since the alias is being removed.
            //
            RemoveTargetDisposeCallback(alias);
            aliases.Remove(name, token);

            if (alias != null)
            {
                //
                // NOTE: Prevent the command from trying to cleanup
                //       the alias since it has now been deleted.
                //
                alias.NameToken = null;
            }

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Alias, NotifyFlags.Removed,
                new ObjectTriplet(alias, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveAlias(
            long token,
            IClientData clientData,
            ref Result result
            ) /* NOT USED */
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasAliases(ref result))
                {
                    string name = null;
                    IAlias alias = null;

                    if (GetAlias(token, LookupFlags.Remove, ref name,
                            ref alias, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveAlias(
                            name, token, alias, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveAlias(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasAliases(ref result))
                {
                    long token = 0;
                    IAlias alias = null;

                    if (GetAlias(name, LookupFlags.Remove, ref token,
                            ref alias, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveAlias(
                            name, token, alias, clientData, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IFunction
        public ReturnCode GetFunction(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IFunction function,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetFunction(
                        token, lookupFlags, ref name, ref function,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid function token \"{0}\"",
                            token) :
                        "invalid function token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetFunction(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IFunction function,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetFunction(
                        name, lookupFlags, ref token, ref function,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid function name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid function name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ListFunctions(
            FunctionFlags hasFlags,
            FunctionFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasFunctions(ref localError))
                {
                    code = functions.ToList(
                        hasFlags, notHasFlags, hasAll, notHasAll,
                        pattern, noCase, ref list, ref error);
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddFunction(
            Type type,
            string name,
            int arguments,
            TypeList types,
            FunctionFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            if (type == null)
                type = Type.GetType(
                    FormatOps.FunctionTypeName(name), false, true);

            if (type == null)
                type = Type.GetType(FormatOps.FunctionTypeName(
                    Characters.Underscore + name), false, true);

            if (type != null)
            {
                FunctionFlags functionFlags =
                    AttributeOps.GetFunctionFlags(type) | flags;

                //
                // NOTE: Is this interpreter marked as "safe"?
                //
                bool createSafe = FlagOps.HasFlags(createFlags,
                    CreateFlags.Safe, true);

                //
                // NOTE: Is this interpreter marked as "standard"?
                //
                bool createStandard = FlagOps.HasFlags(createFlags,
                    CreateFlags.Standard, true);

                //
                // NOTE: Check if this function has been marked as "safe" or
                //       "unsafe" by its author.
                //
                bool safe = FlagOps.HasFlags(functionFlags,
                        FunctionFlags.Safe, true) &&
                    !FlagOps.HasFlags(functionFlags,
                        FunctionFlags.Unsafe, true);

                //
                // NOTE: If the interpreter is "safe", make sure we only add
                //       functions that are marked as "safe" and NOT marked
                //       as "unsafe" unless we are merely hiding functions
                //       not considered to be "safe".  In that case, we add
                //       all functions, hidden them as necessary.
                //
                if (safe || !createSafe)
                {
                    //
                    // NOTE: Check if this function is part of the "Tcl Standard"
                    //       (i.e. it is largely (or completely) compatible with
                    //       an identically named function from Tcl/Tk 8.4, 8.5,
                    //       and/or 8.6).
                    //
                    bool standard = FlagOps.HasFlags(
                        functionFlags, FunctionFlags.Standard, true);

                    //
                    // NOTE: If the interpreter is "standard", make sure we only
                    //       add functions that are marked as "standard" and NOT
                    //       marked as "non-standard" unless we are merely hiding
                    //       functions not considered to be "standard".  In that
                    //       case, we add all functions, hidden them as necessary.
                    //
                    if (standard || !createStandard)
                    {
                        try
                        {
                            if (arguments == (int)Arity.Automatic)
                                arguments = AttributeOps.GetArguments(type);

                            object[] args = {
                                new FunctionData(
                                    name, null, null, arguments, types,
                                    flags, clientData, plugin, 0)
                            };

                            IFunction function =
                                (IFunction)Activator.CreateInstance(type, args);

                            return AddFunction(
                                function, null, ref token, ref result);
                        }
                        catch (Exception e)
                        {
                            result = e;
                        }
                    }
                    else if (strict)
                    {
                        result = "cannot add non-standard function to standard interpreter";
                    }
                    else
                    {
                        return ReturnCode.Ok;
                    }
                }
                else if (strict)
                {
                    result = "cannot add unsafe function to safe interpreter";
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                result = String.Format(
                    "function \"{0}\" not found",
                    FormatOps.FunctionTypeName(name));
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddFunction(
            IFunction function,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (function == null)
                {
                    result = "invalid function";
                    return ReturnCode.Error;
                }

                if (function.Name == null)
                {
                    result = "invalid function name";
                    return ReturnCode.Error;
                }

                if (!HasFunctions(ref result))
                    return ReturnCode.Error;

                if (DoesFunctionExist(function.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": function already exists",
                        function.Name);

                    return ReturnCode.Error;
                }

                //
                // HACK: Due to how the expression parser works, we cannot allow a
                //       function to be added that has the name of an existing
                //       operator.
                //
                if (DoesOperatorExist(function.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": operator already exists",
                        function.Name);

                    return ReturnCode.Error;
                }

#if false
                //
                // HACK: This is part of an ugly hack to add "tcl::mathfunc::*" and
                //       "tcl::mathop::*" support for [expr] functions and operators
                //       to Eagle, respectively.
                //
                if (AreNamespacesEnabled())
                {
                    INamespace @namespace = NamespaceOps.Lookup(
                        this, TclVars.MathFunctionNamespaceName, true, true,
                        ref result);

                    if (@namespace == null)
                        return ReturnCode.Error;

                    IExecute execute = function as IExecute;
                    long token2 = 0;

                    if ((execute != null) && AddIExecute(
                            NamespaceOps.MakeQualifiedName(this, @namespace,
                            function.Name), execute, clientData, ref token2,
                            ref result) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }
                }
                else
                {
                    IExecute execute = function as IExecute;
                    long token2 = 0;

                    if ((execute != null) && AddIExecute(NamespaceOps.MakeName(
                            TclVars.MathFunctionNamespaceName, function.Name,
                            true, false), execute, clientData, ref token2,
                            ref result) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }
                }
#endif

                ReturnCode code = ReturnCode.Ok;

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    try
                    {
                        code = function.Initialize(this,
                            (clientData != null) ? clientData : function.ClientData,
                            ref result);
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while initializing function: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        bool savedImmutable = BeginMutableExecution();

                        ReturnCode terminateCode;
                        Result terminateResult = null;

                        try
                        {
                            terminateCode = function.Terminate(this,
                                (clientData != null) ? clientData : function.ClientData,
                                ref terminateResult);
                        }
                        catch (Exception e)
                        {
                            terminateResult = String.Format(
                                "caught exception while terminating function: {0}",
                                e);

                            terminateCode = ReturnCode.Error;
                        }
                        finally
                        {
                            EndMutableExecution(savedImmutable);
                        }

                        if (terminateCode != ReturnCode.Ok)
                            DebugOps.Complain(this, terminateCode, terminateResult);
                    }
                }

                if (code != ReturnCode.Ok)
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                    return code;
                }

                long id = NextId();
                _Wrappers.Function functionWrapper = new _Wrappers.Function(id, function);
                long newToken = EntityOps.GetToken(functionWrapper);

                //
                // NOTE: Are we allowed to assist in managing the function
                //       token via the associated plugin?
                //
                if (!EntityOps.IsNoToken(function))
                {
                    //
                    // NOTE: Store the function token so that we can remove
                    //       them later without using their names (which
                    //       can change).
                    //
                    IPlugin plugin = function.Plugin;

                    if (plugin != null)
                    {
                        LongList tokens = plugin.FunctionTokens;

                        if ((tokens != null) && !tokens.Contains(newToken))
                        {
                            tokens.Add(newToken);

#if ISOLATED_PLUGINS
                            //
                            // HACK: Force the function tokens for the
                            //       isolated plugin to be updated.
                            //
                            if (AppDomainOps.IsIsolated(plugin))
                                plugin.FunctionTokens = tokens;
#endif
                        }
                    }
                }

                EntityOps.SetToken(function, newToken);
                functions.Add(function.Name, functionWrapper);
                token = newToken;

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Function, NotifyFlags.Added,
                    new ObjectPair(function, token), this,
                    clientData, null, null, ref result);
#endif

                /* IGNORED */
                GlobalState.PopActiveInterpreter();
                return code;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveFunction(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasFunctions(ref result))
                {
                    string name = null;
                    IFunction function = null;

                    if (GetFunction(token, LookupFlags.Remove, ref name,
                            ref function, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(function))
                        {
                            return PrivateRemoveFunction(
                                name, token, function, clientData, ref result);
                        }
                        else
                        {
                            result = "function is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveFunction(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasFunctions(ref result))
                {
                    long token = 0;
                    IFunction function = null;

                    if (GetFunction(name, LookupFlags.Remove, ref token,
                            ref function, ref result) == ReturnCode.Ok)
                    {
                        if (!EntityOps.IsReadOnly(function))
                        {
                            return PrivateRemoveFunction(
                                name, token, function, clientData, ref result);
                        }
                        else
                        {
                            result = "function is read-only";
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode PrivateGetFunction(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IFunction function,
            ref Result error
            )
        {
            if (!HasFunctions(ref error))
                return ReturnCode.Error;

            _Wrappers.Function wrapper;

            if (!functions.TryGetValue(token, out wrapper))
            {
                error = "function not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                function = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((function == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid function wrapper";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid function wrapper";
                    return ReturnCode.Error;
                }

                function = wrapper.function;
                name = EntityOps.GetName(function);

                if ((function == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetFunction(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IFunction function,
            ref Result error
            )
        {
            if (!HasFunctions(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid function name";
                return ReturnCode.Error;
            }

            _Wrappers.Function wrapper;

            if (!functions.TryGetValue(name, out wrapper))
            {
                error = "function not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                function = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((function == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid function";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid function wrapper";
                    return ReturnCode.Error;
                }

                function = wrapper.function;
                token = EntityOps.GetToken(function);

                if ((function == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid function";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetFunction(
            string name,
            LookupFlags lookupFlags,
            ref IFunction function,
            ref Result error
            )
        {
            long token = 0;

            return GetFunction(name, lookupFlags, ref token, ref function, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddFunction(
            Type type,
            string name,
            TypeList types,
            FunctionFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref Result result
            )
        {
            long token = 0;

            return AddFunction(
                type, name, types, flags, plugin, clientData,
                strict, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddFunction(
            Type type,
            string name,
            TypeList types,
            FunctionFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref long token,
            ref Result result
            )
        {
            return AddFunction(
                type, name, (int)Arity.Automatic, types, flags,
                plugin, clientData, strict, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveFunction(
            string name,
            long token,
            IFunction function,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid function name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if ((function == null) ||
                    (function.Terminate(this, (clientData != null) ?
                            clientData : function.ClientData, ref result) == ReturnCode.Ok))
                {
                    functions.Remove(name, token);

                    if (function != null)
                    {
                        //
                        // NOTE: Are we allowed to assist in managing the function
                        //       token via the associated plugin?
                        //
                        bool noToken = EntityOps.IsNoToken(function);

                        if (!noToken)
                        {
                            //
                            // NOTE: If this function is being managed by a plugin,
                            //       remove the associated token from said plugin.
                            //
                            IPlugin plugin = function.Plugin;

                            if (plugin != null)
                            {
                                LongList tokens = plugin.FunctionTokens;

                                if ((tokens != null) && tokens.Contains(token))
                                {
                                    tokens.Remove(token);

#if ISOLATED_PLUGINS
                                    //
                                    // HACK: Force the function tokens for the
                                    //       isolated plugin to be updated.
                                    //
                                    if (AppDomainOps.IsIsolated(plugin))
                                        plugin.FunctionTokens = tokens;
#endif
                                }
                            }
                        }
                    }

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Function, NotifyFlags.Removed,
                        new ObjectTriplet(function, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

                return ReturnCode.Error;
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating function: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IProcedure
        public ReturnCode GetProcedure(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IProcedure procedure,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetProcedure(
                        token, lookupFlags, ref name, ref procedure,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid procedure token \"{0}\"",
                            token) :
                        "invalid procedure token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetProcedure(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IProcedure procedure,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetProcedure(
                        name, lookupFlags, ref token, ref procedure,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid procedure name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid procedure name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ListProcedures(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasProcedures(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        if (code == ReturnCode.Ok)
                        {
                            StringList localList = null;

                            code = procedures.ToList(
                                hasFlags, notHasFlags, hasAll, notHasAll,
                                null, false, ref localList, ref error);

                            bool qualified = NamespaceOps.IsQualifiedName(pattern);

                            if (code == ReturnCode.Ok)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, currentNamespace, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = procedures.ToList(
                            hasFlags, notHasFlags, hasAll, notHasAll,
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddOrUpdateProcedure(
            string name,
            ProcedureFlags flags,
            StringList arguments,
            string body,
            IScriptLocation location,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            CheckDisposed();

            IProcedure procedure = RuntimeOps.NewCoreProcedure(
                this, ScriptOps.MakeCommandName(name), null, null,
                flags, new ArgumentList(arguments, ArgumentFlags.NameOnly),
                body, location, clientData);

            return AddOrUpdateProcedure(procedure, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RenameProcedure(
            string oldName,
            string newName,
            bool delete,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasProcedures(ref result))
                {
                    if (!delete || !String.IsNullOrEmpty(newName))
                    {
                        IProcedure oldProcedure = null;

                        if (GetProcedure(oldName, LookupFlags.Default, ref oldProcedure, ref result) == ReturnCode.Ok)
                        {
                            if (!EntityOps.IsReadOnly(oldProcedure))
                            {
                                if (EntityOps.IsNoRename(oldProcedure))
                                    return ReturnCode.Ok;

                                _Wrappers.Procedure oldWrapper = oldProcedure as _Wrappers.Procedure;

                                if (oldWrapper != null)
                                {
                                    IAlias oldAlias = oldWrapper.procedure as IAlias;

                                    if (PreventAliasLoop(oldAlias, newName, ref result) == ReturnCode.Ok)
                                    {
                                        if (IsValidCommandName(newName, ref result) == ReturnCode.Ok)
                                        {
                                            if (!AreNamespacesEnabled() ||
                                                RenameImportInNamespaces(oldName, newName, ref result) == ReturnCode.Ok)
                                            {
                                                //
                                                // NOTE: New name, same token.
                                                //
                                                oldWrapper.Name = newName;

                                                /* IGNORED */
                                                procedures.Rename(oldName, newName);

#if EXECUTE_CACHE
                                                if (executeCache != null)
                                                    executeCache.Rename(oldName, newName, oldWrapper, false);
#endif

#if NOTIFY
                                                /* IGNORED */
                                                CheckNotifications(
                                                    NotifyType.Procedure, NotifyFlags.Renamed,
                                                    new ObjectTriplet(oldProcedure, oldName, newName), this,
                                                    null, null, null, ref result);
#endif

                                                result = String.Empty;
                                                return ReturnCode.Ok;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    result = String.Format(
                                        "can't rename \"{0}\": invalid procedure wrapper",
                                        oldName);
                                }
                            }
                            else
                            {
                                result = "procedure is read-only";
                            }
                        }
                        else
                        {
                            result = String.Format(
                                "can't rename \"{0}\": procedure doesn't exist",
                                oldName);
                        }
                    }
                    else
                    {
                        return RemoveProcedure(oldName, null, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveProcedure(
            long token,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                string name = null;
                IProcedure procedure = null;

                if (GetProcedure(token, LookupFlags.Default, ref name,
                        ref procedure, ref result) == ReturnCode.Ok)
                {
                    if (!EntityOps.IsReadOnly(procedure))
                    {
                        if (EntityOps.IsNoRemove(procedure))
                            return ReturnCode.Ok;

                        return PrivateRemoveProcedure(
                            name, token, procedure, clientData, ref result);
                    }
                    else
                    {
                        result = "procedure is read-only";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveProcedure(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                long token = 0;
                IProcedure procedure = null;

                if (GetProcedure(name, LookupFlags.Default, ref token,
                        ref procedure, ref result) == ReturnCode.Ok)
                {
                    if (!EntityOps.IsReadOnly(procedure))
                    {
                        if (EntityOps.IsNoRemove(procedure))
                            return ReturnCode.Ok;

                        return PrivateRemoveProcedure(
                            name, token, procedure, clientData, ref result);
                    }
                    else
                    {
                        result = "procedure is read-only";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MatchProcedure(
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref IProcedure procedure,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                bool useHidden = Engine.HasUseHidden(engineFlags);
                bool matchHidden = Engine.HasMatchHidden(engineFlags);

                ProcedureWrapperDictionary localProcedures =
                    useHidden ? hiddenProcedures : procedures;

                if (localProcedures != null)
                {
                    //
                    // NOTE: *WARNING* Empty command/procedure names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (localProcedures.Count > 0)
                        {
                            _Wrappers.Procedure localProcedure;
                            string exactName = null;
                            StringList list = new StringList();

                            if (localProcedures.TryGetValue(name, out localProcedure) &&
                                (matchHidden || !EntityOps.IsHidden(localProcedure)))
                            {
                                //
                                // NOTE: Exact procedure match.
                                //
                                exactName = name;

                                //
                                // NOTE: Store the exact procedure match in the result
                                //       list.
                                //
                                list.Add(name);
                            }
                            else
                            {
                                foreach (KeyValuePair<string, _Wrappers.Procedure> pair in localProcedures)
                                {
                                    if (String.Compare(
                                            pair.Key, 0, name, 0, name.Length,
                                            StringOps.SystemStringComparisonType) == 0)
                                    {
                                        //
                                        // NOTE: Is the procedure visible or are we allowed to
                                        //       find hidden procedures?
                                        //
                                        if (matchHidden || !EntityOps.IsHidden(pair.Value))
                                        {
                                            //
                                            // NOTE: Was the key valid (this should always succeed).
                                            //
                                            if (pair.Key != null)
                                            {
                                                //
                                                // NOTE: It was a match; however, was it an exact match?
                                                //
                                                if (pair.Key.Length == name.Length)
                                                    //
                                                    // NOTE: Preserve match, it may differ in case.
                                                    //
                                                    exactName = pair.Key;

                                                //
                                                // NOTE: Was it an exact match or did we match at least one
                                                //       character in a partial match?
                                                //
                                                if ((pair.Key.Length == name.Length) || (name.Length > 0))
                                                    //
                                                    // NOTE: Store the exact or partial match in the results
                                                    //       dictionary.
                                                    //
                                                    list.Add(pair.Key);
                                            }
                                        }
                                    }
                                }
                            }

                            //
                            // NOTE: If there was an exact match, just use it.
                            //
                            if (exactName != null)
                            {
                                //
                                // NOTE: No need to change the caller's variable,
                                //       it already contains the correct value.
                                //
                                if ((useHidden && PrivateGetHiddenProcedure(
                                        exactName, lookupFlags, ref token,
                                        ref procedure, ref error) == ReturnCode.Ok) ||
                                    (!useHidden && PrivateGetProcedure(
                                        exactName, lookupFlags, ref token,
                                        ref procedure, ref error) == ReturnCode.Ok))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenProcedure : NotifyType.Procedure,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, procedure, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count == 1)
                            {
                                //
                                // NOTE: Normal case, exactly one procedure matched.
                                //
                                if ((useHidden && PrivateGetHiddenProcedure(
                                        list[0], lookupFlags, ref token,
                                        ref procedure, ref error) == ReturnCode.Ok) ||
                                    (!useHidden && PrivateGetProcedure(
                                        list[0], lookupFlags, ref token,
                                        ref procedure, ref error) == ReturnCode.Ok))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        useHidden ? NotifyType.HiddenProcedure : NotifyType.Procedure,
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, list[0], procedure, token), this, null, null,
                                        null, ref error);
#endif

                                    return ReturnCode.Ok;
                                }
                            }
                            else if (list.Count > 1)
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        "ambiguous", "procedure", name, list,
                                        null, null) :
                                    (Result)"ambiguous procedure";

                                ambiguous = true;
                            }
                            else
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    ScriptOps.BadValue(
                                        null, "procedure", name, localProcedures.Keys,
                                        null, null) :
                                    (Result)"bad procedure";
                            }
                        }
                        else
                        {
                            error = "no procedures defined";
                        }
                    }
                    else
                    {
                        error = "invalid procedure name";
                    }
                }
                else
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "{0}procedures not available",
                            useHidden ? "hidden " : String.Empty) :
                        "procedures not available";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal int SetProceduresReadOnly(
            string pattern,
            bool noCase,
            bool readOnly
            )
        {
            int result = 0;

            lock (syncRoot)
            {
                if (procedures != null)
                {
                    foreach (KeyValuePair<string, _Wrappers.Procedure> pair in procedures)
                    {
                        IProcedure procedure = pair.Value;

                        if (procedure == null)
                            continue;

                        if ((pattern != null) && !StringOps.Match(this,
                                StringOps.DefaultMatchMode, pair.Key,
                                pattern, noCase))
                        {
                            continue;
                        }

                        if (EntityOps.SetReadOnly(procedure, readOnly))
                            result++;
                    }
                }
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetProcedure(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IProcedure procedure,
            ref Result error
            )
        {
            if (!HasProcedures(ref error))
                return ReturnCode.Error;

            _Wrappers.Procedure wrapper;

            if (!procedures.TryGetValue(token, out wrapper))
            {
                error = "procedure not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                procedure = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid procedure wrapper";
                    return ReturnCode.Error;
                }

                procedure = wrapper.procedure;
                name = EntityOps.GetName(procedure);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetProcedure(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IProcedure procedure,
            ref Result error
            )
        {
            if (!HasProcedures(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid procedure name";
                return ReturnCode.Error;
            }

            _Wrappers.Procedure wrapper;

            if (!procedures.TryGetValue(name, out wrapper))
            {
                error = "procedure not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                procedure = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid procedure wrapper";
                    return ReturnCode.Error;
                }

                procedure = wrapper.procedure;
                token = EntityOps.GetToken(procedure);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetProcedure(
            string name,
            LookupFlags lookupFlags,
            ref IProcedure procedure
            )
        {
            Result error = null;

            return GetProcedure(name, lookupFlags, ref procedure, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetProcedure(
            string name,
            LookupFlags lookupFlags,
            ref IProcedure procedure,
            ref Result error
            )
        {
            long token = 0;

            return GetProcedure(name, lookupFlags, ref token, ref procedure, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListProcedures(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListProcedures(
                hasFlags, notHasFlags, hasAll, notHasAll, pattern, noCase,
                strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenProcedures(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list
            )
        {
            Result error = null;

            return ListHiddenProcedures(
                hasFlags, notHasFlags, hasAll, notHasAll, pattern, noCase,
                strict, ref list, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListHiddenProcedures(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasHiddenProcedures(ref localError))
                {
                    if (AreNamespacesEnabled())
                    {
                        INamespace currentNamespace = null;

                        code = GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default, ref currentNamespace,
                            ref error);

                        if (code == ReturnCode.Ok)
                        {
                            StringList localList = null;

                            code = hiddenProcedures.ToList(
                                hasFlags, notHasFlags, hasAll, notHasAll,
                                null, false, ref localList, ref error);

                            bool qualified = NamespaceOps.IsQualifiedName(pattern);

                            if (code == ReturnCode.Ok)
                            {
                                code = NamespaceOps.MatchItems(
                                    this, currentNamespace, localList, pattern,
                                    noCase, !qualified, qualified, false, ref list,
                                    ref error);
                            }
                        }
                    }
                    else
                    {
                        pattern = ScriptOps.MakeCommandName(pattern);

                        code = hiddenProcedures.ToList(
                            hasFlags, notHasFlags, hasAll, notHasAll,
                            pattern, noCase, ref list, ref error);
                    }
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddOrUpdateProcedureWithReplace(
            IProcedure procedure,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddOrUpdateProcedureWithReplace(
                procedure, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOrUpdateProcedureWithReplace(
            IProcedure procedure,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            if (procedure != null)
            {
                ReturnCode code = AddOrUpdateProcedure(procedure, ref token, ref result);

                if (code == ReturnCode.Ok)
                {
                    try
                    {
                        string name = procedure.Name;

                        if ((code == ReturnCode.Ok) &&
                            (DoesIExecuteExist(name) == ReturnCode.Ok))
                        {
                            code = RemoveIExecute(name, clientData, ref result);
                        }

                        if ((code == ReturnCode.Ok) &&
                            (DoesCommandExist(name) == ReturnCode.Ok))
                        {
                            code = RemoveCommand(name, clientData, ref result);
                        }
                    }
                    finally
                    {
                        //
                        // BUGFIX: If we fail to remove an ICommand or IExecute,
                        //         we must still remove the procedure we just
                        //         added.
                        //
                        if (code != ReturnCode.Ok)
                        {
                            ReturnCode removeCode;
                            Result removeResult = null;

                            removeCode = RemoveProcedure(token, clientData, ref removeResult);

                            if (removeCode != ReturnCode.Ok)
                                DebugOps.Complain(this, removeCode, removeResult);
                        }
                    }
                }

                return code;
            }
            else
            {
                result = "invalid procedure";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOrUpdateProcedure(
            IProcedure procedure,
            ref long token,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (procedure == null)
                {
                    result = "invalid procedure";
                    return ReturnCode.Error;
                }

                if (procedure.Name == null)
                {
                    result = "invalid procedure name";
                    return ReturnCode.Error;
                }

                if (!HasProcedures(ref result))
                    return ReturnCode.Error;

                Result localError = null;

                if (AreNamespacesEnabled() && (NamespaceOps.LookupParent(
                        this, procedure.Name, false, true, false, ref localError) == null))
                {
                    result = String.Format(
                        "can't add procedure \"{0}\": {1}",
                        procedure.Name, localError);

                    return ReturnCode.Error;
                }

                _Wrappers.Procedure oldProcedureWrapper = null;
                bool exists = procedures.TryGetValue(procedure.Name, out oldProcedureWrapper);

                if (exists)
                {
                    if (immutable)
                    {
                        result = "interpreter is immutable";
                        return ReturnCode.Error;
                    }

                    if (EntityOps.IsReadOnly(oldProcedureWrapper))
                    {
                        result = "procedure is read-only";
                        return ReturnCode.Error;
                    }

                    if (EntityOps.IsNoReplace(oldProcedureWrapper))
                        return ReturnCode.Ok;
                }

                long id = NextId();
                _Wrappers.Procedure procedureWrapper = new _Wrappers.Procedure(id, procedure);
                long newToken = EntityOps.GetToken(procedureWrapper);
                EntityOps.SetToken(procedure, newToken);

                if (exists)
                {
                    procedures[procedure.Name] = procedureWrapper;

#if EXECUTE_CACHE
                    if (executeCache != null)
                        executeCache.AddOrUpdate(procedure.Name, procedureWrapper, false);
#endif

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Procedure, NotifyFlags.Updated,
                        new ObjectPair(oldProcedureWrapper, procedure), this,
                        null, null, null, ref result);
#endif
                }
                else
                {
                    procedures.Add(procedure.Name, procedureWrapper);

#if EXECUTE_CACHE
                    if (executeCache != null)
                        executeCache.AddOrUpdate(procedure.Name, procedureWrapper, false);
#endif

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Procedure, NotifyFlags.Added,
                        new ObjectPair(procedure, newToken), this,
                        null, null, null, ref result);
#endif
                }

                token = newToken;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveProcedure(
            string name,
            long token,
            IProcedure procedure,
            IClientData clientData,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid procedure name";
                return ReturnCode.Error;
            }

            GlobalState.PushActiveInterpreter(this);

            try
            {
                if (AreNamespacesEnabled() &&
                    RemoveImportFromNamespaces(name, ref result) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }

#if NATIVE && TCL
                if ((procedure == null) ||
                    (DisposeTclBridges(IntPtr.Zero, procedure, null, false, ref result) == ReturnCode.Ok))
#endif
                {
                    procedures.Remove(name, token);

#if EXECUTE_CACHE
                    if (executeCache != null)
                        executeCache.Remove(name, false);
#endif

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Procedure, NotifyFlags.Removed,
                        new ObjectTriplet(procedure, name, token), this,
                        clientData, null, null, ref result);
#endif

                    return ReturnCode.Ok;
                }

#if NATIVE && TCL
                return ReturnCode.Error;
#endif
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating procedure: {0}",
                    e);

                return ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Channel
        public bool IsStreamForChannel(
            string name,
            ChannelType channelType,
            Stream stream
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                string channelId = RuntimeOps.ChannelTypeToName(name, channelType);

                if ((channelId == null) || (stream == null))
                    return false;

                if (!HasChannels())
                    return false;

                Channel channel;

                if (!channels.TryGetValue(channelId, out channel))
                    return false;

                if (channel == null)
                    return false;

                ChannelStream channelStream = channel.GetStream();

                if (channelStream == null)
                    return false;

                Stream innerStream = channelStream.GetStream();

                return Object.ReferenceEquals(stream, innerStream);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ListChannels(
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasChannels(ref localError))
                {
                    code = channels.ToList(
                        pattern, noCase, ref list, ref error);
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddChannel(
            string name,
            ChannelType channelType,
            Stream stream,
            OptionDictionary options,
            StreamFlags flags,
            StreamTranslation inTranslation,
            StreamTranslation outTranslation,
            Encoding encoding,
            bool appendMode,
            bool autoFlush,
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Ok;

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                string channelId = RuntimeOps.ChannelTypeToName(name, channelType);

                if (channelId == null)
                {
                    error = "invalid channel name";
                    return ReturnCode.Error;
                }

                if (!HasChannels(ref error))
                    return ReturnCode.Error;

                if (channels.ContainsKey(channelId))
                {
                    error = String.Format(
                        "can't add \"{0}\": channel already exists",
                        channelId);

                    return ReturnCode.Error;
                }

                ChannelStream channelStream = null;
                Channel channel = null;

                try
                {
                    channelStream = new ChannelStream(
                        stream, options, flags, inTranslation,
                        outTranslation);

                    channel = new Channel(
                        channelStream, encoding, appendMode,
                        autoFlush, clientData);

                    channels.Add(name, channel);

                    code = ReturnCode.Ok;
                }
                catch (Exception e)
                {
                    error = e;
                    code = ReturnCode.Error;
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        if (channelStream != null)
                        {
                            channelStream.PreventClose = false;
                            channelStream.Close();
                            channelStream = null;
                        }

                        if (channel != null)
                        {
                            channel.Close();
                            channel = null;
                        }
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveChannel(
            string name,
            ChannelType channelType,
            bool flush,
            bool close,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                string channelId = RuntimeOps.ChannelTypeToName(name, channelType);

                if (channelId == null)
                {
                    error = "invalid channel name";
                    return ReturnCode.Error;
                }

                if (!HasChannels(ref error))
                    return ReturnCode.Error;

                Channel channel;

                if (channels.TryGetValue(channelId, out channel))
                {
                    if (flush && (channel != null))
                    {
                        try
                        {
                            //
                            // NOTE: Attempt to flush the channel.
                            //
                            channel.Flush(); /* throw */
                        }
                        catch (Exception e)
                        {
                            if (strict)
                            {
                                error = e;
                                return ReturnCode.Error;
                            }
                        }
                    }

                    if (close && (channel != null))
                    {
                        try
                        {
                            //
                            // NOTE: Attempt to close the channel.
                            //
                            channel.Close(); /* throw */
                        }
                        catch (Exception e)
                        {
                            if (strict)
                            {
                                error = e;
                                return ReturnCode.Error;
                            }
                        }
                    }

                    channels.Remove(channelId);

                    return ReturnCode.Ok;
                }
                else
                {
                    error = String.Format(
                        "can not find channel named \"{0}\"",
                        channelId);

                    return ReturnCode.Error;
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallFrame (Scope)
        public ReturnCode GetScope(
            string name,
            LookupFlags lookupFlags,
            ref ICallFrame frame,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasScopes(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty scope names are technically allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    //       That being said, we actually block them for practical
                    //       reasons in the [scope] command itself.
                    //
                    if (name != null)
                    {
                        if (scopes.TryGetValue(name, out frame))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "scope \"{0}\" not found",
                                    name) :
                                "scope not found";
                        }
                    }
                    else
                    {
                        error = "invalid scope name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool HasScopes()
        {
            Result error = null;

            return HasScopes(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetScope(
            string name,
            LookupFlags lookupFlags,
            ref ICallFrame frame
            )
        {
            Result error = null;

            return GetScope(name, lookupFlags, ref frame, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ScopesToString(
            string pattern,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasScopes())
                    result = scopes.ToString(pattern, false);
                else
                    result = String.Empty;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddScope(
            ICallFrame frame,
            IClientData clientData,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (frame == null)
                {
                    result = "invalid scope";
                    return ReturnCode.Error;
                }

                if (frame.Name == null)
                {
                    result = "invalid scope name";
                    return ReturnCode.Error;
                }

                if (!HasScopes(ref result))
                    return ReturnCode.Error;

                if (DoesScopeExist(frame.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": scope already exists",
                        frame.Name);

                    return ReturnCode.Error;
                }

                scopes.Add(frame.Name, frame);
                result = String.Empty;
            }

#if NOTIFY
            //
            // NOTE: This must be done outside of the lock statement (above),
            //       because the code called may have arbitrary side-effects.
            //
            /* IGNORED */
            CheckNotifications(
                NotifyType.CallFrame, NotifyFlags.Added,
                frame, this, clientData, null, null,
                ref result);
#endif

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveScope(
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            ICallFrame frame = null;

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (String.IsNullOrEmpty(name))
                {
                    result = "invalid scope name";
                    return ReturnCode.Error;
                }

                if (!HasScopes(ref result))
                    return ReturnCode.Error;

                if (GetScopeCallFrame(
                        name, LookupFlags.RemoveNoVerbose,
                        true, true, ref frame) == ReturnCode.Ok)
                {
                    //
                    // NOTE: We destroyed the current scope call frame (after
                    //       popping it).
                    //
                    result = String.Empty;
                    return ReturnCode.Ok;
                }
                else
                {
                    //
                    // NOTE: Make sure the scope exists and return an error if
                    //       it does not.
                    //
                    if (GetScope(
                            name, LookupFlags.Remove, ref frame,
                            ref result) == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Remove the scope from the interpreter.
                        //
                        scopes.Remove(name);
                        result = String.Empty;
                    }
                    else
                    {
                        return ReturnCode.Error;
                    }
                }
            }

#if NOTIFY || NOTIFY_OBJECT
            //
            // NOTE: This must be done outside of the lock statement (above),
            //       because the code called may have arbitrary side-effects.
            //
            /* IGNORED */
            CheckNotifications(
                NotifyType.CallFrame, NotifyFlags.Deleted,
                frame, this, clientData, null, null,
                ref result);
#endif

            return ReturnCode.Ok;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDbConnection / IDbTransaction
#if DATA
        public ReturnCode GetDbConnection(
            string name,
            LookupFlags lookupFlags,
            ref IDbConnection connection,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasDbConnections(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty database connection names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (connections.TryGetValue(name, out connection))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "database connection \"{0}\" not found",
                                    name) :
                                "database connection not found";
                        }
                    }
                    else
                    {
                        error = "invalid database connection name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetDbTransaction(
            string name,
            LookupFlags lookupFlags,
            ref IDbTransaction transaction,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasDbTransactions(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty database transaction names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (transactions.TryGetValue(name, out transaction))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "database transaction \"{0}\" not found",
                                    name) :
                                "database transaction not found";
                        }
                    }
                    else
                    {
                        error = "invalid database transaction name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string DbConnectionsToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (connections != null)
                    return connections.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void AddDbConnection(
            string name,
            IDbConnection connection
            )
        {
            if (name != null)
            {
                lock (syncRoot)
                {
                    if (connections != null)
                        connections.Add(name, connection);
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool RemoveDbConnection(
            string name
            )
        {
            if (name != null)
            {
                lock (syncRoot)
                {
                    if (connections != null)
                        return connections.Remove(name);
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string DbTransactionsToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (transactions != null)
                    return transactions.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void AddDbTransaction(
            string name,
            IDbTransaction Transaction
            )
        {
            if (name != null)
            {
                lock (syncRoot)
                {
                    if (transactions != null)
                        transactions.Add(name, Transaction);
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool RemoveDbTransaction(
            string name
            )
        {
            if (name != null)
            {
                lock (syncRoot)
                {
                    if (transactions != null)
                        return transactions.Remove(name);
                }
            }

            return false;
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Encoding
        public static ReturnCode GetEncoding(
            Interpreter interpreter,
            string name,
            ref Encoding encoding,
            ref Result error
            )
        {
            return GetEncoding(
                interpreter, name, LookupFlags.Default, ref encoding, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private EncodingDictionary Encodings
        {
            get
            {
                lock (syncRoot)
                {
                    return encodings;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void GetSystemEncodings(
            ref EncodingDictionary encodings /* in, out */
            )
        {
            if (encodings == null)
                encodings = new EncodingDictionary();

            lock (syncRoot)
            {
                EncodingInfo[] systemEncodings = Encoding.GetEncodings();

                if (systemEncodings != null)
                {
                    foreach (EncodingInfo encodingInfo in systemEncodings)
                    {
                        if (encodingInfo == null)
                            continue;

                        encodings[encodingInfo.Name] = encodingInfo.GetEncoding();
                    }
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void GetEncodings(
            ref EncodingDictionary encodings /* in, out */
            )
        {
            if (encodings == null)
                encodings = new EncodingDictionary();

            lock (syncRoot)
            {
                EncodingDictionary localEncodings = this.encodings;

                if (localEncodings != null)
                    foreach (KeyValuePair<string, Encoding> pair in localEncodings)
                        encodings[pair.Key] = pair.Value;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode GetEncoding(
            Interpreter interpreter,
            string name,
            LookupFlags lookupFlags,
            ref Encoding encoding,
            ref Result error
            )
        {
            if (interpreter != null)
            {
                if (name != null)
                {
                    try
                    {
                        EncodingDictionary encodings = interpreter.Encodings;

                        if ((encodings == null) ||
                            (!encodings.TryGetValue(name, out encoding)))
                        {
                            //
                            // NOTE: Either our encodings are not available or we failed to
                            //       find the one they specified in our collection.  Try to
                            //       fallback to the .NET Framework encoding matching their
                            //       specified name.
                            //
                            encoding = Encoding.GetEncoding(name);
                        }

                        return ReturnCode.Ok;
                    }
                    catch (Exception e)
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            e : (Result)"invalid encoding";
                    }
                }
                else
                {
                    encoding = null;

                    return ReturnCode.Ok;
                }
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        #region Hidden ICommand
        internal ReturnCode HiddenCommandsToList(
            CommandFlags hasFlags,
            CommandFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            ref StringList list,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (hiddenCommands != null)
                {
                    return hiddenCommands.ToList(
                        hasFlags, notHasFlags, hasAll, notHasAll,
                        pattern, noCase, ref list, ref error);
                }
            }

            error = "hidden commands not available";
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasHiddenCommands()
        {
            Result error = null;

            return HasHiddenCommands(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasHiddenCommands(ref Result error)
        {
            /* CheckDisposed(); */

            bool result = (hiddenCommands != null);

            if (!result)
                error = "hidden commands not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenCommand(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ICommand command,
            ref Result error
            )
        {
            if (!HasHiddenCommands(ref error))
                return ReturnCode.Error;

            _Wrappers.Command wrapper;

            if (!hiddenCommands.TryGetValue(token, out wrapper))
            {
                error = "hidden command not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                command = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid hidden command wrapper";
                    return ReturnCode.Error;
                }

                command = wrapper.command;
                name = EntityOps.GetName(command);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenCommand(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            if (!HasHiddenCommands(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid hidden command name";
                return ReturnCode.Error;
            }

            _Wrappers.Command wrapper;

            if (!hiddenCommands.TryGetValue(name, out wrapper))
            {
                error = "hidden command not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                command = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid command wrapper";
                    return ReturnCode.Error;
                }

                command = wrapper.command;
                token = EntityOps.GetToken(command);

                if ((command == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden command";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenCommand(
            long token,
            LookupFlags lookupFlags,
            ref ICommand command
            )
        {
            Result error = null;

            return GetHiddenCommand(token, lookupFlags, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenCommand(
            long token,
            LookupFlags lookupFlags,
            ref ICommand command,
            ref Result error
            )
        {
            string name = null;

            return GetHiddenCommand(token, lookupFlags, ref name, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenCommand(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ICommand command,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetHiddenCommand(
                        token, lookupFlags, ref name, ref command,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden command token \"{0}\"",
                            token) :
                        "invalid hidden command token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetHiddenCommand(
            string name,
            LookupFlags lookupFlags,
            ref ICommand command
            )
        {
            Result error = null;

            return GetHiddenCommand(name, lookupFlags, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenCommand(
            string name,
            LookupFlags lookupFlags,
            ref ICommand command,
            ref Result error
            )
        {
            long token = 0;

            return GetHiddenCommand(name, lookupFlags, ref token, ref command, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenCommand(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ICommand command,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetHiddenCommand(
                        name, lookupFlags, ref token, ref command,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden command name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid hidden command name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Hidden IProcedure
        internal ReturnCode HiddenProceduresToList(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            ref StringList list,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (hiddenProcedures != null)
                {
                    return hiddenProcedures.ToList(
                        hasFlags, notHasFlags, hasAll, notHasAll,
                        pattern, noCase, ref list, ref error);
                }
            }

            error = "hidden procedures not available";
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasHiddenProcedures(ref Result error)
        {
            /* CheckDisposed(); */

            bool result = (hiddenProcedures != null);

            if (!result)
                error = "hidden procedures not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenProcedure(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IProcedure procedure,
            ref Result error
            )
        {
            if (!HasHiddenProcedures(ref error))
                return ReturnCode.Error;

            _Wrappers.Procedure wrapper;

            if (!hiddenProcedures.TryGetValue(token, out wrapper))
            {
                error = "hidden procedure not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                procedure = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid hidden procedure wrapper";
                    return ReturnCode.Error;
                }

                procedure = wrapper.procedure;
                name = EntityOps.GetName(procedure);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenProcedure(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IProcedure procedure,
            ref Result error
            )
        {
            if (!HasHiddenProcedures(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid hidden procedure name";
                return ReturnCode.Error;
            }

            _Wrappers.Procedure wrapper;

            if (!hiddenProcedures.TryGetValue(name, out wrapper))
            {
                error = "hidden procedure not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                procedure = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid hidden procedure wrapper";
                    return ReturnCode.Error;
                }

                procedure = wrapper.procedure;
                token = EntityOps.GetToken(procedure);

                if ((procedure == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden procedure";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenProcedure(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IProcedure procedure,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetHiddenProcedure(
                        token, lookupFlags, ref name, ref procedure,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden procedure token \"{0}\"",
                            token) :
                        "invalid hidden procedure token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetHiddenProcedure(
            string name,
            LookupFlags lookupFlags,
            ref IProcedure procedure
            )
        {
            Result error = null;

            return GetHiddenProcedure(name, lookupFlags, ref procedure, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenProcedure(
            string name,
            LookupFlags lookupFlags,
            ref IProcedure procedure,
            ref Result error
            )
        {
            long token = 0;

            return GetHiddenProcedure(name, lookupFlags, ref token, ref procedure, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenProcedure(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IProcedure procedure,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetHiddenProcedure(
                        name, lookupFlags, ref token, ref procedure,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden procedure name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid hidden procedure name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Hidden IExecute
        private bool HasHiddenIExecutes(ref Result error)
        {
            /* CheckDisposed(); */

            bool result = (hiddenExecutes != null);

            if (!result)
                error = "hidden executes not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenIExecute(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IExecute execute,
            ref Result error
            )
        {
            if (!HasHiddenIExecutes(ref error))
                return ReturnCode.Error;

            _Wrappers._Execute wrapper;

            if (!hiddenExecutes.TryGetValue(token, out wrapper))
            {
                error = "hidden execute not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                execute = wrapper;
                name = EntityOps.GetName(execute as IIdentifier);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid hidden execute wrapper";
                    return ReturnCode.Error;
                }

                execute = wrapper.execute;
                name = EntityOps.GetName(execute as IIdentifier);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetHiddenIExecute(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            if (!HasHiddenIExecutes(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid hidden execute name";
                return ReturnCode.Error;
            }

            _Wrappers._Execute wrapper;

            if (!hiddenExecutes.TryGetValue(name, out wrapper))
            {
                error = "hidden execute not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                execute = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid hidden execute wrapper";
                    return ReturnCode.Error;
                }

                execute = wrapper.execute;

                //
                // WARNING: Cannot grab the token from the IExecute here
                //          because that interface does not inherit from
                //          IWrapperData.
                //
                token = EntityOps.GetToken(wrapper);

                if ((execute == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid hidden execute";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenIExecute(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IExecute execute,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetHiddenIExecute(
                        token, lookupFlags, ref name, ref execute,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden execute token \"{0}\"",
                            token) :
                        "invalid hidden execute token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetHiddenIExecute(
            string name,
            LookupFlags lookupFlags,
            ref IExecute execute
            )
        {
            Result error = null;

            return GetHiddenIExecute(name, lookupFlags, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenIExecute(
            string name,
            LookupFlags lookupFlags,
            ref IExecute execute,
            ref Result error
            )
        {
            long token = 0;

            return GetHiddenIExecute(name, lookupFlags, ref token, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetHiddenIExecute(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetHiddenIExecute(
                        name, lookupFlags, ref token, ref execute,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid hidden execute name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid hidden execute name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ILambda
        #region Dead Code
#if DEAD_CODE
        internal ReturnCode LambdasToList(
            ProcedureFlags hasFlags,
            ProcedureFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            ref StringList list,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (lambdas != null)
                {
                    return lambdas.ToList(
                        hasFlags, notHasFlags, hasAll, notHasAll,
                        pattern, noCase, ref list, ref error);
                }
            }

            error = "lambdas not available";
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasLambdas(ref Result error)
        {
            /* CheckDisposed(); */

            bool result = (lambdas != null);

            if (!result)
                error = "lambdas not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetLambda(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ILambda lambda,
            ref Result error
            )
        {
            if (!HasLambdas(ref error))
                return ReturnCode.Error;

            _Wrappers.Lambda wrapper;

            if (!lambdas.TryGetValue(token, out wrapper))
            {
                error = "lambda not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                lambda = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((lambda == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid lambda";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid lambda wrapper";
                    return ReturnCode.Error;
                }

                lambda = wrapper.lambda;
                name = EntityOps.GetName(lambda);

                if ((lambda == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid lambda";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetLambda(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ILambda lambda,
            ref Result error
            )
        {
            if (!HasLambdas(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid lambda name";
                return ReturnCode.Error;
            }

            _Wrappers.Lambda wrapper;

            if (!lambdas.TryGetValue(name, out wrapper))
            {
                error = "lambda not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                lambda = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((lambda == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid lambda";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid lambda wrapper";
                    return ReturnCode.Error;
                }

                lambda = wrapper.lambda;
                token = EntityOps.GetToken(lambda);

                if ((lambda == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid lambda";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetLambda(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref ILambda lambda,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetLambda(
                        token, lookupFlags, ref name, ref lambda,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid lambda token \"{0}\"",
                            token) :
                        "invalid lambda token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetLambda(
            string name,
            LookupFlags lookupFlags,
            ref ILambda lambda
            )
        {
            Result error = null;

            return GetLambda(name, lookupFlags, ref lambda, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetLambda(
            string name,
            LookupFlags lookupFlags,
            ref ILambda lambda,
            ref Result error
            )
        {
            long token = 0;

            return GetLambda(name, lookupFlags, ref token, ref lambda, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetLambda(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref ILambda lambda,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (syncRoot)
            {
                if (PrivateGetLambda(
                        name, lookupFlags, ref token, ref lambda,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid lambda name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid lambda name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IOperator
        private ReturnCode PrivateGetOperator(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IOperator @operator,
            ref Result error
            )
        {
            if (!HasOperators(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid operator name";
                return ReturnCode.Error;
            }

            _Wrappers.Operator wrapper;

            if (!operators.TryGetValue(name, out wrapper))
            {
                error = "operator not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @operator = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((@operator == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid operator";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid operator wrapper";
                    return ReturnCode.Error;
                }

                @operator = wrapper.@operator;
                token = EntityOps.GetToken(@operator);

                if ((@operator == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid operator";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetOperator(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IOperator @operator,
            ref Result error
            )
        {
            if (!HasOperators(ref error))
                return ReturnCode.Error;

            _Wrappers.Operator wrapper;

            if (!operators.TryGetValue(token, out wrapper))
            {
                error = "operator not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @operator = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((@operator == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid operator";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid operator wrapper";
                    return ReturnCode.Error;
                }

                @operator = wrapper.@operator;
                name = EntityOps.GetName(@operator);

                if ((@operator == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid operator";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetOperator(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IOperator @operator,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetOperator(
                        token, lookupFlags, ref name, ref @operator,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid operator token \"{0}\"",
                            token) :
                        "invalid operator token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetOperator(
            string name,
            LookupFlags lookupFlags,
            ref IOperator @operator
            )
        {
            Result error = null;

            return GetOperator(name, lookupFlags, ref @operator, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetOperator(
            string name,
            LookupFlags lookupFlags,
            ref IOperator @operator,
            ref Result error
            )
        {
            long token = 0;

            return GetOperator(name, lookupFlags, ref token, ref @operator, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetOperator(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IOperator @operator,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetOperator(
                        name, lookupFlags, ref token, ref @operator,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid operator name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid operator name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListOperators(
            OperatorFlags hasFlags,
            OperatorFlags notHasFlags,
            bool hasAll,
            bool notHasAll,
            string pattern,
            bool noCase,
            bool strict,
            ref StringList list,
            ref Result error
            )
        {
            // CheckDisposed();

            ReturnCode code = ReturnCode.Error;

            lock (syncRoot)
            {
                Result localError = null;

                if (HasOperators(ref localError))
                {
                    code = operators.ToList(
                        hasFlags, notHasFlags, hasAll, notHasAll,
                        pattern, noCase, ref list, ref error);
                }
                else if (strict)
                {
                    error = localError;
                }
                else
                {
                    if (list == null)
                        list = new StringList();

                    code = ReturnCode.Ok;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOperator(
            Type type,
            string name,
            Lexeme lexeme,
            TypeList types,
            OperatorFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref Result result
            )
        {
            long token = 0;

            return AddOperator(
                type, name, lexeme, types, flags, plugin,
                clientData, strict, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOperator(
            Type type,
            string name,
            Lexeme lexeme,
            TypeList types,
            OperatorFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref long token,
            ref Result result
            )
        {
            return AddOperator(
                type, name, lexeme, (int)Arity.Automatic, types,
                flags, plugin, clientData, strict, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOperator(
            Type type,
            string name,
            Lexeme lexeme,
            int operands,
            TypeList types,
            OperatorFlags flags,
            IPlugin plugin,
            IClientData clientData,
            bool strict,
            ref long token,
            ref Result result
            )
        {
            // CheckDisposed(); /* NOTE: This API may be public someday. */

            if (type == null)
                type = Type.GetType(
                    FormatOps.OperatorTypeName(name), false, true);

            if (type == null)
                type = Type.GetType(FormatOps.OperatorTypeName(
                    Characters.Underscore + name), false, true);

            if (type != null)
            {
                OperatorFlags operatorFlags =
                    AttributeOps.GetOperatorFlags(type) | flags;

                //
                // NOTE: Is this interpreter marked as "standard"?
                //
                bool createStandard = FlagOps.HasFlags(createFlags,
                    CreateFlags.Standard, true);

                //
                // NOTE: Check if this operator is part of the "Tcl Standard"
                //       (i.e. it is largely (or completely) compatible with
                //       an identically named operator from Tcl/Tk 8.4, 8.5,
                //       and/or 8.6).
                //
                bool standard = FlagOps.HasFlags(
                    operatorFlags, OperatorFlags.Standard, true);

                //
                // NOTE: If the interpreter is "standard", make sure we only
                //       add operators that are marked as "standard" and NOT
                //       marked as "non-standard" unless we are merely hiding
                //       operators not considered to be "standard".  In that
                //       case, we add all operators, hidden them as necessary.
                //
                if (standard || !createStandard)
                {
                    try
                    {
                        if (operands == (int)Arity.Automatic)
                            operands = AttributeOps.GetOperands(type);

                        object[] args = {
                            new OperatorData(
                                name, null, null, lexeme, operands,
                                types, flags, clientData, plugin, 0)
                        };

                        IOperator @operator =
                            (IOperator)Activator.CreateInstance(type, args);

                        return AddOperator(
                            @operator, null, ref token, ref result);
                    }
                    catch (Exception e)
                    {
                        result = e;
                    }
                }
                else if (strict)
                {
                    result = "cannot add non-standard operator to standard interpreter";
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                result = String.Format(
                    "operator \"{0}\" not found",
                    FormatOps.OperatorTypeName(name));
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddOperator(
            IOperator @operator,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (@operator == null)
                {
                    result = "invalid operator";
                    return ReturnCode.Error;
                }

                if (@operator.Name == null)
                {
                    result = "invalid operator name";
                    return ReturnCode.Error;
                }

                if (!HasOperators(ref result))
                    return ReturnCode.Error;

                if (DoesOperatorExist(@operator.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": operator already exists",
                        @operator.Name);

                    return ReturnCode.Error;
                }

                //
                // HACK: Due to how the expression parser works, we cannot allow an
                //       operator to be added that has the name of an existing
                //       function.
                //
                if (DoesFunctionExist(@operator.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": function already exists",
                        @operator.Name);

                    return ReturnCode.Error;
                }

#if false
                //
                // HACK: This is part of an ugly hack to add "tcl::mathfunc::*" and
                //       "tcl::mathop::*" support for [expr] functions and operators
                //       to Eagle, respectively.
                //
                if (AreNamespacesEnabled())
                {
                    INamespace @namespace = NamespaceOps.Lookup(
                        this, TclVars.MathOperatorNamespaceName, true, true,
                        ref result);

                    if (@namespace == null)
                        return ReturnCode.Error;

                    IExecute execute = @operator as IExecute;
                    long token2 = 0;

                    if ((execute != null) && AddIExecute(
                            NamespaceOps.MakeQualifiedName(this, @namespace,
                            @operator.Name), execute, clientData, ref token2,
                            ref result) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }
                }
                else
                {
                    IExecute execute = @operator as IExecute;
                    long token2 = 0;

                    if ((execute != null) && AddIExecute(NamespaceOps.MakeName(
                            TclVars.MathOperatorNamespaceName, @operator.Name,
                            true, false), execute, clientData, ref token2,
                            ref result) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }
                }
#endif

                ReturnCode code = ReturnCode.Ok;

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    try
                    {
                        code = @operator.Initialize(this,
                            (clientData != null) ? clientData : @operator.ClientData,
                            ref result);
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while initializing operator: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                }
                finally
                {
                    if (code != ReturnCode.Ok)
                    {
                        bool savedImmutable = BeginMutableExecution();

                        ReturnCode terminateCode;
                        Result terminateResult = null;

                        try
                        {
                            terminateCode = @operator.Terminate(this,
                                (clientData != null) ? clientData : @operator.ClientData,
                                ref terminateResult);
                        }
                        catch (Exception e)
                        {
                            terminateResult = String.Format(
                                "caught exception while terminating operator: {0}",
                                e);

                            terminateCode = ReturnCode.Error;
                        }
                        finally
                        {
                            EndMutableExecution(savedImmutable);
                        }

                        if (terminateCode != ReturnCode.Ok)
                            DebugOps.Complain(this, terminateCode, terminateResult);
                    }
                }

                if (code != ReturnCode.Ok)
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                    return code;
                }

                long id = NextId();
                _Wrappers.Operator operatorWrapper = new _Wrappers.Operator(id, @operator);

                operators.Add(@operator.Name, operatorWrapper);
                token = EntityOps.GetToken(operatorWrapper);
                EntityOps.SetToken(@operator, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Operator, NotifyFlags.Added,
                    new ObjectPair(@operator, token), this,
                    clientData, null, null, ref result);
#endif

                /* IGNORED */
                GlobalState.PopActiveInterpreter();
                return code;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IModule
#if NATIVE && LIBRARY
        internal string ModulesToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (modules != null)
                    return modules.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetModule(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IModule module,
            ref Result error
            )
        {
            if (!HasModules(ref error))
                return ReturnCode.Error;

            _Wrappers._Module wrapper;

            if (!modules.TryGetValue(token, out wrapper))
            {
                error = "module not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                module = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((module == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid module";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid module wrapper";
                    return ReturnCode.Error;
                }

                module = wrapper.module;
                name = EntityOps.GetName(module);

                if ((module == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid module";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetModule(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IModule module,
            ref Result error
            )
        {
            if (!HasModules(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid module name";
                return ReturnCode.Error;
            }

            _Wrappers._Module wrapper;

            if (!modules.TryGetValue(name, out wrapper))
            {
                error = "module not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                module = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((module == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid module";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid module wrapper";
                    return ReturnCode.Error;
                }

                module = wrapper.module;
                token = EntityOps.GetToken(module);

                if ((module == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid module";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetModule(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IModule module,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetModule(
                        token, lookupFlags, ref name, ref module,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid module token \"{0}\"",
                            token) :
                        "invalid module token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetModule(
            string name,
            LookupFlags lookupFlags,
            ref IModule module,
            ref Result error
            )
        {
            long token = 0;

            return GetModule(name, lookupFlags, ref token, ref module, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetModule(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IModule module,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetModule(
                        name, lookupFlags, ref token, ref module,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid module name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid module name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddModule(
            IModule module,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddModule(module, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddModule(
            IModule module,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (module == null)
                {
                    result = "invalid module";
                    return ReturnCode.Error;
                }

                if (module.Name == null)
                {
                    result = "invalid module name";
                    return ReturnCode.Error;
                }

                if (!HasModules(ref result))
                    return ReturnCode.Error;

                if (DoesModuleExist(module.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": module already exists",
                        module.Name);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers._Module moduleWrapper = new _Wrappers._Module(id, module);

                modules.Add(module.Name, moduleWrapper);
                token = EntityOps.GetToken(moduleWrapper);
                EntityOps.SetToken(module, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Module, NotifyFlags.Added,
                    new ObjectPair(module, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveModule(
            string name,
            long token,
            IModule module,
            IClientData clientData,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            if (dispose)
            {
                if (module != null)
                {
                    if (!FlagOps.HasFlags(module.Flags, ModuleFlags.Locked, true))
                    {
                        GlobalState.PushActiveInterpreter(this);

                        try
                        {
                            if (ObjectOps.TryDispose(module,
                                    ref dispose, ref result) == ReturnCode.Ok)
                            {
                                module = null;

                                if (synchronous)
                                    ObjectOps.CollectGarbage(); /* throw */
                            }
                            else
                            {
                                return ReturnCode.Error;
                            }
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing module: {0}",
                                e);

                            return ReturnCode.Error;
                        }
                        finally
                        {
                            /* IGNORED */
                            GlobalState.PopActiveInterpreter();
                        }
                    }
                    else
                    {
                        result = "cannot dispose or remove a locked module";

                        return ReturnCode.Error;
                    }
                }
            }

            modules.Remove(name, token);

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Module, NotifyFlags.Removed,
                new ObjectTriplet(module, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveModule(
            string name,
            IClientData clientData /* NOT USED */,
            bool synchronous,
            ref Result result
            )
        {
            bool dispose = true;

            return RemoveModule(name, clientData, synchronous, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveModule(
            string name,
            IClientData clientData /* NOT USED */,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasModules(ref result))
                {
                    long token = 0;
                    IModule module = null;

                    if (GetModule(name, LookupFlags.Remove, ref token,
                            ref module, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveModule(
                            name, token, module, clientData, synchronous,
                            ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveModule(
            long token,
            IClientData clientData, /* NOT USED */
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasModules(ref result))
                {
                    string name = null;
                    IModule module = null;

                    if (GetModule(token, LookupFlags.Remove, ref name,
                            ref module, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveModule(
                            name, token, module, clientData, synchronous,
                            ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDelegate
#if NATIVE && LIBRARY
        internal string DelegatesToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (delegates != null)
                    return delegates.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetDelegate(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetDelegate(
                        token, lookupFlags, ref name, ref @delegate,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid delegate token \"{0}\"",
                            token) :
                        "invalid delegate token";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetDelegate(
            long token,
            LookupFlags lookupFlags,
            ref string name,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            if (!HasDelegates(ref error))
                return ReturnCode.Error;

            _Wrappers.Delegate wrapper;

            if (!delegates.TryGetValue(token, out wrapper))
            {
                error = "delegate not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @delegate = wrapper;
                name = EntityOps.GetName(wrapper);

                if ((@delegate == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid delegate";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid delegate wrapper";
                    return ReturnCode.Error;
                }

                @delegate = wrapper.@delegate;
                name = EntityOps.GetName(@delegate);

                if ((@delegate == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid delegate";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetDelegate(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            if (!HasDelegates(ref error))
                return ReturnCode.Error;

            if (name == null)
            {
                error = "invalid delegate name";
                return ReturnCode.Error;
            }

            _Wrappers.Delegate wrapper;

            if (!delegates.TryGetValue(name, out wrapper))
            {
                error = "delegate not found";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                @delegate = wrapper;
                token = EntityOps.GetToken(wrapper);

                if ((@delegate == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid delegate";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                if (wrapper == null)
                {
                    error = "invalid delegate wrapper";
                    return ReturnCode.Error;
                }

                @delegate = wrapper.@delegate;
                token = EntityOps.GetToken(@delegate);

                if ((@delegate == null) &&
                    FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                {
                    error = "invalid delegate";
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetDelegate(
            string name,
            LookupFlags lookupFlags,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            long token = 0;

            return GetDelegate(name, lookupFlags, ref token, ref @delegate, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetDelegate(
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot)
            {
                if (PrivateGetDelegate(
                        name, lookupFlags, ref token, ref @delegate,
                        ref error) != ReturnCode.Ok)
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "invalid delegate name \"{0}\"",
                            FormatOps.DisplayName(name)) :
                        "invalid delegate name";

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddDelegate(
            IDelegate @delegate,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return AddDelegate(@delegate, clientData, ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddDelegate(
            IDelegate @delegate,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (@delegate == null)
                {
                    result = "invalid delegate";
                    return ReturnCode.Error;
                }

                if (@delegate.Name == null)
                {
                    result = "invalid delegate name";
                    return ReturnCode.Error;
                }

                if (!HasDelegates(ref result))
                    return ReturnCode.Error;

                if (DoesDelegateExist(@delegate.Name) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": delegate already exists",
                        @delegate.Name);

                    return ReturnCode.Error;
                }

                long id = NextId();
                _Wrappers.Delegate delegateWrapper = new _Wrappers.Delegate(id, @delegate);

                delegates.Add(@delegate.Name, delegateWrapper);
                token = EntityOps.GetToken(delegateWrapper);
                EntityOps.SetToken(@delegate, token);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Delegate, NotifyFlags.Added,
                    new ObjectPair(@delegate, token), this,
                    clientData, null, null, ref result);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateRemoveDelegate(
            string name,
            long token,
            IDelegate @delegate,
            IClientData clientData,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            if (name == null)
            {
                result = "invalid delegate name";
                return ReturnCode.Error;
            }

            if (dispose)
            {
                if (@delegate != null)
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
                        if (ObjectOps.TryDispose(@delegate,
                                ref dispose, ref result) == ReturnCode.Ok)
                        {
                            @delegate = null;

                            if (synchronous)
                                ObjectOps.CollectGarbage(); /* throw */
                        }
                        else
                        {
                            return ReturnCode.Error;
                        }
                    }
                    catch (Exception e)
                    {
                        result = String.Format(
                            "caught exception while disposing delegate: {0}",
                            e);

                        return ReturnCode.Error;
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
            }

            delegates.Remove(name, token);

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Delegate, NotifyFlags.Removed,
                new ObjectTriplet(@delegate, name, token), this,
                clientData, null, null, ref result);
#endif

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveDelegate(
            string name,
            IClientData clientData /* NOT USED */,
            bool synchronous,
            ref Result result
            )
        {
            bool dispose = true;

            return RemoveDelegate(name, clientData, synchronous, ref dispose, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveDelegate(
            string name,
            IClientData clientData /* NOT USED */,
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasDelegates(ref result))
                {
                    long token = 0;
                    IDelegate @delegate = null;

                    if (GetDelegate(name, LookupFlags.Remove, ref token,
                            ref @delegate, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveDelegate(
                            name, token, @delegate, clientData, synchronous,
                            ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveDelegate(
            long token,
            IClientData clientData, /* NOT USED */
            bool synchronous,
            ref bool dispose,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                if (HasDelegates(ref result))
                {
                    string name = null;
                    IDelegate @delegate = null;

                    if (GetDelegate(token, LookupFlags.Remove, ref name,
                            ref @delegate, ref result) == ReturnCode.Ok)
                    {
                        return PrivateRemoveDelegate(
                            name, token, @delegate, clientData, synchronous,
                            ref dispose, ref result);
                    }
                }
            }

            return ReturnCode.Error;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Channel
        internal bool HasChannels()
        {
            Result error = null;

            return HasChannels(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private Channel GetChannel(string name)
        {
            Result error = null;

            return GetChannel(name, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal Channel GetChannel(
            string name,
            ref Result error
            )
        {
            Channel result = null;

            if (name != null)
            {
                lock (syncRoot)
                {
                    if (channels != null)
                    {
                        if (channels.TryGetValue(name, out result))
                        {
                            if (result == null)
                                error = "invalid channel";
                        }
                        else
                        {
                            error = String.Format(
                                "can not find channel named \"{0}\"",
                                name);
                        }
                    }
                    else
                    {
                        error = "no channels available";
                    }
                }
            }
            else
            {
                error = "invalid channel name";
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetChannelEncoding(
            string name,
            ref Encoding encoding
            )
        {
            Channel channel = GetChannel(name);

            if (channel != null)
            {
                encoding = channel.GetEncoding();

                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal Stream GetChannelStream(string name)
        {
            Stream result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.GetStream();

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Reader & Writer
        internal BinaryReader GetChannelBinaryReader(string name)
        {
            BinaryReader result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.GetBinaryReader();

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal BinaryWriter GetChannelBinaryWriter(string name)
        {
            BinaryWriter result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.GetBinaryWriter();

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal TextReader GetChannelTextReader(string name)
        {
            TextReader result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.GetStreamReader();

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal TextWriter GetChannelTextWriter(string name)
        {
            TextWriter result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.GetStreamWriter();

            return result;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Virtual Output
        internal StringBuilder GetChannelVirtualOutput(string name)
        {
            StringBuilder result = null;
            Channel channel = GetChannel(name);

            if (channel != null)
                result = channel.VirtualOutput;

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetChannelVirtualOutput(
            string name,
            ref Result result
            )
        {
            Channel channel = GetChannel(name, ref result);

            if (channel != null)
            {
                if (channel.VirtualOutput != null)
                {
                    result = channel.VirtualOutput;

                    return ReturnCode.Ok;
                }

                result = String.Format(
                    "virtual output is not enabled for channel named \"{0}\"",
                    name);
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetChannelVirtualOutput(
            string name,
            bool enable,
            ref Result result
            )
        {
            Channel channel = GetChannel(name, ref result);

            if (channel != null)
            {
                if (enable)
                    channel.VirtualOutput = StringOps.NewStringBuilder();
                else
                    channel.VirtualOutput = null;

                result = String.Format(
                    "virtual output {0} for channel \"{1}\"",
                    ConversionOps.ToEnabled(enable), name);

                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Adding Channels
        internal ReturnCode AddFileOrSocketChannel(
            string name,
            Stream stream,
            OptionDictionary options,
            StreamFlags flags,
            bool appendMode,
            bool autoFlush,
            IClientData clientData,
            ref Result error
            )
        {
            return AddChannel(
                name, ChannelType.None, stream, options, flags, StreamTranslation.auto,
                StreamTranslation.auto, Channel.DefaultEncoding, appendMode, autoFlush,
                clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NETWORK
        private ReturnCode AddTcpListenerChannel(
            string name,
            ChannelType channelType,
            TcpListener listener,
            SocketClientData clientData,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                string channelId = RuntimeOps.ChannelTypeToName(name, channelType);

                if (channelId == null)
                {
                    error = "invalid channel name";
                    return ReturnCode.Error;
                }

                if (!HasChannels(ref error))
                    return ReturnCode.Error;

                if (channels.ContainsKey(channelId))
                {
                    error = String.Format(
                        "can't add \"{0}\": channel already exists",
                        channelId);

                    return ReturnCode.Error;
                }

                OptionDictionary options = (clientData != null) ?
                    clientData.Options : null;

                channels.Add(channelId, new Channel(listener, options,
                    StreamFlags.ListenSocket, clientData));
            }

            return ReturnCode.Ok;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Standard Channels
        internal ReturnCode AddStandardChannels(
            IStreamHost streamHost,
            string name, /* NOTE: Cannot be non-null when adding multiple channels. */
            ChannelType channelType,
            bool replace,
            bool strict,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (channels != null)
                {
                    if (streamHost != null)
                    {
                        //
                        // HACK: For the built-in console host only,
                        //       temporarily disable the throwing of
                        //       exceptions due to the console being
                        //       closed.  This is necessary because
                        //       we need to access several properties
                        //       of the host while [re-]adding the
                        //       standard channels (e.g. from the
                        //       [host reset -channels] sub-command).
                        //       See the test "host-1.1" for details.
                        //
#if CONSOLE
                        bool throwOnMustBeOpen = false;

                        if (streamHost is _Hosts.Console)
                        {
                            _Hosts.Console.ThrowOnMustBeOpen = false;
                            throwOnMustBeOpen = true;
                        }

                        try
                        {
#endif
                            HostFlags hostFlags = streamHost.GetFlags();

                            try
                            {
                                string channelId;
                                bool contains;

                                if (FlagOps.HasFlags(channelType, ChannelType.Input, true))
                                {
                                    channelId = (name != null) ? name : StandardChannel.Input;
                                    contains = channels.ContainsKey(channelId);

                                    if (!contains || replace)
                                    {
                                        //
                                        // HACK: We have no clean way to determine if the stdin stream
                                        //       has additional data to read; therefore, we need to
                                        //       allow any end-of-line character to terminate an input
                                        //       line or we can run into problems on wherever the
                                        //       end-of-line sequence differs.
                                        //
                                        StreamFlags streamFlags = PlatformOps.IsWindowsOperatingSystem() ?
                                            StreamFlags.None : StreamFlags.UseAnyEndOfLineChar;

                                        Channel channel = new Channel(
                                            streamHost.DefaultIn, null, streamFlags, StreamTranslation.auto,
                                            StreamTranslation.auto, streamHost.InputEncoding, false,
                                            false, null);

                                        if (contains)
                                        {
                                            if (channels[channelId] != null)
                                                channels[channelId].Dispose();

                                            channels[channelId] = channel;
                                        }
                                        else
                                        {
                                            channels.Add(channelId, channel);
                                        }
                                    }
                                    else if (strict)
                                    {
                                        error = String.Format(
                                            "can't add \"{0}\": channel already exists",
                                            channelId);

                                        return ReturnCode.Error;
                                    }
                                }

                                if (FlagOps.HasFlags(channelType, ChannelType.Output, true))
                                {
                                    channelId = (name != null) ? name : StandardChannel.Output;
                                    contains = channels.ContainsKey(channelId);

                                    if (!contains || replace)
                                    {
                                        Channel channel = new Channel(
                                            streamHost.DefaultOut, null, StreamFlags.None, StreamTranslation.auto,
                                            StreamTranslation.auto, streamHost.OutputEncoding, false,
                                            FlagOps.HasFlags(hostFlags, HostFlags.AutoFlushOutput, true), null);

                                        if (contains)
                                        {
                                            if (channels[channelId] != null)
                                                channels[channelId].Dispose();

                                            channels[channelId] = channel;
                                        }
                                        else
                                        {
                                            channels.Add(channelId, channel);
                                        }
                                    }
                                    else if (strict)
                                    {
                                        error = String.Format(
                                            "can't add \"{0}\": channel already exists",
                                            channelId);

                                        return ReturnCode.Error;
                                    }
                                }

                                if (FlagOps.HasFlags(channelType, ChannelType.Error, true))
                                {
                                    channelId = (name != null) ? name : StandardChannel.Error;
                                    contains = channels.ContainsKey(channelId);

                                    if (!contains || replace)
                                    {
                                        Channel channel = new Channel(
                                            streamHost.DefaultError, null, StreamFlags.None, StreamTranslation.auto,
                                            StreamTranslation.auto, streamHost.ErrorEncoding, false,
                                            FlagOps.HasFlags(hostFlags, HostFlags.AutoFlushError, true), null);

                                        if (contains)
                                        {
                                            if (channels[channelId] != null)
                                                channels[channelId].Dispose();

                                            channels[channelId] = channel;
                                        }
                                        else
                                        {
                                            channels.Add(channelId, channel);
                                        }
                                    }
                                    else if (strict)
                                    {
                                        error = String.Format(
                                            "can't add \"{0}\": channel already exists",
                                            channelId);

                                        return ReturnCode.Error;
                                    }
                                }

                                return ReturnCode.Ok;
                            }
                            catch (Exception e)
                            {
                                error = e;
                            }
#if CONSOLE
                        }
                        finally
                        {
                            if (throwOnMustBeOpen)
                            {
                                _Hosts.Console.ThrowOnMustBeOpen = true;
                                throwOnMustBeOpen = false;
                            }
                        }
#endif
                    }
                    else
                    {
                        error = "interpreter host not available";
                    }
                }
                else
                {
                    error = "no channels available";
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region AppDomain
#if APPDOMAINS
        private ReturnCode AddAppDomain(
            string friendlyName,
            string packagePath,
#if CAS_POLICY
            Evidence evidence,
#endif
            IClientData clientData,
            bool useBasePath,
            ref AppDomain appDomain,
            ref Result error
            )
        {
            //
            // NOTE: *WARNING* Empty application domain names are allowed,
            //       please do not change this to "!String.IsNullOrEmpty".
            //
            if (friendlyName != null)
            {
                lock (syncRoot)
                {
                    if (appDomains != null)
                    {
                        if (AppDomainOps.Create(
                                this, friendlyName, packagePath,
#if CAS_POLICY
                                evidence,
#endif
                                clientData, useBasePath, ref appDomain,
                                ref error) == ReturnCode.Ok)
                        {
                            appDomains.Add(friendlyName, appDomain);

#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.AppDomain, NotifyFlags.Added,
                                new ObjectPair(friendlyName, appDomain), this,
                                clientData, null, null, ref error);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        error = "application domains not available";
                    }
                }
            }
            else
            {
                error = "invalid friendly name";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveAppDomain(
            string friendlyName,
            IClientData clientData,
            ref Result error
            )
        {
            //
            // NOTE: *WARNING* Empty application domain names are allowed,
            //       please do not change this to "!String.IsNullOrEmpty".
            //
            if (friendlyName != null)
            {
                lock (syncRoot)
                {
                    if (appDomains != null)
                    {
                        AppDomain appDomain;

                        if (appDomains.TryGetValue(friendlyName, out appDomain))
                        {
                            if (AppDomainOps.Unload(appDomain,
                                    clientData, ref error) == ReturnCode.Ok)
                            {
                                appDomains.Remove(friendlyName);

#if NOTIFY
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.AppDomain, NotifyFlags.Removed,
                                    new ObjectPair(friendlyName, appDomain), this,
                                    clientData, null, null, ref error);
#endif

                                return ReturnCode.Ok;
                            }
                        }
                        else
                        {
                            error = String.Format(
                                "invalid application domain name \"{0}\"",
                                FormatOps.DisplayName(friendlyName));
                        }
                    }
                    else
                    {
                        error = "application domains not available";
                    }
                }
            }
            else
            {
                error = "invalid friendly name";
            }

            return ReturnCode.Error;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region CLR Integration
        //
        // NOTE: For System.Type short-name to long-name lookups (i.e. TypeDefs).
        //
        internal StringDictionary ObjectTypes
        {
            get
            {
                lock (syncRoot)
                {
                    return objectTypes;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For System.Type objects, not related to Tcl namespaces.
        //
        internal StringDictionary ObjectNamespaces
        {
            get
            {
                lock (syncRoot)
                {
                    return objectNamespaces;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For COM interop assemblies, we keep track of interfaces.
        //
        internal TypePairDictionary<string, long> ObjectInterfaces
        {
            get
            {
                lock (syncRoot)
                {
                    return objectInterfaces;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Keep track of the namespaces that should be used for aliased
        //       object commands that use types from a particular assembly.
        //
        internal StringDictionary ObjectAliasNamespaces
        {
            get
            {
                lock (syncRoot)
                {
                    return objectAliasNamespaces;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasObjectTypes(ref Result error)
        {
            bool result = (objectTypes != null);

            if (!result)
                error = "object types not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasObjectNamespaces(ref Result error)
        {
            bool result = (objectNamespaces != null);

            if (!result)
                error = "object namespaces not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasObjectInterfaces(ref Result error)
        {
            bool result = (objectInterfaces != null);

            if (!result)
                error = "interfaces not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasObjectAliasNamespaces(ref Result error)
        {
            bool result = (objectAliasNamespaces != null);

            if (!result)
                error = "alias namespaces not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectTypes(
            StringList list,
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                //
                // HACK: Potentially modifies object types instead of purely
                //       adding.
                //
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasObjectTypes(ref error))
                {
                    if (list != null)
                    {
                        if ((list.Count % 2) == 0)
                        {
                            for (int index = 0; index < list.Count; index += 2)
                            {
                                string key = list[index];

                                if (key != null) // empty string allowed.
                                {
                                    string value = list[index + 1];

                                    if ((mode == MatchMode.None) ||
                                        StringOps.Match(this, mode, key, pattern, noCase))
                                    {
                                        objectTypes[key] = value;
                                    }
                                }
                            }

                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = "type list must have an even number of elements";
                        }
                    }
                    else
                    {
                        error = "invalid type list";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjectTypes(
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasObjectTypes(ref error))
                {
                    StringList keys = new StringList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the types dictionary in the containing interpreter.
                    //
                    foreach (KeyValuePair<string, string> pair in objectTypes)
                    {
                        string type = pair.Key;

                        if ((mode == MatchMode.None) ||
                            StringOps.Match(this, mode, type, pattern, noCase))
                        {
                            keys.Add(type);
                        }
                    }

                    //
                    // NOTE: Cleanup, PASS #2, and remove all the types we found from
                    //       PASS #1 (above).
                    //
                    foreach (string key in keys)
                        objectTypes.Remove(key);

                    //
                    // NOTE: Ok, we were successful.
                    //
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectNamespaces(
            StringDictionary dictionary,
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (HasObjectNamespaces(ref error))
                {
                    if (dictionary != null)
                    {
                        foreach (KeyValuePair<string, string> pair in dictionary)
                        {
                            string key = pair.Key;

                            if ((mode == MatchMode.None) ||
                                StringOps.Match(this, mode, key, pattern, noCase))
                            {
                                string value = pair.Value;

                                if (!objectNamespaces.ContainsKey(key))
                                    objectNamespaces.Add(key, value);
                            }
                        }

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = "invalid namespace list";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectNamespaces(
            Assembly assembly,
            bool nonPublic,
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (HasObjectNamespaces(ref error))
                {
                    if (assembly != null)
                    {
                        TypeList types = new TypeList(assembly.GetTypes());

                        foreach (Type type in types)
                        {
                            if ((type != null) &&
                                (nonPublic || type.IsPublic) &&
                                !String.IsNullOrEmpty(type.Namespace))
                            {
                                if ((mode == MatchMode.None) ||
                                    StringOps.Match(this, mode, type.Namespace, pattern, noCase))
                                {
                                    if (!objectNamespaces.ContainsKey(type.Namespace))
                                    {
                                        objectNamespaces.Add(type.Namespace,
                                            AssemblyOps.GetFullName(type));
                                    }
                                }
                            }
                        }

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = "invalid assembly";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjectNamespaces(
            MatchMode mode,
            string pattern,
            bool noCase,
            bool values,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasObjectNamespaces(ref error))
                {
                    StringList keys = new StringList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the namespaces collection in the containing interpreter.
                    //
                    foreach (KeyValuePair<string, string> pair in objectNamespaces)
                    {
                        string namespaceName = pair.Key;

                        if (values)
                        {
                            string assemblyName = pair.Value;

                            if ((mode == MatchMode.None) ||
                                StringOps.Match(this, mode, assemblyName, pattern, noCase))
                            {
                                keys.Add(namespaceName);
                            }
                        }
                        else
                        {
                            if ((mode == MatchMode.None) ||
                                StringOps.Match(this, mode, namespaceName, pattern, noCase))
                            {
                                keys.Add(namespaceName);
                            }
                        }
                    }

                    //
                    // NOTE: Cleanup, PASS #2, and remove all the namespaces we found from
                    //       PASS #1 (above).
                    //
                    foreach (string key in keys)
                        objectNamespaces.Remove(key);

                    //
                    // NOTE: Ok, we were successful.
                    //
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectInterfaces(
            TypeList types,
            bool nonPublic,
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (HasObjectInterfaces(ref error))
                {
                    if (types != null)
                    {
                        foreach (Type type in types)
                        {
                            if ((type != null) &&
                                type.IsInterface &&
                                (nonPublic || type.IsPublic))
                            {
                                if ((mode == MatchMode.None) ||
                                    StringOps.Match(this, mode, type.FullName, pattern, noCase))
                                {
                                    if (!objectInterfaces.ContainsKey(type))
                                    {
                                        objectInterfaces.Add(type,
                                            new AnyPair<string, long>(
                                                AssemblyOps.GetFullName(type),
                                                NextId()));
                                    }
                                }
                            }
                        }

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = "invalid interface list";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectInterfaces(
            Assembly assembly,
            bool nonPublic,
            MatchMode mode,
            string pattern,
            bool noCase,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (HasObjectInterfaces(ref error))
                {
                    if (assembly != null)
                    {
                        TypeList types = new TypeList(assembly.GetTypes());

                        return AddObjectInterfaces(
                            types, nonPublic, mode, pattern, noCase, ref error);
                    }
                    else
                    {
                        error = "invalid assembly";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjectInterfaces(
            MatchMode mode,
            string pattern,
            bool noCase,
            bool values,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasObjectInterfaces(ref error))
                {
                    TypeList keys = new TypeList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the interfaces collection in the containing interpreter.
                    //
                    foreach (KeyValuePair<Type, IAnyPair<string, long>> pair in objectInterfaces)
                    {
                        Type @interface = pair.Key;

                        if (@interface != null)
                        {
                            if (values)
                            {
                                IAnyPair<string, long> anyPair = pair.Value;

                                if (anyPair != null)
                                {
                                    string assemblyName = anyPair.X;

                                    if ((mode == MatchMode.None) ||
                                        StringOps.Match(this, mode, assemblyName, pattern, noCase))
                                    {
                                        keys.Add(@interface);
                                    }
                                }
                            }
                            else
                            {
                                if ((mode == MatchMode.None) ||
                                    StringOps.Match(this, mode, @interface.FullName, pattern, noCase))
                                {
                                    keys.Add(@interface);
                                }
                            }
                        }
                    }

                    //
                    // NOTE: Cleanup, PASS #2, and remove all the interfaces we found from
                    //       PASS #1 (above).
                    //
                    foreach (Type key in keys)
                        objectInterfaces.Remove(key);

                    //
                    // NOTE: Ok, we were successful.
                    //
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private string GetObjectAliasName(
            IObject @object,
            string name
            )
        {
            if (@object == null)
                return name;

            object objectValue = @object.Value;

            if (objectValue == null)
                return name;

            Type type = objectValue.GetType();

            return GetObjectAliasName(type, name, name);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string GetObjectAliasName(
            Type type,
            string name,
            string @default
            )
        {
            lock (syncRoot)
            {
                if ((type == null) || String.IsNullOrEmpty(name))
                    return @default;

                if (!AreNamespacesEnabled())
                    return @default;

                Assembly assembly = type.Assembly;

                if (assembly == null)
                    return @default;

                string assemblyName = assembly.FullName;

                if (assemblyName == null)
                    return @default;

                string namespaceName;

                if (!objectAliasNamespaces.TryGetValue(
                        assemblyName, out namespaceName))
                {
                    return @default;
                }

                return NamespaceOps.MakeName(namespaceName, name, true, true);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectAliasNamespace(
            Assembly assembly,
            INamespace @namespace,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (!HasObjectAliasNamespaces(ref error))
                    return ReturnCode.Error;

                if (!AreNamespacesEnabled())
                {
                    error = "namespaces not available";
                    return ReturnCode.Error;
                }

                if (assembly == null)
                {
                    error = "invalid assembly";
                    return ReturnCode.Error;
                }

                if (@namespace == null)
                {
                    error = "invalid namespace";
                    return ReturnCode.Error;
                }

                string assemblyName = assembly.FullName;

                if (assemblyName == null)
                {
                    error = "invalid assembly name";
                    return ReturnCode.Error;
                }

                string namespaceName;

                if (!objectAliasNamespaces.TryGetValue(
                        assemblyName, out namespaceName))
                {
                    objectAliasNamespaces.Add(
                        assemblyName, @namespace.QualifiedName);

                    return ReturnCode.Ok;
                }
                else if (String.Equals(
                        namespaceName, @namespace.QualifiedName,
                        StringOps.SystemStringComparisonType))
                {
                    //
                    // NOTE: Already added, same namespace name.  This
                    //       is allowed.
                    //
                    return ReturnCode.Ok;
                }
                else
                {
                    //
                    // NOTE: Already added, different namespace name.
                    //       This is an error.
                    //
                    error = String.Format(
                        "assembly \"{0}\" already mapped to namespace \"{1}\"",
                        FormatOps.DisplayName(assemblyName), namespaceName);
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjectAliasNamespaces(
            MatchMode mode,
            string pattern,
            bool noCase,
            bool values,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasObjectAliasNamespaces(ref error))
                {
                    StringList keys = new StringList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the namespaces collection in the containing interpreter.
                    //
                    foreach (KeyValuePair<string, string> pair in objectAliasNamespaces)
                    {
                        string assemblyName = pair.Key;

                        if (values)
                        {
                            string namespaceName = pair.Value;

                            if ((mode == MatchMode.None) ||
                                StringOps.Match(this, mode, namespaceName, pattern, noCase))
                            {
                                keys.Add(assemblyName);
                            }
                        }
                        else
                        {
                            if ((mode == MatchMode.None) ||
                                StringOps.Match(this, mode, assemblyName, pattern, noCase))
                            {
                                keys.Add(assemblyName);
                            }
                        }
                    }

                    //
                    // NOTE: Cleanup, PASS #2, and remove all the namespaces we found from
                    //       PASS #1 (above).
                    //
                    foreach (string key in keys)
                        objectAliasNamespaces.Remove(key);

                    //
                    // NOTE: Ok, we were successful.
                    //
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region INamespace
        internal INamespace GlobalNamespace
        {
            get { /* NO-LOCK */ return globalNamespace; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace Status Support
        internal bool AreNamespacesEnabled()
        {
            return RuntimeOps.AreNamespacesEnabled(createFlags);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool CanDeleteNamespace(
            INamespace @namespace
            )
        {
            //
            // NOTE: The global namespace cannot be deleted until the call stack
            //       for the interpreter is completely unwound.  Other namespaces
            //       cannot be deleted until they are no longer referenced.
            //
            if ((@namespace != null) && !IsGlobalNamespace(@namespace))
                return (@namespace.ReferenceCount <= 0);
            else
                return (Levels == 0);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace Traversal Support
        #region For Namespace Diagnostic Use Only
        private ReturnCode ShowNamespaces(
            bool imports,
            bool exports,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (globalNamespace == null)
                {
                    error = "invalid global namespace";
                    return ReturnCode.Error;
                }

                return globalNamespace.Traverse(
                    ShowNamespace, new ClientData(new Pair<bool>(
                        imports, exports)), ref error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ShowNamespace(
            INamespace @namespace,
            IClientData clientData,
            ref Result error
            ) /* NamespaceCallback */
        {
            if (@namespace == null)
            {
                error = "invalid namespace";
                return ReturnCode.Error;
            }

            if (clientData == null)
            {
                error = "invalid clientData";
                return ReturnCode.Error;
            }

            IPair<bool> pair = clientData.Data as IPair<bool>;

            if (pair == null)
            {
                error = "invalid boolean pair";
                return ReturnCode.Error;
            }

            bool imports = pair.X;
            bool exports = pair.Y;

            lock (syncRoot)
            {
                if (host == null)
                {
                    error = "interpreter host not available";
                    return ReturnCode.Error;
                }

                if (!host.WriteLine(String.Format(
                        "NAMESPACE {0}",
                        FormatOps.DisplayValue(@namespace.QualifiedName))))
                {
                    error = "write to host failed";
                    return ReturnCode.Error;
                }

                if (imports)
                {
                    foreach (string importName in
                            @namespace.GetImportNames(null, true, false))
                    {
                        if (!host.WriteLine(String.Format(
                                "IMPORT-SOURCE {0}",
                                FormatOps.DisplayValue(importName))))
                        {
                            error = "write to host failed";
                            return ReturnCode.Error;
                        }
                    }

                    foreach (string importName in
                            @namespace.GetImportNames(null, false, false))
                    {
                        if (!host.WriteLine(String.Format(
                                "IMPORT-TARGET {0}",
                                FormatOps.DisplayValue(importName))))
                        {
                            error = "write to host failed";
                            return ReturnCode.Error;
                        }
                    }
                }

                if (exports)
                {
                    foreach (string exportName in
                            @namespace.GetExportNames(null))
                    {
                        if (!host.WriteLine(String.Format(
                                "EXPORT {0}",
                                FormatOps.DisplayValue(exportName))))
                        {
                            error = "write to host failed";
                            return ReturnCode.Error;
                        }
                    }
                }

                return ReturnCode.Ok;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region For Namespace Import Renaming
        private ReturnCode RenameImportInNamespaces(
            string oldName,
            string newName,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (globalNamespace == null)
                {
                    error = "invalid global namespace";
                    return ReturnCode.Error;
                }

                return globalNamespace.Traverse(
                    RenameImportInNamespace, new ClientData(new StringPair(
                        oldName, newName)), ref error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RenameImportInNamespace(
            INamespace @namespace,
            IClientData clientData,
            ref Result error
            ) /* NamespaceCallback */
        {
            if (@namespace == null)
            {
                error = "invalid namespace";
                return ReturnCode.Error;
            }

            if (clientData == null)
            {
                error = "invalid clientData";
                return ReturnCode.Error;
            }

            IPair<string> pair = clientData.Data as IPair<string>;

            if (pair == null)
            {
                error = "invalid string pair";
                return ReturnCode.Error;
            }

            string oldName = pair.X;

            if (oldName == null)
            {
                error = "invalid old command name";
                return ReturnCode.Error;
            }

            string newName = pair.Y;

            if (newName == null)
            {
                error = "invalid new command name";
                return ReturnCode.Error;
            }

            if (@namespace.RenameImport(
                    oldName, newName, false, ref error) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region For Namespace Import Removal
        private ReturnCode RemoveImportFromNamespaces(
            string name,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (globalNamespace == null)
                {
                    error = "invalid global namespace";
                    return ReturnCode.Error;
                }

                return globalNamespace.Traverse(
                    RemoveImportFromNamespace, new ClientData(name),
                    ref error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveImportFromNamespace(
            INamespace @namespace,
            IClientData clientData,
            ref Result error
            ) /* NamespaceCallback */
        {
            if (@namespace == null)
            {
                error = "invalid namespace";
                return ReturnCode.Error;
            }

            if (clientData == null)
            {
                error = "invalid clientData";
                return ReturnCode.Error;
            }

            string name = clientData.Data as string;

            if (name == null)
            {
                error = "invalid command name";
                return ReturnCode.Error;
            }

            if (@namespace.RemoveImports(
                    name, false, ref error) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            return ReturnCode.Ok;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Pending Cleanup Flag
        public static bool IsPendingCleanup( /* EXTERNAL USE ONLY. */
            Interpreter interpreter
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* throw */
                {
                    return interpreter.IsPendingCleanup();
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsPendingCleanup()
        {
            //
            // NOTE: Check the pending cleanup flag.
            //
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.Cleanup, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void SetPendingCleanup()
        {
            //
            // NOTE: Set the pending cleanup flag.
            //
            interpreterFlags |= InterpreterFlags.Cleanup;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void UnsetPendingCleanup()
        {
            //
            // NOTE: Clear the pending cleanup flag.
            //
            interpreterFlags &= ~InterpreterFlags.Cleanup;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace Deletion Support
        internal ReturnCode CleanupNamespaces(
            VariableFlags flags,
            bool force,
            ref Result result
            )
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                bool pendingCleanup = IsPendingCleanup();

                if (pendingCleanup && AreNamespacesEnabled())
                {
                    if (pendingNamespaces == null)
                    {
                        result = "namespaces pending cleanup not available";
                        return ReturnCode.Error;
                    }

                    //
                    // NOTE: This foreach cannot simply iterate over the pending
                    //       namespace dictionary itself because it is modified
                    //       by the contained DeleteNamespace method.
                    //
                    Result localResult = null;
                    StringList keys = new StringList(pendingNamespaces.Keys);

                    foreach (string key in keys)
                    {
                        INamespace @namespace;

                        if (!pendingNamespaces.TryGetValue(key, out @namespace))
                            continue;

                        if (@namespace == null)
                            continue;

                        //
                        // HACK: If the namespace was somehow "undeleted" prior
                        //       to this cleanup method running, then do *NOT*
                        //       delete it; however, we still want to remove it
                        //       from the pending cleanup list.
                        //
                        if (@namespace.Deleted && DeleteNamespace(
                                flags, @namespace, force,
                                ref localResult) != ReturnCode.Ok)
                        {
                            break;
                        }
                    }

                    //
                    // NOTE: In this context, "success" means that there should
                    //       be no more namespaces pending deletion af this
                    //       point.
                    //
                    if (pendingNamespaces.Count == 0)
                    {
                        UnsetPendingCleanup();
                        return ReturnCode.Ok;
                    }

                    //
                    // NOTE: If there is a local result, use it; otherwise,
                    //       return a generic error message.
                    //
                    if (localResult != null)
                        result = localResult;
                    else
                        result = "some namespaces pending cleanup were not deleted";

                    return ReturnCode.Error;
                }
                else if (pendingCleanup)
                {
                    //
                    // NOTE: Namespace support is disabled; therefore, just
                    //       delete the global namespace now.
                    //
                    if (DeleteNamespace(
                            flags, (INamespace)null, false,
                            ref result) == ReturnCode.Ok)
                    {
                        UnsetPendingCleanup();
                        return ReturnCode.Ok;
                    }

                    return ReturnCode.Error;
                }
                else
                {
                    //
                    // NOTE: Namespace support is disabled and the pending
                    //       cleanup flag for the interpreter is not set,
                    //       do nothing.
                    //
                    return ReturnCode.Ok;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DeleteNamespace(
            VariableFlags flags,
            string name,
            bool force,
            ref Result result
            )
        {
            INamespace @namespace = null;

            if (AreNamespacesEnabled())
            {
                @namespace = NamespaceOps.Lookup(this, name, false, false);

                if (@namespace == null)
                {
                    result = String.Format(
                        "unknown namespace \"{0}\" in namespace delete command",
                        FormatOps.DisplayName(name)); /* COMPAT: Tcl. */

                    return ReturnCode.Error;
                }
            }

            return DeleteNamespace(flags, @namespace, force, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode DeleteNamespace(
            VariableFlags flags,
            INamespace @namespace,
            bool force,
            ref Result result
            )
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                if (!IsModifiable(false, ref result))
                    return ReturnCode.Error;

                bool useNamespaces = AreNamespacesEnabled();

                if (useNamespaces && (@namespace == null))
                {
                    result = "invalid namespace";
                    return ReturnCode.Error;
                }

                //
                // NOTE: Grab the fully qualified name for the namespace now
                //       as it is needed in several places in this method.
                //
                string qualifiedName = (@namespace != null) ?
                    @namespace.QualifiedName : null;

                //
                // NOTE: See if we can delete the namespace immediately -OR-
                //       if we have to wait until the evluation stack for the
                //       namespace is completely unwound.
                //
                if (force || CanDeleteNamespace(@namespace))
                {
                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Delete all children of the namespace first.
                    //
                    if (@namespace != null)
                    {
                        foreach (INamespace childNamespace in
                                /* ALL */ @namespace.GetChildren(null, true))
                        {
                            if (childNamespace == null)
                                continue;

                            if (DeleteNamespace(
                                    flags, childNamespace, force,
                                    ref result) != ReturnCode.Ok) /* RECURSIVE */
                            {
                                return ReturnCode.Error;
                            }
                        }
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove all commands that were imported into the
                    //       namespace now.  Each imported command actually
                    //       corresponds to an alias name token in the target
                    //       interpreter.
                    //
                    if (@namespace != null)
                    {
                        if (@namespace.RemoveImports(
                                null, false, ref result) != ReturnCode.Ok)
                        {
                            return ReturnCode.Error;
                        }
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove all exported commands belonging to this
                    //       namespace from all other namespaces now.
                    //
                    if (@namespace != null)
                    {
                        if (RemoveImportFromNamespaces(
                                NamespaceOps.MakeQualifiedPattern(
                                this, @namespace, null, false),
                                ref result) != ReturnCode.Ok)
                        {
                            return ReturnCode.Error;
                        }
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Apparently, hidden commands should only be deleted
                    //       from non-global namespaces (COMPAT: Tcl).
                    //
                    bool deleteHidden = !useNamespaces || !IsGlobalNamespace(
                        @namespace);

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove all hidden IExecute objects in the
                    //       namespace now.
                    //
                    if (deleteHidden && (hiddenExecutes != null))
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, hiddenExecutes.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(hiddenExecutes.Keys);
                        }

                        foreach (string key in keys)
                            hiddenExecutes.Remove(key);

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove all non-hidden IExecute objects in the
                    //       namespace now.
                    //
                    if (executes != null)
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, executes.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(executes.Keys);
                        }

                        foreach (string key in keys)
                            executes.Remove(key);

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove hidden all procedures in the namespace
                    //       now.
                    //
                    if (deleteHidden && (hiddenProcedures != null))
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, hiddenProcedures.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(hiddenProcedures.Keys);
                        }

                        foreach (string key in keys)
                        {
                            IProcedure procedure = hiddenProcedures[key];

                            if (procedure != null)
                            {
                                //
                                // BUGFIX: Skip deleting read-only procedures.
                                //
                                if (!EntityOps.IsReadOnly(procedure) &&
                                    !EntityOps.IsNoRemove(procedure))
                                {
                                    hiddenProcedures.Remove(key);
                                }
                            }
                            else
                            {
                                hiddenProcedures.Remove(key);
                            }
                        }

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove non-hidden all procedures in the namespace
                    //       now.
                    //
                    if (procedures != null)
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, procedures.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(procedures.Keys);
                        }

                        foreach (string key in keys)
                        {
                            IProcedure procedure = procedures[key];

                            if (procedure != null)
                            {
                                //
                                // BUGFIX: Skip deleting read-only procedures.
                                //
                                if (!EntityOps.IsReadOnly(procedure) &&
                                    !EntityOps.IsNoRemove(procedure))
                                {
                                    procedures.Remove(key);
                                }
                            }
                            else
                            {
                                procedures.Remove(key);
                            }
                        }

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Attempt to terminate and remove all hidden
                    //       commands for the namespace now.
                    //
                    if (deleteHidden && (hiddenCommands != null))
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, hiddenCommands.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(hiddenCommands.Keys);
                        }

                        foreach (string key in keys)
                        {
                            ICommand command = hiddenCommands[key];

                            if (command != null)
                            {
                                //
                                // BUGFIX: Skip deleting read-only commands.
                                //
                                if (!EntityOps.IsReadOnly(command))
                                {
                                    ReturnCode code;

                                    GlobalState.PushActiveInterpreter(this);

                                    try
                                    {
                                        code = command.Terminate(
                                            this, null, ref result);
                                    }
                                    catch (Exception e)
                                    {
                                        result = String.Format(
                                            "caught exception while terminating command: {0}",
                                            e);

                                        code = ReturnCode.Error;
                                    }
                                    finally
                                    {
                                        /* IGNORED */
                                        GlobalState.PopActiveInterpreter();
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        //
                                        // NOTE: Command terminated, remove it.
                                        //
                                        hiddenCommands.Remove(key);
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Failure, halt deletion.
                                        //
                                        return code;
                                    }
                                }
                            }
                            else
                            {
                                hiddenCommands.Remove(key);
                            }
                        }

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Attempt to terminate and remove all non-hidden
                    //       commands for the namespace now.
                    //
                    if (commands != null)
                    {
                        StringList keys = null;

                        if (useNamespaces)
                        {
                            if (NamespaceOps.MatchItems(
                                    this, @namespace, commands.Keys,
                                    null, false, false, false, false,
                                    ref keys, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }
                        }
                        else
                        {
                            keys = new StringList(commands.Keys);
                        }

                        foreach (string key in keys)
                        {
                            ICommand command = commands[key];

                            if (command != null)
                            {
                                //
                                // BUGFIX: Skip deleting read-only commands.
                                //
                                if (!EntityOps.IsReadOnly(command))
                                {
                                    ReturnCode code;

                                    GlobalState.PushActiveInterpreter(this);

                                    try
                                    {
                                        code = command.Terminate(
                                            this, null, ref result);
                                    }
                                    catch (Exception e)
                                    {
                                        result = String.Format(
                                            "caught exception while terminating command: {0}",
                                            e);

                                        code = ReturnCode.Error;
                                    }
                                    finally
                                    {
                                        /* IGNORED */
                                        GlobalState.PopActiveInterpreter();
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        //
                                        // NOTE: Command terminated, remove it.
                                        //
                                        commands.Remove(key);
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Failure, halt deletion.
                                        //
                                        return code;
                                    }
                                }
                            }
                            else
                            {
                                commands.Remove(key);
                            }
                        }

#if EXECUTE_CACHE
                        //
                        // BUGFIX: Everything may have just gone away,
                        //         clear the caches now.
                        //
                        ClearExecuteCache();
#endif
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Next, remove all variables in the namespace now.
                    //       This step may remove all global variables (i.e.
                    //       if the global namespace is being deleted).
                    //
                    ICallFrame frame;

                    if (!useNamespaces || IsGlobalNamespace(@namespace))
                        frame = GlobalFrame;
                    else
                        frame = @namespace.VariableFrame;

                    if (frame != null)
                    {
                        VariableDictionary variables = frame.Variables;

                        if (variables != null)
                        {
#if NOTIFY || NOTIFY_OBJECT
                            //
                            // NOTE: *SPECIAL* This notification must be
                            //       done before the variables are marked
                            //       as "Undefined" because that is what
                            //       the ObjectTraceCallback method
                            //       expects for the BeforeVariableUnset
                            //       breakpoint type.
                            //
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.CallFrame, NotifyFlags.Deleted |
                                    NotifyFlags.Force, frame, this, null,
                                null, null, ref result);
#endif

                            bool reset = FlagOps.HasFlags(
                                flags, VariableFlags.ResetValue, true);

                            bool zero = HasZeroString() && HasZeroString(flags);

                            foreach (KeyValuePair<string, IVariable> pair in variables)
                            {
                                IVariable variable = pair.Value;

                                if (variable == null)
                                    continue;

                                //
                                // BUGFIX: Skip deleting any read-only (-OR-
                                //         "invariant") variables.
                                //
                                if (!EntityOps.IsReadOnly(variable) &&
                                    !EntityOps.IsInvariant(variable))
                                {
                                    //
                                    // NOTE: The variable is now dead.
                                    //
                                    if (reset && (variable is Variable))
                                    {
                                        ((Variable)variable).ResetValue(
                                            this, zero);
                                    }

                                    EntityOps.SetUndefined(variable, true);

                                    //
                                    // NOTE: Remove any pending array searches
                                    //       that may exist for this variable.
                                    //
                                    CleanupArraySearches(variable);

                                    //
                                    // BUGFIX: Mark the variable as "dirty"
                                    //         AFTER the actual modifications
                                    //         have been completed.
                                    //
                                    EntityOps.SignalDirty(variable, null);
                                }
                            }
                        }

                        //
                        // NOTE: The call frame is no longer usable.
                        //
                        /* IGNORED */
                        CallFrameOps.Cleanup(CurrentFrame, frame, true);
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Remove the namespace being deleted from its parent
                    //       unless its parent namespace is already deleted.
                    //
                    if (@namespace != null)
                    {
                        INamespace parentNamespace = @namespace.Parent;

                        if ((parentNamespace != null) &&
                            !parentNamespace.Deleted)
                        {
                            ReturnCode removeCode;
                            Result removeError = null;

                            removeCode = parentNamespace.RemoveChild(
                                @namespace.Name, ref removeError);

                            if (removeCode != ReturnCode.Ok)
                                DebugOps.Complain(this, removeCode, removeError);
                        }
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Next, make sure the namespace is removed from the
                    //       pending deletion list, if applicable.  This needs
                    //       to be done prior to actually disposing the object
                    //       itself because the object disposal can fail and
                    //       even if it does, we never want to try and delete
                    //       this namespace again.
                    //
                    if ((pendingNamespaces != null) &&
                        (qualifiedName != null))
                    {
                        /* IGNORED */
                        pendingNamespaces.Remove(qualifiedName);
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: Finally, dispose of the namespace itself.
                    //
                    if (@namespace != null)
                    {
                        ReturnCode disposeCode;
                        Result disposeError = null;

                        disposeCode = NamespaceOps.Dispose(
                            this, ref @namespace, ref disposeError);

                        if (disposeCode != ReturnCode.Ok)
                        {
                            result = String.Format(
                                "caught exception while disposing namespace \"{0}\": {1}",
                                qualifiedName, disposeError);

                            return disposeCode;
                        }
                    }
                }
                else
                {
                    //
                    // NOTE: Mark the namespace as requiring cleanup after the
                    //       current evaluation stack unwinds.
                    //
                    if (@namespace != null)
                    {
                        if ((pendingNamespaces != null) &&
                            (qualifiedName != null) &&
                            !pendingNamespaces.ContainsKey(qualifiedName))
                        {
                            pendingNamespaces.Add(qualifiedName, @namespace);
                        }

                        @namespace.MarkDeleted();
                    }

                    SetPendingCleanup();
                }

                return ReturnCode.Ok;
            }
        }
        #endregion
        #endregion
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IInterpreterManager Members
        public bool IsMasterInterpreter()
        {
            CheckDisposed();

            return (masterInterpreter == null);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasSlaveInterpreters(ref Result error)
        {
            CheckDisposed();

            bool result = (slaveInterpreters != null);

            if (!result)
                error = "slave interpreters not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesSlaveInterpreterExist(string path)
        {
            CheckDisposed();

            return DoesSlaveInterpreterExist(path, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetSlaveInterpreter(
            string path,
            LookupFlags lookupFlags,
            bool nested,
            bool create,
            ref Interpreter interpreter,
            ref string name,
            ref Result error
            )
        {
            CheckDisposed();

            if (nested)
                return GetNestedSlaveInterpreter(path, lookupFlags, create,
                    ref interpreter, ref name, ref error);
            else
                return GetSlaveInterpreter(path, lookupFlags, ref interpreter,
                    ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddSlaveInterpreter(
            string name,
            Interpreter interpreter,
            IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (interpreter == null)
                {
                    error = "invalid interpreter";
                    return ReturnCode.Error;
                }

                if (name == null)
                {
                    error = "invalid interpreter name";
                    return ReturnCode.Error;
                }

                if (!HasSlaveInterpreters(ref error))
                    return ReturnCode.Error;

                if (Object.ReferenceEquals(interpreter, this))
                {
                    error = String.Format(
                        "can't add \"{0}\": same as current interpreter",
                        name);

                    return ReturnCode.Error;
                }

                if (DoesSlaveInterpreterExist(name, false) == ReturnCode.Ok)
                {
                    error = String.Format(
                        "can't add \"{0}\": slave interpreter already exists",
                        name);

                    return ReturnCode.Error;
                }

                slaveInterpreters.Add(name, interpreter);

#if NOTIFY && NOTIFY_GLOBAL
                if (this.GlobalNotify)
                    /* IGNORED */
                    CheckNotifications(
                        null, false,
                        NotifyType.Interpreter, NotifyFlags.Added,
                        //
                        // BUGBUG: In order to use this class for notification
                        //         parameters, it really should probably be
                        //         made public.
                        //
                        new ObjectList(name), interpreter,
                        clientData, null, null, ref error);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveSlaveInterpreter(
            string name,
            IClientData clientData,
            bool synchronous,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (HasSlaveInterpreters(ref error))
                {
                    Interpreter interpreter = null;

                    if (GetSlaveInterpreter(
                            name, LookupFlags.Interpreter, ref interpreter,
                            ref error) == ReturnCode.Ok)
                    {
                        if (interpreter != null)
                        {
                            if (!Object.ReferenceEquals(interpreter, this))
                            {
                                GlobalState.PushActiveInterpreter(this);

                                try
                                {
#if APPDOMAINS && ISOLATED_INTERPRETERS
                                    string appDomainName = interpreter.SlaveAppDomainName;
#endif

                                    ///////////////////////////////////////////////////////////////////

                                    if (ObjectOps.TryDispose(
                                            interpreter, ref error) == ReturnCode.Ok)
                                    {
                                        interpreter = null;

                                        if (synchronous)
                                            ObjectOps.CollectGarbage(); /* throw */
                                    }
                                    else
                                    {
                                        return ReturnCode.Error;
                                    }

                                    ///////////////////////////////////////////////////////////////////

#if APPDOMAINS && ISOLATED_INTERPRETERS
                                    if (appDomainName != null)
                                    {
                                        ReturnCode removeCode;
                                        Result removeError = null;

                                        removeCode = RemoveAppDomain(
                                            appDomainName, clientData, ref removeError);

                                        if (removeCode == ReturnCode.Ok)
                                        {
                                            if (synchronous)
                                                ObjectOps.CollectGarbage(); /* throw */
                                        }
                                        else
                                        {
                                            //
                                            // NOTE: Not much we can do at this point.  The slave
                                            //       interpreter itself was successfully disposed
                                            //       and must be removed from the collection.  The
                                            //       application domain can still be disposed during
                                            //       the disposal of this interpreter.
                                            //
                                            DebugOps.Complain(this, removeCode, removeError);
                                        }
                                    }
#endif
                                }
                                catch (Exception e)
                                {
                                    error = String.Format(
                                        "caught exception while disposing slave interpreter: {0}",
                                        e);

                                    return ReturnCode.Error;
                                }
                                finally
                                {
                                    /* IGNORED */
                                    GlobalState.PopActiveInterpreter();
                                }
                            }
                        }

                        slaveInterpreters.Remove(name);

#if NOTIFY && NOTIFY_GLOBAL
                        if (this.GlobalNotify)
                            /* IGNORED */
                            CheckNotifications(
                                null, false,
                                NotifyType.Interpreter, NotifyFlags.Removed,
                                //
                                // BUGBUG: In order to use this class for notification
                                //         parameters, it really should probably be
                                //         made public.
                                //
                                new ObjectList(name), interpreter,
                                clientData, null, null, ref error);
#endif

                        return ReturnCode.Ok;
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal Interpreter MasterInterpreter
        {
            get { return masterInterpreter; }
            set { masterInterpreter = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string SlaveName
        {
            get { return slaveName; }
            set { slaveName = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if APPDOMAINS && ISOLATED_INTERPRETERS
        internal string SlaveAppDomainName
        {
            get { return slaveAppDomainName; }
            set { slaveAppDomainName = value; }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private InterpreterDictionary CopySlaveInterpreters()
        {
            lock (syncRoot)
            {
                if (slaveInterpreters != null)
                    return new InterpreterDictionary(slaveInterpreters);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string SlaveInterpretersToString(
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                if (slaveInterpreters != null)
                    return slaveInterpreters.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsMasterInterpreter(
            Interpreter interpreter
            )
        {
            lock (syncRoot)
            {
                return (interpreter != null) &&
                    Object.ReferenceEquals(interpreter, masterInterpreter);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsSlaveInterpreter(
            Interpreter interpreter
            )
        {
            lock (syncRoot)
            {
                return (interpreter != null) && (slaveInterpreters != null) &&
                    slaveInterpreters.ContainsValue(interpreter);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsMasterOrSlaveInterpreter(
            object value
            )
        {
            Interpreter interpreter = value as Interpreter;

            return (interpreter != null) ?
                IsMasterInterpreter(interpreter) || IsSlaveInterpreter(interpreter) : false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode DoesSlaveInterpreterExist(
            string path,
            bool nested
            )
        {
            string name = null;

            return DoesSlaveInterpreterExist(path, nested, ref name);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DoesSlaveInterpreterExist(
            string path,
            bool nested,
            ref string name
            )
        {
            Interpreter interpreter = null;
            Result error = null;

            return GetSlaveInterpreter(path, LookupFlags.Exists,
                nested, false, ref interpreter, ref name, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetSlaveInterpreter(
            string path,
            LookupFlags lookupFlags,
            bool nested,
            bool create,
            ref Interpreter interpreter,
            ref Result error
            )
        {
            string name = null;

            return GetSlaveInterpreter(path, lookupFlags, nested, create,
                ref interpreter, ref name, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetSlaveInterpreter(
            string name,
            LookupFlags lookupFlags,
            ref Interpreter interpreter,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (HasSlaveInterpreters(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty interpreter names are technically allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (name.Length > 0)
                        {
                            if (slaveInterpreters.TryGetValue(name, out interpreter))
                            {
                                if ((interpreter != null) ||
                                    !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
                                {
                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    error = FlagOps.HasFlags(
                                        lookupFlags, LookupFlags.Verbose, true) ?
                                        String.Format(
                                            "invalid interpreter name \"{0}\"",
                                            FormatOps.DisplayName(name)) :
                                        "invalid interpreter name";
                                }
                            }
                            else
                            {
                                error = FlagOps.HasFlags(
                                    lookupFlags, LookupFlags.Verbose, true) ?
                                    String.Format(
                                        "could not find interpreter \"{0}\"",
                                        FormatOps.DisplayName(name)) :
                                    "could not find interpreter";
                            }
                        }
                        else
                        {
                            //
                            // NOTE: The empty string always represents the current
                            //       interpreter.
                            //
                            interpreter = this;

                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        error = "invalid interpreter name";
                    }
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IErrorManager Members
        public int ErrorLine
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ErrorLine;
                else
                    return 0;
#else
                lock (syncRoot)
                {
                    return errorLine;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ErrorLine = value;
#else
                lock (syncRoot)
                {
                    errorLine = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CopyErrorInformation(
            VariableFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            return CopyErrorInformation(flags, false, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CopyErrorInformation(
            VariableFlags flags,
            bool strict,
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code;
            Result errorCode = null;
            Result errorInfo = null;
            ResultList errors = null;

            code = CopyErrorInformation(
                flags, strict, ref errorCode, ref errorInfo,
                ref errors);

            if (code == ReturnCode.Ok)
            {
                if (result == null)
                    result = String.Empty;

                result.ErrorCode = errorCode;
                result.ErrorInfo = errorInfo;
            }
            else
            {
                if (errors != null)
                    result = errors.ToString();
                else
                    result = "could not copy error information";
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CopyErrorInformation(
            VariableFlags flags,
            bool strict,
            ref Result errorCode,
            ref Result errorInfo
            )
        {
            CheckDisposed();

            ResultList errors = null;

            return CopyErrorInformation(flags, strict,
                ref errorCode, ref errorInfo, ref errors);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CopyErrorInformation(
            VariableFlags flags,
            bool strict,
            ref Result errorCode,
            ref Result errorInfo,
            ref ResultList errors
            )
        {
            CheckDisposed();

            //
            // NOTE: For now, only allow flags related to disabling watches,
            //       traces, and notifications, etc.
            //
            flags &= VariableFlags.FastNonInstanceMask;

            //
            // NOTE: Keep track of any errors encountered while querying the
            //       error related variables and report them to the caller,
            //       even in non-strict mode (i.e. when we would return Ok).
            //
            int errorCount = 0;
            Result error = null;

            if (GetVariableValue(
                    Engine.ErrorCodeVariableFlags | flags,
                    TclVars.ErrorCode, ref errorCode,
                    ref error) != ReturnCode.Ok)
            {
                if (errors == null)
                    errors = new ResultList();

                errors.Add(error); errorCount++;
            }

            if (GetVariableValue(
                    Engine.ErrorInfoVariableFlags | flags,
                    TclVars.ErrorInfo, ref errorInfo,
                    ref error) != ReturnCode.Ok)
            {
                if (errors == null)
                    errors = new ResultList();

                errors.Add(error); errorCount++;
            }

            //
            // NOTE: In strict mode, return Error if there were any errors
            //       querying the variables; otherwise, return Ok.
            //
            return strict ?
                (errorCount > 0 ? ReturnCode.Error : ReturnCode.Ok) :
                ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal static int GetErrorLine(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return 0;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return 0;

                return interpreter.ErrorLine;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static void SetErrorLine(
            Interpreter interpreter,
            int errorLine
            )
        {
            if (interpreter == null)
                return;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return;

                interpreter.ErrorLine = errorLine;
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IHistoryManager Members
#if HISTORY
        public bool History
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return history;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    history = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int HistoryLimit
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return historyLimit;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    historyLimit = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasHistory(ref Result error)
        {
            CheckDisposed();

            bool result = (_History != null);

            if (!result)
                error = "history not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryData HistoryLoadData
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistoryLoadData;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historyLoadData;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistoryLoadData = value;
#else
                lock (syncRoot)
                {
                    historyLoadData = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryData HistorySaveData
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistorySaveData;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historySaveData;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistorySaveData = value;
#else
                lock (syncRoot)
                {
                    historySaveData = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryFilter HistoryEngineFilter
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.HistoryEngineFilter;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historyEngineFilter;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.HistoryEngineFilter = value;
#else
                lock (syncRoot)
                {
                    historyEngineFilter = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryFilter HistoryInfoFilter
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistoryInfoFilter;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historyInfoFilter;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistoryInfoFilter = value;
#else
                lock (syncRoot)
                {
                    historyInfoFilter = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryFilter HistoryLoadFilter
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistoryLoadFilter;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historyLoadFilter;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistoryLoadFilter = value;
#else
                lock (syncRoot)
                {
                    historyLoadFilter = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHistoryFilter HistorySaveFilter
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistorySaveFilter;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historySaveFilter;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistorySaveFilter = value;
#else
                lock (syncRoot)
                {
                    historySaveFilter = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string HistoryFileName
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.HistoryFileName;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return historyFileName;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.HistoryFileName = value;
#else
                lock (syncRoot)
                {
                    historyFileName = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ClearHistory(
            IHistoryFilter historyFilter, /* NOT USED */
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (!HasHistory(ref error))
                    return ReturnCode.Error;

                //
                // NOTE: Clear the history of executed commands.
                //
                _History.Clear();

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.History, NotifyFlags.Cleared,
                    null, this,
                    null, null, null, ref error);
#endif
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddHistory(
            ArgumentList arguments,
            IHistoryData historyData,
            IHistoryFilter historyFilter, /* NOT USED */
            ref Result error
            )
        {
            CheckDisposed();

            int levels;
            HistoryFlags flags;

            if (historyData != null)
            {
                levels = historyData.Levels;
                flags = historyData.Flags;
            }
            else
            {
                levels = Level.Invalid;
                flags = HistoryFlags.None;
            }

            return AddHistory(arguments, levels, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode LoadHistory(
            Encoding encoding,
            string fileName,
            IHistoryData historyData,
            IHistoryFilter historyFilter, /* NOT USED */
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (String.IsNullOrEmpty(fileName))
                {
                    error = "invalid file name";
                    return ReturnCode.Error;
                }

                if (!File.Exists(fileName))
                {
                    error = String.Format(
                        "couldn't read file \"{0}\": no such file or directory",
                        fileName);

                    return ReturnCode.Error;
                }

                if (!HasHistory(ref error))
                    return ReturnCode.Error;

                try
                {
                    if (encoding == null)
                        encoding = DefaultEncoding;

                    using (StreamReader streamReader = new StreamReader(
                            new FileStream(fileName, FileMode.Open,
                                FileAccess.Read), encoding)) /* EXEMPT */
                    {
                        int levels;
                        HistoryFlags flags;

                        if (historyData != null)
                        {
                            levels = historyData.Levels;
                            flags = historyData.Flags;
                        }
                        else
                        {
                            levels = Level.Invalid;
                            flags = HistoryFlags.None;
                        }

                        while (!streamReader.EndOfStream)
                        {
                            StringList list = null;
                            Result localError = null;

                            if (Parser.SplitList(
                                    this, streamReader.ReadLine(), 0,
                                    Length.Invalid, true, ref list,
                                    ref localError) == ReturnCode.Ok)
                            {
                                IClientData clientData = new HistoryClientData(
                                    null, new ArgumentList(list, ArgumentFlags.None),
                                    levels, flags & HistoryFlags.InstanceMask);

                                _History.AddLast(clientData);
                            }
                            else if (strict)
                            {
                                error = localError;
                                return ReturnCode.Error;
                            }
                        }
                    }

                    return ReturnCode.Ok;
                }
                catch (Exception e)
                {
                    error = e;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SaveHistory(
            Encoding encoding,
            string fileName,
            IHistoryData historyData, /* NOT USED */
            IHistoryFilter historyFilter,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (String.IsNullOrEmpty(fileName))
                {
                    error = "invalid file name";
                    return ReturnCode.Error;
                }

                if (!HasHistory(ref error))
                    return ReturnCode.Error;

                try
                {
                    if (encoding == null)
                        encoding = DefaultEncoding;

                    using (StreamWriter streamWriter = new StreamWriter(
                            new FileStream(fileName, FileMode.Create,
                                FileAccess.Write), encoding)) /* EXEMPT */
                    {
                        foreach (IClientData clientData in _History)
                        {
                            HistoryClientData historyClientData =
                                clientData as HistoryClientData;

                            if (historyClientData != null)
                            {
                                if (HistoryOps.MatchData(
                                        historyClientData, historyFilter))
                                {
                                    ArgumentList arguments =
                                        historyClientData.Arguments;

                                    if (arguments != null)
                                        streamWriter.WriteLine(
                                            arguments.ToString());
                                }
                            }
                            else if (strict)
                            {
                                error = "invalid history data";
                                return ReturnCode.Error;
                            }
                        }
                    }

                    return ReturnCode.Ok;
                }
                catch (Exception e)
                {
                    error = e;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool CanAddHistory()
        {
            // CheckDisposed();

            // lock (syncRoot) // BUGBUG: *PERF* Used by engine.
            {
                return history &&
#if THREADING
                    (_History != null);
#else
                    (_history != null);
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool HasHistory() // NOTE: For _Hosts.Default use only.
        {
#if THREADING
            return (_History != null);
#else
            return (_history != null);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddHistory(
            ArgumentList arguments,
            int levels,
            HistoryFlags flags
            )
        {
            Result error = null;

            return AddHistory(arguments, levels, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddHistory(
            ArgumentList arguments,
            int levels,
            HistoryFlags flags,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!IsModifiable(true, ref error))
                    return ReturnCode.Error;

                if (arguments == null)
                {
                    error = "invalid arguments";
                    return ReturnCode.Error;
                }

                if (!HasHistory(ref error))
                    return ReturnCode.Error;

                //
                // NOTE: Add the arguments to the history of executed commands.
                //
                IClientData clientData =
                    new HistoryClientData(null, arguments, levels, flags);

                _History.AddFirst(clientData);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.History, NotifyFlags.Added,
                    clientData, this,
                    null, null, null, ref error);
#endif

                //
                // NOTE: Prevent the number of history items from exceeding the
                //       limit (unless the limit is -1).
                //
                int limit = historyLimit;

                if (limit >= 0)
                {
                    //
                    // NOTE: If the limit is zero, use the default limit.
                    //
                    if (limit == 0)
                        limit = DefaultHistoryLimit;

                    while (_History.Count > limit)
                    {
                        //
                        // NOTE: Remove old argument lists in FIFO style.
                        //
                        LinkedListNode<IClientData> last = _History.Last;

                        if (last == null)
                            break;

                        clientData = last.Value;
                        _History.RemoveLast();

#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.History, NotifyFlags.Removed,
                            clientData, this,
                            null, null, null, ref error);
#endif
                    }
                }
            }

            return ReturnCode.Ok;
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IInteractiveManager Members
        public bool Interactive // using interactive shell?
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.Interactive;
                else
                    return false;
#else
                lock (syncRoot)
                {
                    return interactive;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.Interactive = value;
#else
                lock (syncRoot)
                {
                    interactive = value;
                }
#endif

                if (IsPrimaryThread())
                {
                    //
                    // NOTE: Do not create the variable if we have been prohibited
                    //       from doing so.
                    //
                    VariableFlags flags = VariableFlags.ViaProperty;

                    if (FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                        flags |= VariableFlags.NoCreate;

                    //
                    // NOTE: Update script-level informational variable.
                    //
                    SetLibraryVariableValue(
                        flags, TclVars.Interactive, value.ToString());
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string InteractiveInput
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.InteractiveInput;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return interactiveInput;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.InteractiveInput = value;
#else
                lock (syncRoot)
                {
                    interactiveInput = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string PreviousInteractiveInput
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.PreviousInteractiveInput;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return previousInteractiveInput;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.PreviousInteractiveInput = value;
#else
                lock (syncRoot)
                {
                    previousInteractiveInput = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string InteractiveMode
        {
            get
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.InteractiveMode;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return interactiveMode;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.InteractiveMode = value;
#else
                lock (syncRoot)
                {
                    interactiveMode = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private static void SetInteractiveInput(
            Interpreter interpreter,
            string interactiveInput
            )
        {
            if (interpreter == null)
                return;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return;

                interpreter.InteractiveInput = interactiveInput;
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IInterpreter Members
        #region Identity & Affinity
        public long Id
        {
            get { CheckDisposed(); return id; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int ThreadId
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return threadId;
                }
            }
            internal set
            {
                CheckDisposed(); /* NON-PUBLIC, SANITY */

                lock (syncRoot)
                {
                    threadId = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public Thread Thread
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return thread;
                }
            }
            internal set
            {
                CheckDisposed(); /* NON-PUBLIC, SANITY */

                lock (syncRoot)
                {
                    thread = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL
        public Thread InteractiveThread
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return interactiveThread;
                }
            }
            internal set
            {
                CheckDisposed(); /* NON-PUBLIC, SANITY */

                lock (syncRoot)
                {
                    interactiveThread = value;
                }
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public EventWaitHandle VariableEvent
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return variableEvent;
                }
            }
            internal set
            {
                CheckDisposed(); /* NON-PUBLIC, SANITY */

                lock (syncRoot)
                {
                    variableEvent = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public long IdNoThrow
        {
            get
            {
                //
                // NOTE: This method may NOT throw exceptions.
                //
                /* CheckDisposed(); */

                return id;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int GetHashCodeNoThrow()
        {
            //
            // NOTE: This method may NOT throw exceptions.
            //
            /* CheckDisposed(); */

            int Y = 0; /* NOTE: Low half. */
            int Z = 0; /* NOTE: High half. */

            ConversionOps.ToInts(id, ref Y, ref Z);
            return CommonOps.HashCodes.Combine(Y, Z);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public AppDomain GetAppDomain()
        {
            CheckDisposed();

            // lock (syncRoot) /* NOT CHANGED */
            {
                return appDomain;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public StrongName GetStrongName()
        {
            CheckDisposed();

            return AssemblyOps.GetStrongName(GlobalState.GetAssembly());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public Hash GetHash()
        {
            CheckDisposed();

            return AssemblyOps.GetHash(GlobalState.GetAssembly());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public X509Certificate GetCertificate()
        {
            CheckDisposed();

            return AssemblyOps.GetCertificate(GlobalState.GetAssembly());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void DemandStrongName()
        {
            CheckDisposed();

            StrongName strongName = GetStrongName();

            new StrongNameIdentityPermission(
                (strongName != null) ? strongName.PublicKey : null,
                null, null).Demand();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void DemandCertificate()
        {
            CheckDisposed();

            new PublisherIdentityPermission(GetCertificate()).Demand();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public long NextId() /* THREAD-SAFE */
        {
            CheckDisposed();

            long result;

            //
            // NOTE: This is our cheap per-interpreter unique Id
            //       generator for the various script visible
            //       identifiers (such as channel names, etc).
            //
            result = Interlocked.Increment(ref nextId);

            if (result < 0)
                DebugOps.Complain(this, ReturnCode.Error,
                    "next identifier is negative");

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool IsPrimaryThread()
        {
            return IsPrimaryThread(GlobalState.GetCurrentThreadId());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool IsPrimaryThread(int threadId)
        {
            return (threadId == this.threadId);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private EventWaitHandle PrivateVariableEvent
        {
            get { return variableEvent; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void SignalVariableEvent()
        {
            ReturnCode code;
            Result error = null;

            code = SignalVariableEvent(ref error);

            if (code != ReturnCode.Ok)
                DebugOps.Complain(this, code, error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SignalVariableEvent(
            ref Result error
            )
        {
            EventWaitHandle variableEvent;

            lock (syncRoot)
            {
                variableEvent = this.variableEvent;
            }

            if (variableEvent != null)
            {
                if (ThreadOps.SetEvent(variableEvent))
                {
                    return ReturnCode.Ok;
                }
                else
                {
                    error = "failed to signal variable event";
                }
            }
            else
            {
                error = "cannot signal variable event";
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Host & Script Environment
        #region Global Default Quiet Mode Setting
        internal static bool DefaultQuiet
        {
            get
            {
                lock (staticSyncRoot)
                {
                    return defaultQuiet;
                }
            }
            set
            {
                lock (staticSyncRoot)
                {
                    defaultQuiet = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static bool DefaultTraceStack
        {
            get
            {
                lock (staticSyncRoot)
                {
                    return defaultTraceStack;
                }
            }
            set
            {
                lock (staticSyncRoot)
                {
                    defaultTraceStack = value;
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Global New Host Callback
        public static NewHostCallback NewHostCallback
        {
            get
            {
                lock (staticSyncRoot)
                {
                    return newHostCallback;
                }
            }
            set
            {
                lock (staticSyncRoot)
                {
                    newHostCallback = value;
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ScriptFlags ScriptFlags
        {
            get { CheckDisposed(); lock (syncRoot) { return scriptFlags; } }
            set { CheckDisposed(); lock (syncRoot) { scriptFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IHost Host
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return host;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    host = value;

                    //
                    // BUGFIX: We may have just been handed a host that we have
                    //         never seen before.  Make sure it is setup properly.
                    //
                    ReturnCode code;
                    Result error = null;

                    if (host != null)
                    {
                        code = PreSetupHost(host, false, ref error);

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, error);

                        code = SetupHostChannels(this, host, true, ref error);

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, error);
                    }

#if DEBUGGER
                    code = SetupDebuggerHost(this, host, ref error);

                    if (code != ReturnCode.Ok)
                        DebugOps.Complain(this, code, error);
#endif
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IBinder Binder
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return binder;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    binder = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public CultureInfo CultureInfo
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return cultureInfo;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    cultureInfo = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Be relatively quiet (i.e. suppress complaints)?  This is
        //       exposed as a public property; however, it should only be
        //       used in circumstances where it is extremely undesirable
        //       to have any extraneous output sent to the interpreter
        //       host (e.g. the console) because it can prevent important
        //       warnings and other information from being displayed.  An
        //       example is that MSBuild (v3.5) appears to interpret output
        //       being sent to the standard error channel as an indication
        //       that an "Exec" task has failed, even if the exit code
        //       of the command is zero.
        //
        public bool Quiet
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return quiet;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    quiet = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if POLICY_TRACE
        public bool PolicyTrace
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return policyTrace;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    policyTrace = value;
                }
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NETWORK
        public NewWebClientCallback NewWebClientCallback
        {
            get { CheckDisposed(); lock (syncRoot) { return newWebClientCallback; } }
            set { CheckDisposed(); lock (syncRoot) { newWebClientCallback = value; } }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string BackgroundError
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return backgroundError;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    backgroundError = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string Unknown
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return PrivateUnknown;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    PrivateUnknown = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string GlobalUnknown
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return unknown;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    unknown = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string NamespaceUnknown
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    INamespace currentNamespace = null;

                    if ((GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default,
                            ref currentNamespace) == ReturnCode.Ok) &&
                        (currentNamespace != null))
                    {
                        return currentNamespace.Unknown;
                    }

                    return null;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    INamespace currentNamespace = null;

                    if ((GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default,
                            ref currentNamespace) == ReturnCode.Ok) &&
                        (currentNamespace != null))
                    {
                        currentNamespace.Unknown = value;
                    }
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string PackageUnknown
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return packageUnknown;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    packageUnknown = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
#if ISOLATED_PLUGINS
        internal IHost CoreHost
        {
            get
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    return coreHost;
                }
            }
            set
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    coreHost = value;
                }
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private IHost PrivateHost
        {
            get { /* NO-LOCK */ return host; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private string PrivateUnknown /* WARNING: Assumes lock is held. */
        {
            get
            {
                if (!disposed && AreNamespacesEnabled())
                {
                    string result;
                    INamespace currentNamespace = null;

                    if ((GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default,
                            ref currentNamespace) == ReturnCode.Ok) &&
                        (currentNamespace != null))
                    {
                        result = currentNamespace.Unknown;

                        if (result != null)
                            return result;
                    }

                    if (globalNamespace != null)
                    {
                        result = globalNamespace.Unknown;

                        if (result != null)
                            return result;
                    }
                }

                return unknown; /* NOTE: *COMPAT* Eagle beta. */
            }
            set
            {
                if (!disposed && AreNamespacesEnabled())
                {
                    INamespace currentNamespace = null;

                    if ((GetCurrentNamespaceViaResolvers(
                            null, LookupFlags.Default,
                            ref currentNamespace) == ReturnCode.Ok) &&
                        (currentNamespace != null))
                    {
                        currentNamespace.Unknown = value;
                        return;
                    }

                    if (globalNamespace != null)
                    {
                        globalNamespace.Unknown = value;
                        return;
                    }
                }

                unknown = value; /* NOTE: *COMPAT* Eagle beta. */
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private string GetUnknown(
            EngineFlags engineFlags
            )
        {
            if (Engine.HasGlobalOnly(engineFlags))
                return unknown; /* FIELD */

            return PrivateUnknown; /* PROPERTY */
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AttemptToUseUnknown(
            ReturnCode returnCode,
            EngineFlags engineFlags,
            LookupFlags lookupFlags,
            ArgumentList arguments,
            ref IExecute execute,
            ref bool useUnknown
            )
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                string unknownText = GetUnknown(engineFlags);

                if ((unknownText != null) && (UnknownLevels == 0))
                {
                    StringList unknownList = null;

                    if ((Parser.SplitList(
                            this, unknownText, 0, Length.Invalid, true,
                            ref unknownList) == ReturnCode.Ok) &&
                        (unknownList.Count > 0))
                    {
                        if (GetIExecuteViaResolvers(
                                engineFlags | EngineFlags.ToExecute,
                                unknownList[0], arguments, lookupFlags,
                                ref execute) == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Prefix the argument list provided by the
                            //       caller with the unknown handler for this
                            //       namespace or interpreter.
                            //
                            arguments.InsertRange(0, unknownList);

                            //
                            // NOTE: Set the unknown flag so that the we can
                            //       properly modify the unknown nesting level
                            //       (below) prior to actually executing
                            //       [unknown]; otherwise, infinite recursion
                            //       may result.
                            //
                            useUnknown = true;

                            //
                            // NOTE: The unknown handler is available.  Have
                            //       the caller try to use it by indicating
                            //       success here.
                            //
                            return ReturnCode.Ok;
                        }
                    }
                }

                return returnCode;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool ShouldBeQuiet()
        {
            // CheckDisposed();

            return ShouldBeQuiet(DebugOps.GetDefaultQuiet(DefaultQuiet));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This method uses more-or-less the same general idea as the
        //       SafeGetQuiet method of the DebugOps class; however, this one
        //       avoids causing an exception to be thrown (and caught) by
        //       accessing the quiet field directly instead of via the property.
        //
        internal bool ShouldBeQuiet(
            bool @default
            )
        {
            // CheckDisposed();

            if (quiet) /* FIELD */
                return true;

            //
            // HOOK: Allow the test suite (and others components) to override
            //       the quietness setting via the environment.
            //
            if (CommonOps.Environment.GetVariable(EnvVars.Quiet) != null)
                return true;

            return @default;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool HasNoBackgroundError()
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.NoBackgroundError, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void SetNoBackgroundError(
            bool noBackgroundError
            )
        {
            if (noBackgroundError)
                interpreterFlags |= InterpreterFlags.NoBackgroundError;
            else
                interpreterFlags &= ~InterpreterFlags.NoBackgroundError;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Xml Data Handling
#if XML
        public bool ValidateXml
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return validateXml;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    validateXml = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool AllXml
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return allXml;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    allXml = value;
                }
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Initialization & Termination
        public bool Exit
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return exit;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    exit = value;

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Interpreter, NotifyFlags.Exit,
                        exit, this,
                        null, null, null);
#endif
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ExitCode ExitCode
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return exitCode;
                }

            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    exitCode = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private bool PrivateExit
        {
            get { /* NO-LOCK */ return exit; }
            set { /* NO-LOCK */ exit = value; }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Event Queue Management
        public int SleepTime
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return sleepTime;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    sleepTime = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IEventManager EventManager
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return eventManager;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public EventFlags ServiceEventFlags
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return serviceEventFlags;
                }
            }
            private set
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    serviceEventFlags = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode QueueScript(
            DateTime dateTime,
            string text,
            ref Result error
            )
        {
            CheckDisposed();

            IEvent @event = null;

            return QueueScript(dateTime, text, ref @event, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode QueueScript(
            DateTime dateTime,
            string text,
            ref IEvent @event,
            ref Result error
            )
        {
            CheckDisposed();

            //
            // BUGFIX: Prevent deadlock caused by holding the interpreter lock
            //         while calling the QueueScript method, which acquires and
            //         holds the event manager lock.  The other thread holds
            //         the event manager lock via the DequeueAnyReadyEvent
            //         method and then ends up trying to acquire the
            //         interpreter lock while attempting to get the value of
            //         the NotifyFlags property via the CheckNotifications
            //         method.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            if (EventOps.ManagerIsOk(eventManager))
            {
                return eventManager.QueueScript(
                    dateTime, text, engineFlags, substitutionFlags,
                    queueEventFlags, expressionFlags,
                    EventPriority.QueueScript, ref @event, ref error);
            }
            else
            {
                error = "event manager not available";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Pending Wait Count
        public static bool IsPendingWait(
            Interpreter interpreter
            )
        {
            return (interpreter != null) ? interpreter.IsPendingWait() : false;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal int WaitCount
        {
            get { return waitCount; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int WaitSpinCount
        {
            get { return waitSpinCount; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IScript CreateAfterScript(
            string name,
            string group,
            string description,
            string type,
            string text,
            DateTime timeStamp,
            EngineMode engineMode,
            ScriptFlags scriptFlags,
            IClientData clientData,
            bool idle
            )
        {
            return Script.Create(
                name, group, description, type, text, timeStamp,
                engineMode, scriptFlags,
                engineFlags | EngineFlags.EvaluateGlobal,
                substitutionFlags, afterEventFlags |
                    (idle ? EventFlags.Idle : EventFlags.None) |
                    EventFlags.Interpreter, expressionFlags,
                clientData);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EventFlags CombineEngineEventFlags(
            EventFlags eventFlags
            )
        {
            return FlagOps.HasFlags(eventFlags, EventFlags.Interpreter, true) ?
                engineEventFlags | (eventFlags & ~EventFlags.DequeueMask) :
                eventFlags;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void ClearEvents()
        {
            //
            // BUGFIX: Prevent deadlock caused by holding the interpreter lock
            //         while calling the ClearEvents method, which acquires and
            //         holds the event manager lock.  The other thread holds
            //         the event manager lock via the DequeueAnyReadyEvent
            //         method and then ends up trying to acquire the
            //         interpreter lock while attempting to get the value of
            //         the NotifyFlags property via the CheckNotifications
            //         method.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            if (EventOps.ManagerIsOk(eventManager))
            {
                ReturnCode code;
                Result error = null;

                code = eventManager.ClearEvents(ref error);

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode QueueScript( /* ScriptThread USE ONLY */
            DateTime dateTime,
            string text,
            EventFlags eventFlags,
            ref Result error
            )
        {
            // CheckDisposed();

            //
            // BUGFIX: Prevent deadlock caused by holding the interpreter lock
            //         while calling the QueueScript method, which acquires and
            //         holds the event manager lock.  The other thread holds
            //         the event manager lock via the DequeueAnyReadyEvent
            //         method and then ends up trying to acquire the
            //         interpreter lock while attempting to get the value of
            //         the NotifyFlags property via the CheckNotifications
            //         method.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            if (EventOps.ManagerIsOk(eventManager))
            {
                return eventManager.QueueScript(
                    dateTime, text, engineFlags, substitutionFlags,
                    eventFlags, expressionFlags, EventPriority.QueueScript,
                    ref error);
            }
            else
            {
                error = "event manager not available";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int GetSleepTime()
        {
            //
            // BUGFIX: Prevent possible future deadlock caused by holding the
            //         interpreter lock while calling the GetSleepTime method,
            //         which may at some point acquire and hold the event
            //         manager lock.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            return (EventOps.ManagerIsOk(eventManager)) ?
                eventManager.GetSleepTime() :
                _Public.EventManager.DefaultSleepTime;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int GetMinimumSleepTime()
        {
            //
            // BUGFIX: Prevent possible future deadlock caused by holding the
            //         interpreter lock while calling the GetMinimumSleepTime
            //         method, which may at some point acquire and hold the
            //         event manager lock.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            //
            // BUGFIX: Since this method is called from Dispose, do not attempt
            //         to access the event manager if it too has already been
            //         disposed.
            //
            return (EventOps.ManagerIsOk(eventManager)) ?
                eventManager.GetMinimumSleepTime() :
                _Public.EventManager.MinimumSleepTime;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Pending Wait Count
        private bool IsPendingWait()
        {
            return (waitCount > 0);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterWait()
        {
            return Interlocked.Increment(ref waitCount);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitWait()
        {
            return Interlocked.Decrement(ref waitCount);
        }
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Entity Management
        public IEntityManager EntityManager
        {
            get
            {
                CheckDisposed();

                return this;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interpreter Management
        public IInterpreterManager InterpreterManager
        {
            get
            {
                CheckDisposed();

                return this;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Argument & Option Handling
        public ReturnCode GetOptions(
            OptionDictionary options,
            ArgumentList arguments,
            int listCount /* for MustBeIndex, the count of the list tied to the option(s) */,
            int startIndex,
            int stopIndex,
            bool strict, /* raise an error if any unknown option is encountered (instead of stopping). */
            ref int nextIndex /* upon success, location of the first non-option argument. */,
            ref Result error
            )
        {
            CheckDisposed();

            int endIndex = Index.Invalid;

            return GetOptions(
                options, arguments, listCount, startIndex, stopIndex,
                strict ? OptionBehaviorFlags.Strict : OptionBehaviorFlags.Default,
                true, false, false, ref nextIndex, ref endIndex, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetArguments(
            StringList arguments,
            ref Result error
            )
        {
            CheckDisposed();

            return SetArguments(arguments, true, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetArguments(
            StringList arguments,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code;

            if (arguments != null)
            {
                code = SetLibraryVariableValue(
                    VariableFlags.None, TclVars.ShellArgumentCount,
                    arguments.Count.ToString(), ref error);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue(
                        VariableFlags.None, TclVars.ShellArguments,
                        arguments.ToString(), ref error);
            }
            else if (!strict)
            {
                code = SetLibraryVariableValue(
                    VariableFlags.None, TclVars.ShellArgumentCount,
                    0.ToString(), ref error);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue(
                        VariableFlags.None, TclVars.ShellArguments,
                        null, ref error);
            }
            else
            {
                error = "invalid arguments";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool HasZeroString()
        {
            return HasZeroString(interpreterFlags);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool HasZeroString(
            InterpreterFlags interpreterFlags
            )
        {
#if !MONO && NATIVE && WINDOWS
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.ZeroString, true);
#else
            return false;
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetOptions(
            OptionDictionary options,
            ArgumentList arguments,
            int listCount,
            int startIndex,
            int stopIndex,
            OptionBehaviorFlags flags,
            bool strict,
            ref int nextIndex,
            ref Result error
            )
        {
            int endIndex = Index.Invalid;

            return GetOptions(
                options, arguments, listCount, startIndex, stopIndex, flags |
                (strict ? OptionBehaviorFlags.Strict : OptionBehaviorFlags.Default),
                true, false, false, ref nextIndex, ref endIndex, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This is the "Universal Option Parser".
        //
        internal ReturnCode GetOptions(
            OptionDictionary options,
            ArgumentList arguments,
            int listCount /* for MustBeIndex, the count of the list tied to the option(s) */,
            int startIndex,
            int stopIndex,
            OptionBehaviorFlags behaviorFlags, /* do we want to stop, error, or ignore unknown options? */
            bool noCase, /* case-insensitive option names? */
            bool noValue, /* do not try to interpret strings as values of any kind. */
            bool noSet, /* scan mode, do not set any values (no changes to options dictionary). */
            ref int nextIndex, /* upon success, location of the first non-option argument. */
            ref int endIndex, /* upon success, location of EndOfOptions if found, otherwise unchanged. */
            ref Result error
            )
        {
            ReturnCode code;

            if (options != null)
            {
                if (arguments != null)
                {
                    int argumentCount = arguments.Count;

                    if (ListOps.CheckStartAndStopIndex(
                            0, argumentCount - 1, ref startIndex, ref stopIndex, ref error))
                    {
                        code = ReturnCode.Ok;

                        for (int argumentIndex = startIndex; argumentIndex <= stopIndex; argumentIndex++)
                        {
                            Argument currentArgument = arguments[argumentIndex];
                            string current = currentArgument;

                            Argument nextArgument = ((argumentIndex + 1) <= stopIndex) ?
                                arguments[argumentIndex + 1] : null;

                            string next = nextArgument;

                            //
                            // NOTE: If this is the last argument, make sure it can be
                            //       treated as a "possible option".  If not, stop now.
                            //
                            if ((argumentIndex == stopIndex) &&
                                FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.LastIsNonOption, true))
                            {
                                nextIndex = argumentIndex;
                                break;
                            }

                            if (Option.IsEndOfOptions(current))
                            {
                                if (options.Has(Option.EndOfOptions))
                                {
                                    if ((argumentIndex + 1) < argumentCount)
                                        nextIndex = argumentIndex + 1;
                                    else
                                        nextIndex = Index.Invalid;

                                    endIndex = argumentIndex;
                                    break;
                                }
                                else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.ErrorOnEndOfOptions, true))
                                {
                                    //
                                    // NOTE: This is rarely used because if they do not
                                    //       explicitly allow the end-of-options marker
                                    //       they normally also want it to be considered
                                    //       the first "non-option" argument.
                                    //
                                    error = "unexpected end-of-options marker";
                                    code = ReturnCode.Error;
                                    break;
                                }
                                else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.StopOnEndOfOptions, true))
                                {
                                    //
                                    // NOTE: This end-of-options marker is not a valid
                                    //       option and we want to stop now because we
                                    //       want to assume it is the first non-option
                                    //       argument.  This is the default behavior.
                                    //
                                    nextIndex = argumentIndex;
                                    break;
                                }
                                else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.IgnoreOnEndOfOptions, true))
                                {
                                    //
                                    // NOTE: This end-of-options marker is not a valid
                                    //       option and we want to simply ignore it.
                                    //       We may also want to skip the next argument.
                                    //       This behavior should almost never be used
                                    //       unless the caller is 100% sure what it does.
                                    //
                                    if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.SkipOnEndOfOptions, true))
                                        argumentIndex++;
                                }
                            }
                            else if (Option.LooksLikeOption(current))
                            {
                                IOption option = null;
                                Result localError = null;

                                if (options.TryResolve(current, true, noCase,
                                        ref option, ref localError) == ReturnCode.Ok)
                                {
                                    if (option != null)
                                    {
                                        if (option.IsIgnored(options))
                                        {
                                            if (option.MustHaveValue(options))
                                            {
                                                if (next != null)
                                                {
                                                    argumentIndex++; // skip option value...
                                                }
                                                else
                                                {
                                                    error = String.Format(
                                                        "\"{0}\" option must be followed by {1}",
                                                        current, option.ToString(option.Flags));

                                                    code = ReturnCode.Error;
                                                    break;
                                                }
                                            }
                                        }
                                        else if (!option.CanBePresent(options, ref error))
                                        {
                                            code = ReturnCode.Error;
                                            break;
                                        }
                                        else if (option.HasFlags(OptionFlags.EndOfOptions, true))
                                        {
                                            if ((argumentIndex + 1) < argumentCount)
                                                nextIndex = argumentIndex + 1;
                                            else
                                                nextIndex = Index.Invalid;

                                            endIndex = argumentIndex;
                                            break;
                                        }
                                        else if (option.IsUnsafe(options) && IsSafe())
                                        {
                                            error = String.Format(
                                                "permission denied: safe interpreter cannot use option \"{0}\"",
                                                option.Name);

                                            code = ReturnCode.Error;
                                        }
                                        else if (option.MustHaveValue(options))
                                        {
#if !MONO && NATIVE && WINDOWS
                                            bool canZero = HasZeroString();
#endif

                                            bool zero = false;

                                            try
                                            {
                                                if (next != null)
                                                {
                                                    //
                                                    // NOTE: Initially, this value of this option is null.  The block
                                                    //       below has the implicit guarantee that either the option
                                                    //       value will be set to something non-null OR the return
                                                    //       code will be set to something non-Ok.
                                                    //
                                                    Variant variant = null;

                                                    //
                                                    // NOTE: Are we allowed to interpret the string as the type of
                                                    //       value required for this option?  Otherwise, we will not
                                                    //       attempt any conversion and if we are in non-scan mode
                                                    //       the final option value will be set as a string.  We
                                                    //       assume that the caller knows this.
                                                    //
                                                    if (!noValue)
                                                    {
                                                        //
                                                        // NOTE: Does this option require strict value recognition
                                                        //       semantics?
                                                        //
                                                        bool strictOption = option.IsStrict(options);

                                                        //
                                                        // NOTE: Does this option not care about case?
                                                        //
                                                        bool noCaseOption = option.IsNoCase(options);

                                                        //
                                                        // NOTE: Ok, now figure out what kind of value this option
                                                        //       requires and try to parse it from the option value
                                                        //       string.
                                                        //
                                                        if (option.HasFlags(OptionFlags.MustBeTypeList, true))
                                                        {
                                                            TypeList typeList = null;
                                                            ResultList errors = null;

                                                            code = Value.GetTypeList(
                                                                this, next, appDomain, Value.GetTypeValueFlags(
                                                                    strictOption, false, noCase || noCaseOption),
                                                                cultureInfo, ref typeList, ref errors);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(typeList);
                                                            else
                                                                error = errors;
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeReturnCodeList, true))
                                                        {
                                                            ReturnCodeList returnCodeList = null;

                                                            code = Value.GetReturnCodeList(next, cultureInfo,
                                                                ref returnCodeList, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(returnCodeList);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeVersion, true))
                                                        {
                                                            Version version = null;

                                                            code = Value.GetVersion(next, cultureInfo,
                                                                ref version, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(version);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeAlias, true))
                                                        {
                                                            IAlias alias = null;

                                                            code = GetAlias(next, LookupFlags.Default, ref alias, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(alias);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeOption, true))
                                                        {
                                                            IOption optionValue = Option.FromString(
                                                                this, next, appDomain, strictOption, false,
                                                                noCase || noCaseOption, cultureInfo, ref error);

                                                            if (optionValue != null)
                                                                variant = new Variant(optionValue);
                                                            else
                                                                code = ReturnCode.Error;
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeAbsoluteNamespace, true))
                                                        {
                                                            if (AreNamespacesEnabled())
                                                            {
                                                                INamespace @namespace = NamespaceOps.Lookup(
                                                                    this, next, true, false, ref error);

                                                                if (@namespace != null)
                                                                    variant = new Variant(@namespace);
                                                                else
                                                                    code = ReturnCode.Error;
                                                            }
                                                            else
                                                            {
                                                                error = "namespaces not available";
                                                                code = ReturnCode.Error;
                                                            }
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeRelativeNamespace, true))
                                                        {
                                                            if (AreNamespacesEnabled())
                                                            {
                                                                INamespace @namespace = NamespaceOps.Lookup(
                                                                    this, next, false, false, ref error);

                                                                if (@namespace != null)
                                                                    variant = new Variant(@namespace);
                                                                else
                                                                    code = ReturnCode.Error;
                                                            }
                                                            else
                                                            {
                                                                error = "namespaces not available";
                                                                code = ReturnCode.Error;
                                                            }
                                                        }
#if NATIVE && TCL
                                                        else if (option.HasFlags(OptionFlags.MustBeTclInterpreter, true))
                                                        {
                                                            IntPtr interp = IntPtr.Zero;

#if TCL_THREADS
                                                            bool fromThread = false;

                                                            code = GetTclInterpreterOrThread(
                                                                next, LookupFlags.Default, ref interp, ref fromThread,
                                                                ref error);
#else
                                                            code = GetTclInterpreter(
                                                                next, LookupFlags.Default, ref interp, ref error);
#endif

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(next); /* interpName */
                                                        }
#endif
                                                        else if (option.HasFlags(OptionFlags.MustBeType, true))
                                                        {
                                                            Type type = null;
                                                            ResultList errors = null;

                                                            code = Value.GetType(
                                                                this, next, appDomain, Value.GetTypeValueFlags(
                                                                    strictOption, false, noCase || noCaseOption),
                                                                cultureInfo, ref type, ref errors);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(type);
                                                            else
                                                                error = errors;
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeInterpreter, true))
                                                        {
                                                            Interpreter interpreter = null;

                                                            code = Value.GetInterpreter(
                                                                this, next, InterpreterType.Default, ref interpreter,
                                                                ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(interpreter);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeObject, true))
                                                        {
                                                            IObject @object = null;

                                                            code = GetObject(next, LookupFlags.Default, ref @object, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(@object);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeValue, true))
                                                        {
                                                            object value = null;

                                                            code = Value.GetValue(next, dateTimeFormat, ValueFlags.AnyStrict,
                                                                cultureInfo, ref value, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(value);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeList, true))
                                                        {
                                                            StringList list = null;

                                                            //
                                                            // TODO: *PERF* We cannot have this call to SplitList perform any
                                                            //       caching because we do not know exactly what the resulting
                                                            //       list will be used for.
                                                            //
                                                            code = Parser.SplitList(
                                                                this, next, 0, Length.Invalid, false, ref list,
                                                                ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(list);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeDictionary, true))
                                                        {
                                                            StringList list = null;

                                                            //
                                                            // TODO: *PERF* We cannot have this call to SplitList perform any
                                                            //       caching because we do not know exactly what the resulting
                                                            //       list will be used for.
                                                            //
                                                            code = Parser.SplitList(
                                                                this, next, 0, Length.Invalid, false, ref list,
                                                                ref error);

                                                            if (code == ReturnCode.Ok)
                                                            {
                                                                if ((list.Count % 2) == 0)
                                                                {
                                                                    try
                                                                    {
                                                                        variant = new Variant(
                                                                            new StringDictionary(list, true, true));
                                                                    }
                                                                    catch (Exception e)
                                                                    {
                                                                        error = e;
                                                                        code = ReturnCode.Error;
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    error = "dictionary list must have an even number of elements";
                                                                    code = ReturnCode.Error;
                                                                }
                                                            }
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeDateTime, true))
                                                        {
                                                            DateTime dateTime = DateTime.MinValue;

                                                            code = Value.GetDateTime2(next, dateTimeFormat, strictOption ?
                                                                ValueFlags.AnyStrictDateTime : ValueFlags.AnyDateTime,
                                                                dateTimeKind, cultureInfo, ref dateTime, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(dateTime);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeTimeSpan, true))
                                                        {
                                                            TimeSpan timeSpan = TimeSpan.Zero;

                                                            code = Value.GetTimeSpan2(next, strictOption ?
                                                                ValueFlags.AnyStrictTimeSpan : ValueFlags.AnyTimeSpan,
                                                                cultureInfo, ref timeSpan, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(timeSpan);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeGuid, true))
                                                        {
                                                            Guid guid = Guid.Empty;

                                                            code = Value.GetGuid(next, cultureInfo, ref guid, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(guid);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeEnum, true))
                                                        {
                                                            if (option.Type != null)
                                                            {
                                                                if (option.Type.IsEnum)
                                                                {
                                                                    object enumValue;

                                                                    //
                                                                    // NOTE: Reset the local error result here because we check it
                                                                    //       below (i.e. it will not be set by TryParseEnum).
                                                                    //
                                                                    localError = null;

                                                                    if (EnumOps.IsFlagsEnum(option.Type))
                                                                        enumValue = EnumOps.TryParseFlagsEnum(
                                                                            this, option.Type, (option.Value != null) ?
                                                                                option.Value.ToString() : null, next,
                                                                            cultureInfo, strictOption, noCase || noCaseOption,
                                                                            ref localError);
                                                                    else
                                                                        enumValue = EnumOps.TryParseEnum(
                                                                            option.Type, next, noCase || noCaseOption);

                                                                    //
                                                                    // NOTE: Did we end up with a valid enum value for this type?
                                                                    //
                                                                    if (enumValue != null)
                                                                    {
                                                                        //
                                                                        // NOTE: It is now guaranteed to be the correct Enum type because
                                                                        //       TryParseEnum uses our System.Type object directly and
                                                                        //       cannot return non-null unless Enum.Parse succeeds.
                                                                        //
                                                                        variant = new Variant(enumValue);
                                                                    }
                                                                    else
                                                                    {
                                                                        //
                                                                        // NOTE: Retain any locally generated error information (from
                                                                        //       TryParseFlagsEnum) because it provides more specific
                                                                        //       feedback than we can at this point.
                                                                        //
                                                                        if (!String.IsNullOrEmpty(localError))
                                                                            error = localError;
                                                                        else
                                                                            error = ScriptOps.BadValue(
                                                                                null, String.Format("\"{0}\" value", option.Type.FullName),
                                                                                next, Enum.GetNames(option.Type), null, null);

                                                                        code = ReturnCode.Error;
                                                                    }
                                                                }
                                                                else
                                                                {
                                                                    error = String.Format(
                                                                        "option \"{0}\" base type is not an enum",
                                                                        option.Name);

                                                                    code = ReturnCode.Error;
                                                                }
                                                            }
                                                            else
                                                            {
                                                                error = String.Format(
                                                                    "option \"{0}\" has an invalid base type",
                                                                    option.Name);

                                                                code = ReturnCode.Error;
                                                            }
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeReturnCode, true))
                                                        {
                                                            ReturnCode returnCode = ReturnCode.Ok;

                                                            code = Value.GetReturnCode2(next, ValueFlags.AnyReturnCode,
                                                                cultureInfo, ref returnCode, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(returnCode);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeMatchMode, true))
                                                        {
                                                            MatchMode matchMode = MatchMode.None;

                                                            code = Value.GetMatchMode2(this,
                                                                (option.Value != null) ? option.Value.ToString() : null,
                                                                next, strictOption ? ValueFlags.AnyStrictMatchMode :
                                                                ValueFlags.AnyMatchMode, cultureInfo, ref matchMode,
                                                                ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(matchMode);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeLevel, true))
                                                        {
                                                            ICallFrame otherFrame = null;

                                                            if (GetCallFrame(
                                                                    next, ref otherFrame,
                                                                    ref error) != FrameResult.Invalid)
                                                            {
                                                                variant = new Variant(otherFrame);
                                                            }
                                                            else
                                                            {
                                                                code = ReturnCode.Error;
                                                            }
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeIndex, true))
                                                        {
                                                            int index = Index.Invalid;

                                                            code = Value.GetIndex(next, listCount, cultureInfo,
                                                                ref index, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(index);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeWideInteger, true))
                                                        {
                                                            long longValue = 0;

                                                            code = Value.GetWideInteger2(next, ValueFlags.AnyWideInteger,
                                                                cultureInfo, ref longValue, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(longValue);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeInteger, true))
                                                        {
                                                            int intValue = 0;

                                                            code = Value.GetInteger2(next, ValueFlags.AnyInteger,
                                                                cultureInfo, ref intValue, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(intValue);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeBoolean, true))
                                                        {
                                                            bool boolValue = false;

                                                            code = Value.GetBoolean2(next, strictOption ?
                                                                ValueFlags.AnyStrictBoolean : ValueFlags.AnyBoolean,
                                                                cultureInfo, ref boolValue, ref error);

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(boolValue);
                                                        }
                                                        else if (option.HasFlags(OptionFlags.MustBeSecureString, true))
                                                        {
                                                            zero = true;

                                                            SecureString secureStringValue = null;
                                                            IObject @object = null;

                                                            if (GetObject(
                                                                    next, LookupFlags.Default, ref @object,
                                                                    ref error) == ReturnCode.Ok)
                                                            {
                                                                if (@object.Value is SecureString)
                                                                {
                                                                    secureStringValue = (SecureString)@object.Value;
                                                                }
                                                                else
                                                                {
                                                                    error = "invalid secure string";
                                                                    code = ReturnCode.Error;
                                                                }
                                                            }
                                                            else
                                                            {
                                                                secureStringValue = new SecureString();

                                                                foreach (char character in next)
                                                                    secureStringValue.AppendChar(character);

                                                                secureStringValue.MakeReadOnly();
                                                            }

                                                            if (code == ReturnCode.Ok)
                                                                variant = new Variant(secureStringValue);
                                                        }
                                                        else
                                                        {
                                                            //
                                                            // NOTE: No strongly-typed value flags were set for this
                                                            //       option, just use the string verbatim.
                                                            //
                                                            variant = new Variant(next); // String
                                                        }
                                                    }
                                                    else
                                                    {
                                                        //
                                                        // NOTE: We are forbidden from interpreting the string as a
                                                        //       strongly-typed value, just use the string verbatim.
                                                        //
                                                        variant = new Variant(next); // String
                                                    }

                                                    //
                                                    // NOTE: If we succeeded, set the option value; otherwise, bail.
                                                    //
                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        if (!noSet)
                                                            option.SetPresent(options, true, argumentIndex, variant);

                                                        argumentIndex++; // skip option value...
                                                    }
                                                    else
                                                    {
                                                        break;
                                                    }
                                                }
                                                else
                                                {
                                                    error = String.Format(
                                                        "\"{0}\" option must be followed by {1}",
                                                        current, option.ToString(option.Flags));

                                                    code = ReturnCode.Error;
                                                    break;
                                                }
                                            }
                                            finally
                                            {
                                                if (zero)
                                                {
                                                    //
                                                    // HACK: Attempt to forcibly "scrub"
                                                    //       the plain-text option value
                                                    //       from memory via whatever
                                                    //       means are available.
                                                    //
                                                    if (nextArgument != null)
                                                        nextArgument.ResetValue(this, true);

                                                    if (localError != null)
                                                        localError.ResetValue(this, true);

                                                    if (error != null)
                                                        error.ResetValue(this, true);

#if !MONO && NATIVE && WINDOWS
                                                    if (canZero)
                                                    {
                                                        ReturnCode scrubCode;
                                                        Result scrubError = null;

                                                        scrubCode = StringOps.ZeroString(
                                                            next, ref scrubError);

                                                        if (scrubCode != ReturnCode.Ok)
                                                            DebugOps.Complain(this, scrubCode, scrubError);
                                                    }
#endif

                                                    ObjectOps.CollectGarbage(); /* throw */
                                                }
                                            }
                                        }
                                        else if (!noSet)
                                        {
                                            option.SetPresent(options, true, argumentIndex, null);
                                        }
                                    }
                                }
                                else
                                {
                                    if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.ErrorOnUnknownOption, true))
                                    {
                                        //
                                        // NOTE: This is not a valid option and we want to
                                        //       treat this as an error.
                                        //
                                        error = localError;
                                        code = ReturnCode.Error;
                                        break;
                                    }
                                    else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.StopOnUnknownOption, true))
                                    {
                                        //
                                        // NOTE: This is not a valid option and we want to
                                        //       stop now because we want to assume it is
                                        //       the first non-option argument.  This is
                                        //       the default behavior.
                                        //
                                        nextIndex = argumentIndex;
                                        break;
                                    }
                                    else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.IgnoreOnUnknownOption, true))
                                    {
                                        //
                                        // NOTE: This is not a valid option and we want to
                                        //       simply ignore it.  We may also want to skip
                                        //       the next argument.
                                        //
                                        if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.SkipOnUnknownOption, true))
                                            argumentIndex++;
                                    }
                                }
                            }
                            else
                            {
                                if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.ErrorOnNonOption, true))
                                {
                                    //
                                    // NOTE: This is a non-option and we want to treat
                                    //       this as an error.
                                    //
                                    error = String.Format(
                                        "unexpected non-option argument \"{0}\"",
                                        current);

                                    code = ReturnCode.Error;
                                    break;
                                }
                                else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.StopOnNonOption, true))
                                {
                                    //
                                    // NOTE: This is a non-option and we want to stop
                                    //       now because we want to treat it as the
                                    //       first non-option argument.  This is the
                                    //       default behavior.
                                    //
                                    nextIndex = argumentIndex;
                                    break;
                                }
                                else if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.IgnoreOnNonOption, true))
                                {
                                    //
                                    // NOTE: This is a non-option and we want to simply
                                    //       ignore it.  We may also want to skip the
                                    //       next argument.
                                    //
                                    if (FlagOps.HasFlags(behaviorFlags, OptionBehaviorFlags.SkipOnNonOption, true))
                                        argumentIndex++;
                                }
                            }
                        }
                    }
                    else
                    {
                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    error = "invalid arguments";
                    code = ReturnCode.Error;
                }
            }
            else
            {
                error = "invalid options";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode MergeArguments(
            OptionDictionary options,
            ArgumentList arguments1,
            ArgumentList arguments2,
            int startIndex1,
            int startIndex2,
            bool skipName1,
            bool skipName2,
            ref ArgumentList arguments,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Ok;

            //
            // NOTE: The purpose of this method is to properly merge two
            //       arguments lists, including any options, so that the new
            //       combined argument list is constructed in a well-defined
            //       way and can be processed properly by the target command.
            //
            if ((arguments1 != null) || (arguments2 != null))
                arguments = new ArgumentList();
            else
                arguments = null;

            //
            // NOTE: *PHASE 1* Figure out where the options are in the first
            //       argument list (if there are any at all).
            //
            int nextIndex1 = Index.Invalid;
            int endIndex1 = Index.Invalid;

            if (code == ReturnCode.Ok)
            {
                if (startIndex1 < 0)
                    startIndex1 = 0;

                if ((options != null) && (arguments1 != null))
                {
                    if (arguments1.Count > startIndex1)
                    {
                        //
                        // NOTE: Execute the universal option parser in "scan only"
                        //       mode.  We do not want to waste any time processing
                        //       the option values here just to throw them away, we
                        //       just need to know where they end so that we can build
                        //       the final argument list for the target command.
                        //
                        code = GetOptions(
                            options, arguments1, 0, startIndex1, Index.Invalid,
                            OptionBehaviorFlags.Default, true, true, true,
                            ref nextIndex1, ref endIndex1, ref error);
                    }
                }
                else if ((options == null) && (arguments1 != null))
                {
                    //
                    // BUGFIX: We must set the next index even if there are no
                    //         options because the default value means that
                    //         there are "no non-option arguments left".
                    //
                    nextIndex1 = startIndex1;
                }
            }

            //
            // NOTE: *PHASE 2* Figure out where the options are in the second
            //       argument list (if there are any at all).
            //
            int nextIndex2 = Index.Invalid;
            int endIndex2 = Index.Invalid;

            if (code == ReturnCode.Ok)
            {
                if (startIndex2 < 0)
                    startIndex2 = 0;

                if ((options != null) && (arguments2 != null))
                {
                    if (arguments2.Count > startIndex2)
                    {
                        //
                        // NOTE: Execute the universal option parser in "scan only"
                        //       mode.  We do not want to waste any time processing
                        //       the option values here just to throw them away, we
                        //       just need to know where they end so that we can build
                        //       the final argument list for the target command.
                        //
                        code = GetOptions(
                            options, arguments2, 0, startIndex2, Index.Invalid,
                            OptionBehaviorFlags.Default, true, true, true,
                            ref nextIndex2, ref endIndex2, ref error);
                    }
                }
                else if ((options == null) && (arguments2 != null))
                {
                    //
                    // BUGFIX: We must set the next index even if there are no
                    //         options because the default value means that
                    //         there are "no non-option arguments left".
                    //
                    nextIndex2 = startIndex2;
                }
            }

            //
            // NOTE: *PHASE 3* With the information gathered above, perform the
            //       merge of the two argument lists into one, retaining the
            //       options chosen and any trailing end-of-options marker we
            //       find (one maximum).
            //
            if (code == ReturnCode.Ok)
            {
                //
                // NOTE: Process the arguments from the first list, if any.
                //
                if (arguments1 != null)
                {
                    //
                    // NOTE: Figure out where we need to stop adding option
                    //       arguments from the first list.
                    //
                    int stopIndex1;

                    if (endIndex1 != Index.Invalid) /* Exclude EndOfOptions? */
                        stopIndex1 = endIndex1 - ((arguments2 != null) ? 1 : 0);
                    else if ((nextIndex1 != Index.Invalid) && (nextIndex1 > 0))
                        stopIndex1 = nextIndex1 - 1; /* Before First Non-Option */
                    else
                        stopIndex1 = arguments1.Count - 1; /* All */

                    //
                    // NOTE: First, we want all the arguments from the first list
                    //       except the trailing end-of-options marker, if any.
                    //
                    for (int argumentIndex1 = (skipName1 ? 1 : 0);
                            argumentIndex1 <= stopIndex1;
                            argumentIndex1++)
                    {
                        arguments.Add(arguments1[argumentIndex1]);
                    }
                }

                //
                // NOTE: Process the arguments from the second list, if any.
                //
                if (arguments2 != null)
                {
                    //
                    // NOTE: Figure out where we need to stop adding option
                    //       arguments from the second list.
                    //
                    int stopIndex2;

                    if (endIndex2 != Index.Invalid)
                        stopIndex2 = endIndex2; /* Include EndOfOptions */
                    else if ((nextIndex2 != Index.Invalid) && (nextIndex2 > 0))
                        stopIndex2 = nextIndex2 - 1; /* Before First Non-Option */
                    else
                        stopIndex2 = Index.Invalid; /* None */

                    //
                    // NOTE: Next, we want all the option arguments from the second
                    //       list, including the trailing end-of-options marker, if
                    //       any.  If there is no trailing end-of-options marker in
                    //       the second list and there was in the first list, we
                    //       "move" the one from the first list to the end of the
                    //       options arguments for the second list.
                    //
                    if (stopIndex2 != Index.Invalid)
                    {
                        for (int argumentIndex2 = startIndex2;
                                argumentIndex2 <= stopIndex2; argumentIndex2++)
                        {
                            arguments.Add(arguments2[argumentIndex2]);
                        }
                    }

                    //
                    // NOTE: Next, if the first list had a trailing end-of-options
                    //       marker (which we skipped) and the second list does not,
                    //       add it to the resulting argument list now.
                    //
                    if ((endIndex1 != Index.Invalid) && (endIndex2 == Index.Invalid))
                        arguments.Add(Option.EndOfOptions);

                    //
                    // NOTE: Next, we want all the [non-option] arguments from the
                    //       second list starting at the beginning of the list and
                    //       ending before the first option argument.
                    //
                    for (int argumentIndex2 = (skipName2 ? 1 : 0);
                            (argumentIndex2 < arguments2.Count) &&
                            (argumentIndex2 < startIndex2); argumentIndex2++)
                    {
                        arguments.Add(arguments2[argumentIndex2]);
                    }

                    //
                    // NOTE: Finally, we want all the [non-option] arguments from the
                    //       second list starting after the last option argument until
                    //       the end of the list.
                    //
                    if (stopIndex2 != Index.Invalid)
                    {
                        for (int argumentIndex2 = stopIndex2 + 1;
                                argumentIndex2 < arguments2.Count; argumentIndex2++)
                        {
                            arguments.Add(arguments2[argumentIndex2]);
                        }
                    }
                }
            }

            return code;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Data Type Conversion
        public string DateTimeFormat
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return dateTimeFormat;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    dateTimeFormat = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public DateTimeKind DateTimeKind
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return dateTimeKind;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    dateTimeKind = value;
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Expression Precision
        public int Precision /* throw */
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return precision;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    precision = value;
                }

                //
                // NOTE: Do not create the variable if we have been prohibited
                //       from doing so.
                //
                VariableFlags flags = VariableFlags.ViaProperty;

                if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                    FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                {
                    flags |= VariableFlags.NoCreate;
                }

                //
                // NOTE: Update script-level informational variable.
                //
                SetLibraryVariableValue(
                    flags, TclVars.PrecisionName, value.ToString(),
                    precisionTraceList);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal static decimal FixIntermediatePrecision(decimal value)
        {
            return value; /* NOP */
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static double FixIntermediatePrecision(double value)
        {
            return value; /* NOP */
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal decimal FixFinalPrecision(decimal value)
        {
            if (precision > 0)
                return Math.Round(value, precision);
            else if (precision < 0)
                return Math.Round(value, 0);
            else
                return value;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal double FixFinalPrecision(double value)
        {
            if (precision > 0)
                return Math.Round(value, precision);
            else if (precision < 0)
                return Math.Round(value, 0);
            else
                return value;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Execution Limits
        //
        // NOTE: If this value is false, no evaluation [or substitution] requests
        //       can take place using this interpreter.
        //
        public bool Enabled
        {
            get
            {
                CheckDisposed();

                //
                // NOTE: Check both the global flags and the per-thread flags.
                //
                EngineFlags localEngineFlags = EngineFlags;

                return !Engine.HasNoEvaluate(localEngineFlags) &&
                    !Engine.HasNoSubstitute(localEngineFlags);
            }
            set
            {
                CheckDisposed();

                //
                // NOTE: Set the global flags only.
                //
                if (value)
                    engineFlags &= ~EngineFlags.EnabledMask;
                else
                    engineFlags |= EngineFlags.EnabledMask;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: If this value is true, no objects (commands, functions, procecures,
        //       etc) may be added, renamed, or removed and no variables may be added,
        //       set, or unset.
        //
        public bool ReadOnly
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return readOnly;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    readOnly = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: If this value is true, no objects (commands, functions, procecures, etc)
        //       may be renamed or removed and no variables may be changed or unset.
        //
        public bool Immutable
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return immutable;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    immutable = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int ReadyLimit
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return readyLimit;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    readyLimit = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int RecursionLimit
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return recursionLimit;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    recursionLimit = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int Timeout
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return timeout;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    timeout = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int FinallyTimeout
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return finallyTimeout;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    finallyTimeout = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int ThreadStackSize
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return threadStackSize;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    threadStackSize = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int ExtraStackSpace
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return extraStackSpace;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    extraStackSpace = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private bool IsModifiable(
            bool ignoreImmutable
            )
        {
            Result error = null;

            return IsModifiable(ignoreImmutable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsModifiable(
            bool ignoreImmutable,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (disposed)
                {
                    error = "interpreter is disposed";
                    return false;
                }

                if (readOnly)
                {
                    error = "interpreter is read-only";
                    return false;
                }

                if (!ignoreImmutable && immutable)
                {
                    error = "interpreter is immutable";
                    return false;
                }

                return true;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool BeginMutableExecution()
        {
            lock (syncRoot)
            {
                bool savedImmutable = immutable;

                immutable = false;

                return savedImmutable;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void EndMutableExecution(
            bool savedImmutable
            )
        {
            lock (syncRoot)
            {
                immutable = savedImmutable;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PrivateReadyCount
        {
            get { /* NO-LOCK */ return readyCount; }
            set { /* NO-LOCK */ readyCount = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PrivateReadyLimit
        {
            get { /* NO-LOCK */ return readyLimit; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PrivateRecursionLimit
        {
            get { /* NO-LOCK */ return recursionLimit; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PrivateTimeout
        {
            get { /* NO-LOCK */ return timeout; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PrivateFinallyTimeout
        {
            get { /* NO-LOCK */ return finallyTimeout; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ulong InternalExtraStackSpace
        {
            get
            {
                /* NO-LOCK */
                return (extraStackSpace > 0) ?
                    (ulong)extraStackSpace : 0;
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Notifications
#if NOTIFY || NOTIFY_OBJECT
        public ReturnCode FireNotification(
            IScriptEventArgs eventArgs,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            CheckDisposed();

            return FireNotification(this, eventArgs, clientData, arguments, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private bool CanFireNotifications()
        {
            return (NotifyLevels == 0) &&
                !FlagOps.HasFlags(NotifyFlags, NotifyFlags.NoNotify, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool CheckNotifyTypesAndFlags(
            NotifyType type,         /* in */
            NotifyFlags flags        /* in */
            )
        {
            //
            // NOTE: Using the properties instead of the fields here takes
            //       into account the per-thread types and flags as well
            //       because the properties return a bitwise OR of the
            //       global types and flags with the per-thread values.
            //
            if (FlagOps.HasFlags(NotifyTypes, type & NotifyType.CheckMask, true) &&
                FlagOps.HasFlags(NotifyFlags, flags & NotifyFlags.CheckMask, true))
            {
                return true;
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode FireNotification(
            Interpreter interpreter,
            IScriptEventArgs eventArgs,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                if (interpreter.CanFireNotifications())
                {
                    PluginWrapperDictionary plugins = interpreter.CopyPlugins();

                    if (plugins != null)
                    {
                        //
                        // NOTE: Set the initial result to success.
                        //
                        code = ReturnCode.Ok;

                        //
                        // NOTE: Prevent endless event notification recursion.
                        //
                        interpreter.NotifyFlags |= NotifyFlags.NoNotify;

                        try
                        {

                            //
                            // NOTE: Process each trace (as long as they all continue
                            //       to succeed).
                            //
                            foreach (KeyValuePair<string, _Wrappers.Plugin> pair in plugins)
                            {
                                IPlugin plugin = pair.Value;

                                if (plugin != null)
                                {
                                    INotify notify = plugin as INotify;

                                    if (notify != null)
                                    {
                                        try
                                        {
                                            //
                                            // NOTE: Query the plugin to find out which notification
                                            //       types it has elected to receive.
                                            //
                                            NotifyType types = notify.GetTypes(interpreter);

                                            //
                                            // NOTE: Query the plugin to find out which notification
                                            //       sub-types it has elected to receive.
                                            //
                                            NotifyFlags flags = notify.GetFlags(interpreter);

                                            //
                                            // NOTE: Query the event arguments to figure out which
                                            //       notification types are currently being sent.
                                            //
                                            NotifyType hasTypes = (eventArgs != null) ?
                                                eventArgs.NotifyTypes : NotifyType.None;

                                            //
                                            // NOTE: Query the event arguments to figure out which
                                            //       notification sub-types are currently being sent.
                                            //
                                            NotifyFlags hasFlags = (eventArgs != null) ?
                                                eventArgs.NotifyFlags : NotifyFlags.None;

                                            //
                                            // NOTE: Does this plugin want to receive the notifications
                                            //       being sent?
                                            //
                                            if (FlagOps.HasFlags(types, hasTypes & NotifyType.CheckMask, true) &&
                                                FlagOps.HasFlags(flags, hasFlags & NotifyFlags.CheckMask, true))
                                            {
                                                //
                                                // NOTE: Since events can basically do anything they want,
                                                //       we wrap them in a try block to prevent exceptions
                                                //       from escaping.
                                                //
                                                interpreter.EnterNotifyLevel();

                                                try
                                                {
                                                    //
                                                    // NOTE: Call their notification function.  This could
                                                    //       do practially anything; however, in practice it
                                                    //       should not be modifying the state of the passed
                                                    //       in objects, if any.  No guarantee is made about
                                                    //       the ability of plugins to affect changes in the
                                                    //       state of the passed in objects -OR- to alter
                                                    //       the course of action to be taken after the
                                                    //       notification has been processed.
                                                    //
                                                    code = notify.Notify(interpreter, eventArgs, clientData,
                                                        arguments, ref result);
                                                }
                                                finally
                                                {
                                                    interpreter.ExitNotifyLevel();
                                                }
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            //
                                            // NOTE: Translate exceptions to a failure return.
                                            //
                                            result = String.Format(
                                                "caught exception while firing notification: {0}",
                                                e);

                                            code = ReturnCode.Error;
                                        }

                                        //
                                        // NOTE: Check for exception results specially because we
                                        //       treat "Break" different from other return codes.
                                        //
                                        if (code == ReturnCode.Break)
                                        {
                                            //
                                            // NOTE: Success; however, skip processing further
                                            //       events.
                                            //
                                            code = ReturnCode.Ok;
                                            break;
                                        }
                                        else if (code != ReturnCode.Ok)
                                        {
                                            //
                                            // NOTE: Some type of failure (or exception), stop
                                            //       processing events.
                                            //
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        finally
                        {
                            //
                            // NOTE: Remove event notification prevention flag.
                            //
                            interpreter.NotifyFlags &= ~NotifyFlags.NoNotify;
                        }
                    }
                    else
                    {
                        result = "plugins not available";
                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    //
                    // NOTE: Event notifications are disabled or we are
                    //       already processing one on this thread.  Just
                    //       return success.
                    //
                    code = ReturnCode.Ok;
                }
            }
            else
            {
                result = "invalid interpreter";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckNotifications(
            NotifyType type,         /* in */
            NotifyFlags flags,       /* in */
            object data,             /* in */
            Interpreter interpreter, /* in */
            IClientData clientData,  /* in */
            ArgumentList arguments,  /* in */
            Exception exception      /* in */
            )
        {
            Result result = null;

            return CheckNotifications(type, flags, data, interpreter, clientData,
                arguments, exception, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckNotifications(
            NotifyType type,         /* in */
            NotifyFlags flags,       /* in */
            object data,             /* in */
            Interpreter interpreter, /* in */
            IClientData clientData,  /* in */
            ArgumentList arguments,  /* in */
            Exception exception,     /* in */
            ref Result result        /* in, out */
            )
        {
            if (!IsDisposed(this) && !IsPendingDispose(this) &&
                !Engine.HasNoNotify(engineFlags) && CanFireNotifications())
            {
                if (CheckNotifyTypesAndFlags(type, flags))
                {
#if MONO_BUILD && (!DEBUG || !VERBOSE)
#pragma warning disable 219
#endif
                    ReturnCode eventCode; // NOTE: Flagged by the Mono C# compiler.
#if MONO_BUILD && (!DEBUG || !VERBOSE)
#pragma warning restore 219
#endif

                    Result eventResult = null;

                    try
                    {
                        ScriptException scriptException = null;

                        if (exception != null)
                        {
                            if (exception is ScriptException)
                                scriptException = (ScriptException)exception;
                            else
                                scriptException = new ScriptException(null, exception);
                        }

                        IScriptEventArgs eventArgs = RuntimeOps.GetEventArgs(
                            type, flags, interpreter, new ClientData(data) /* WRAP */,
                            arguments, result, scriptException, InterruptType.None);

                        IClientData eventClientData = clientData; /* REF */

                        ArgumentList eventArguments = (arguments != null) ?
                            new ArgumentList(arguments) : null; /* COPY */

                        eventResult = Result.Copy(result, true); /* COPY */

                        eventCode = FireNotification(
                            eventArgs, eventClientData, eventArguments, ref eventResult);
                    }
                    catch (Exception e)
                    {
                        eventResult = String.Format(
                            "caught exception while firing notifications: {0}",
                            e);

                        eventCode = ReturnCode.Error;
                    }

#if DEBUG && VERBOSE
                    if (eventCode != ReturnCode.Ok)
                        DebugOps.Complain(interpreter, eventCode, eventResult);
#endif
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY_GLOBAL
        private static ReturnCode CheckNotifications(
            string pattern,          /* in */
            bool noCase,             /* in */
            NotifyType type,         /* in */
            NotifyFlags flags,       /* in */
            object data,             /* in */
            Interpreter interpreter, /* in */
            IClientData clientData,  /* in */
            ArgumentList arguments,  /* in */
            Exception exception      /* in */
            )
        {
            Result result = null;

            return CheckNotifications(
                pattern, noCase, type, flags, data, interpreter,
                clientData, arguments, exception, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode CheckNotifications(
            string pattern,          /* in */
            bool noCase,             /* in */
            NotifyType type,         /* in */
            NotifyFlags flags,       /* in */
            object data,             /* in */
            Interpreter interpreter, /* in */
            IClientData clientData,  /* in */
            ArgumentList arguments,  /* in */
            Exception exception,     /* in */
            ref Result result        /* in, out */
            )
        {
            InterpreterDictionary interpreters = GlobalState.GetInterpreters();

            if (interpreters != null)
            {
                bool broadcast = FlagOps.HasFlags(flags, NotifyFlags.Broadcast, true);
                bool safe = FlagOps.HasFlags(flags, NotifyFlags.Safe, true);

                ReturnCode code = ReturnCode.Ok;

                foreach (KeyValuePair<string, Interpreter> pair in interpreters)
                {
                    //
                    // NOTE: Do the pattern matching first to avoid attempting to
                    //       acquire interpreter locks without a valid reason.
                    //
                    if ((pattern == null) || StringOps.Match(
                            null, StringOps.DefaultMatchMode, pair.Key,
                            pattern, noCase))
                    {
                        Interpreter otherInterpreter = pair.Value;

                        if (otherInterpreter == null)
                            continue;

                        bool locked = false;
                        object syncRoot = otherInterpreter.InternalSyncRoot;

                        if (syncRoot == null)
                            continue;

                        try
                        {
                            locked = Monitor.TryEnter(syncRoot);

                            if (!locked)
                                continue;

                            //
                            // BUGFIX: Always skip the interpreter if it has
                            //         been disposed.
                            //
                            if (otherInterpreter.Disposed)
                                continue;

                            //
                            // BUGFIX: By default, skip this interpreter if it
                            //         belongs to another thread because we do
                            //         not want to create [thread] contexts on
                            //         this thread for it that we have no easy
                            //         way to know when to cleanup.  This limit
                            //         does not apply to broadcast notifications.
                            //
                            if (!broadcast && !otherInterpreter.IsPrimaryThread())
                                continue;

                            //
                            // BUGFIX: Do not send any "global" notifications
                            //         to safe interpreters.  Also, do not
                            //         notify an interpreter if we cannot
                            //         obtain the lock for the interpreter OR
                            //         the "global" notification flag is
                            //         disabled for it.  This limit does not
                            //         apply to "safe" notifications.
                            //
                            if (!safe && otherInterpreter.IsSafe())
                                continue;

                            code = otherInterpreter.CheckNotifications(
                                type, flags, data, interpreter, clientData,
                                arguments, exception, ref result);

                            if (code != ReturnCode.Ok)
                                break;
                        }
                        finally
                        {
                            if (locked)
                                Monitor.Exit(syncRoot);
                        }
                    }
                }

                return code;
            }
            else
            {
                result = "no interpreters available";
            }

            return ReturnCode.Error;
        }
#endif
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        #region Random Number Generation
        internal Random Random
        {
            get { return random; }
            set { random = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal RandomNumberGenerator RandomNumberGenerator
        {
            get { return randomNumberGenerator; }
        }
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region INotifyManager Members
#if NOTIFY || NOTIFY_OBJECT
        public NotifyType GlobalNotifyTypes
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return notifyTypes;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    notifyTypes = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public NotifyFlags GlobalNotifyFlags
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return notifyFlags;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    notifyFlags = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool GlobalNotify
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return notify;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    notify = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public NotifyType NotifyTypes
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
#if THREADING
                    IEngineContext context = (contextManager != null) ?
                        contextManager.GetEngineContext(true) : null;

                    if (context != null)
                        return notifyTypes | context.NotifyTypes;
                    else
                        return notifyTypes;
#else
                    return notifyTypes;
#endif
                }
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.NotifyTypes = value;
#else
                lock (syncRoot)
                {
                    notifyTypes = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public NotifyFlags NotifyFlags
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
#if THREADING
                    IEngineContext context = (contextManager != null) ?
                        contextManager.GetEngineContext(true) : null;

                    if (context != null)
                        return notifyFlags | context.NotifyFlags;
                    else
                        return notifyFlags;
#else
                    return notifyFlags;
#endif
                }
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.NotifyFlags = value;
#else
                lock (syncRoot)
                {
                    notifyFlags = value;
                }
#endif
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPackageManager Members
        public ReturnCode PresentPackage(
            string name,
            Version version,
            bool exact,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    IPackage package = null;

                    if ((GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok) &&
                        (package.Loaded != null) &&
                        PackageOps.VersionSatisfies(package.Loaded, version, exact))
                    {
                        result = package.Loaded;
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        result = String.Format(
                            "package \"{0}\" is not present",
                            FormatOps.PackageName(name, version));
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ProvidePackage(
            string name,
            Version version,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    IPackage package = null;

                    if (GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok)
                    {
                        if (version != null)
                        {
                            if (package.Loaded == null)
                            {
                                string provideFileName = null;

                                if (PkgSourceFileName(
                                        ref provideFileName, ref result) != ReturnCode.Ok)
                                {
                                    return ReturnCode.Error;
                                }

                                //
                                // NOTE: This version of the package is now "provided".
                                //
                                package.ProvideFileName = provideFileName;
                                package.Loaded = version;

                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                            else if (PackageOps.VersionCompare(package.Loaded, version) != 0)
                            {
                                //
                                // NOTE: This is an error, a different version of this
                                //       package has already been provided.
                                //
                                result = String.Format(
                                    "conflicting versions provided for package \"{0}\": " +
                                    "{1} then {2} ", name, package.Loaded, version);
                            }
                            else
                            {
                                //
                                // NOTE: Do nothing, the identical version has already
                                //       been provided.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Do nothing, just return the version of the
                            //       package that has been provided.
                            //
                            if (package.Loaded != null)
                                result = package.Loaded;
                            else
                                result = String.Empty;

                            return ReturnCode.Ok;
                        }
                    }
                    else if (version != null)
                    {
                        //
                        // NOTE: *WARNING* Empty package names are allowed, please
                        //       do not change this to "!String.IsNullOrEmpty".
                        //
                        if (name != null)
                        {
                            string provideFileName = null;

                            if (PkgSourceFileName(
                                    ref provideFileName, ref result) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }

                            //
                            // NOTE: We have never seen this package before.  Create
                            //       a new package and mark it as loaded.
                            //
                            if (AddPackage(PackageOps.NewCore(
                                    name, null, null, ClientData.Empty, provideFileName,
                                    provideFileName, PackageFlags.None, version, null),
                                    ClientData.Empty, ref result) == ReturnCode.Ok)
                            {
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                        else
                        {
                            result = "invalid package name";
                        }
                    }
                    else
                    {
                        result = "invalid package version";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RequirePackage(
            string name,
            Version version,
            bool exact,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    IPackage package = null;

                    if (GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok)
                    {
                        ReturnCode code;

                        if (package.Loaded != null)
                        {
                            //
                            // NOTE: Skip trying to load the package, it is already
                            //       loaded.
                            //
                            code = ReturnCode.Ok;
                        }
                        else
                        {
                            //
                            // NOTE: Attempt to load the package using the provided
                            //       script.
                            //
                            Version best = null;

                            try
                            {
                                code = package.Select(
                                    PackagePreference.Default, ref best, ref result);

                                if (code == ReturnCode.Ok)
                                    code = package.Load(this, best, ref result);
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "caught exception while loading package: {0}",
                                    e);

                                code = ReturnCode.Error;
                            }
                        }

                        //
                        // NOTE: Make sure the package did not fail to load.
                        //
                        if (code == ReturnCode.Ok)
                        {
                            if (package.Loaded != null)
                            {
                                if ((version == null) ||
                                    PackageOps.VersionSatisfies(package.Loaded, version, exact))
                                {
                                    result = package.Loaded;
                                }
                                else
                                {
                                    result = String.Format(
                                        "attempt to provide package \"{0}\" failed: " +
                                        "package \"{1}\" provided instead",
                                        FormatOps.PackageName(name, version),
                                        FormatOps.PackageName(name, package.Loaded));

                                    code = ReturnCode.Error;
                                }
                            }
                            else
                            {
                                result = String.Format(
                                    "attempt to provide package \"{0}\" failed: " +
                                    "no version of package \"{1}\" provided",
                                    FormatOps.PackageName(name, version), name);

                                code = ReturnCode.Error;
                            }
                        }

                        return code;
                    }
                    else
                    {
                        result = String.Format(
                            "can't find package \"{0}\"",
                            FormatOps.PackageName(name, version));
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode WithdrawPackage(
            string name,
            Version version,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    IPackage package = null;

                    if (GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok)
                    {
                        if (version != null)
                        {
                            if (package.Loaded != null)
                            {
                                if (PackageOps.VersionCompare(package.Loaded, version) == 0)
                                {
                                    //
                                    // NOTE: This version of the package is now "withdrawn".
                                    //
                                    package.Loaded = null;

                                    result = String.Empty;
                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    //
                                    // NOTE: This is an error, a different version of this
                                    //       package has been provided.
                                    //
                                    result = String.Format(
                                        "conflicting versions withdrawn for package \"{0}\": " +
                                        "{1} then {2} ", FormatOps.DisplayName(name),
                                        package.Loaded, version);
                                }
                            }
                            else
                            {
                                //
                                // NOTE: Do nothing, the package has already been
                                //       unprovided.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Do nothing, just return the version of the
                            //       package that has been provided.
                            //
                            if (package.Loaded != null)
                                result = package.Loaded;
                            else
                                result = String.Empty;

                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        result = String.Format(
                            "can't find package \"{0}\"",
                            FormatOps.PackageName(name, version));
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool HasNoPackageIndexes()
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.NoPackageIndexes, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void SetNoPackageIndexes(
            bool noPackageIndexes
            )
        {
            if (noPackageIndexes)
                interpreterFlags |= InterpreterFlags.NoPackageIndexes;
            else
                interpreterFlags &= ~InterpreterFlags.NoPackageIndexes;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal PackageIndexDictionary CopyPackageIndexes()
        {
            lock (syncRoot)
            {
                if (packageIndexes != null)
                    return new PackageIndexDictionary(packageIndexes);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For AutoPathTraceCallback / [package] use only.
        //
        internal PackageIndexDictionary PackageIndexes
        {
            set { lock (syncRoot) { packageIndexes = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ResetPkgIndexes(
            ref Result error /* NOT USED */
            )
        {
            lock (syncRoot)
            {
                if (packageIndexes != null)
                    packageIndexes.Clear();
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PkgSourceFileName(
            ref string fileName,
            ref Result error
            )
        {
            return ScriptOps.GetLocation(
                this, true, false, ref fileName, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgIndexes(
            string pattern,
            bool noCase,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackageIndexes(ref result))
                {
                    result = packageIndexes.ToString(pattern, noCase);
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgLoaded(
            string pattern,
            bool noCase,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    //
                    // NOTE: Return a list of all loaded packages.
                    //
                    StringList list = new StringList();

                    foreach (KeyValuePair<string, _Wrappers.Package> pair in packages)
                        if ((pair.Value != null) && (pair.Value.Loaded != null))
                            list.Add(pair.Key);

                    result = list.ToString(pattern, noCase);
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgNames(
            string pattern,
            bool noCase,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    //
                    // NOTE: Return a list of all registered packages.
                    //
                    result = packages.ToString(pattern, noCase);
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PkgForget(
            string name
            )
        {
            Result result = null;

            return PkgForget(name, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgForget(
            string name,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    if (DoesPackageExist(name) == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Remove the package.
                        //
                        if (RemovePackage(name, null, ref result) == ReturnCode.Ok)
                            return ReturnCode.Ok;
                    }
                    else
                    {
                        result = String.Format(
                            "can't find package \"{0}\"",
                            FormatOps.PackageName(name, null));
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgForget(
            StringList names,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    if (names != null)
                    {
                        foreach (string name in names)
                            /* IGNORED */
                            PkgForget(name);

                        result = String.Empty;
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        result = "invalid package list";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgIfNeeded(
            string name,
            Version version,
            string text,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    if (version != null)
                    {
                        if (text != null)
                        {
                            ReturnCode code;
                            IPackage package = null;

                            if (GetPackage(name, LookupFlags.NoVerbose, ref package) != ReturnCode.Ok)
                            {
                                //
                                // NOTE: *WARNING* Empty package names are allowed, please
                                //       do not change this to "!String.IsNullOrEmpty".
                                //
                                if (name != null)
                                {
                                    string indexFileName = null;

                                    code = PkgSourceFileName(ref indexFileName, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        package = PackageOps.NewCore(
                                            name, null, null, ClientData.Empty, indexFileName,
                                            null, PackageFlags.None, null, null);

                                        code = AddPackage(package, ClientData.Empty, ref result);
                                    }
                                }
                                else
                                {
                                    result = "invalid package name";
                                    code = ReturnCode.Error;
                                }
                            }
                            else
                            {
                                //
                                // NOTE: Package is already present in the collection.
                                //       Update the package index file name to reflect
                                //       the current file being evaluated.
                                //
                                string indexFileName = null;

                                code = PkgSourceFileName(ref indexFileName, ref result);

                                if (code == ReturnCode.Ok)
                                    package.IndexFileName = indexFileName;
                            }

                            //
                            // NOTE: Make sure we added the package OK (or that we did not need to).
                            //
                            if (code == ReturnCode.Ok)
                            {
                                VersionStringDictionary ifNeeded = package.IfNeeded;

                                if (ifNeeded != null)
                                {
                                    ifNeeded[version] = text;
                                    result = String.Empty;
                                }
                                else
                                {
                                    result = String.Format(
                                        "package \"{0}\" ifneeded scripts not available",
                                        name);

                                    code = ReturnCode.Error;
                                }
                            }

                            return code;
                        }
                        else
                        {
                            IPackage package = null;

                            if (GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok)
                            {
                                VersionStringDictionary ifNeeded = package.IfNeeded;

                                if (ifNeeded != null)
                                {
                                    string localText;

                                    if (ifNeeded.TryGetValue(version, out localText))
                                        result = localText;
                                    else
                                        result = String.Empty;

                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    result = String.Format(
                                        "package \"{0}\" ifneeded scripts not available",
                                        name);
                                }
                            }
                            else
                            {
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                    }
                    else
                    {
                        result = "invalid package version";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode PkgVersions(
            string name,
            ref Result result
            )
        {
            lock (syncRoot)
            {
                if (HasPackages(ref result))
                {
                    IPackage package = null;

                    if (GetPackage(name, LookupFlags.NoVerbose, ref package) == ReturnCode.Ok)
                    {
                        VersionStringDictionary ifNeeded = package.IfNeeded;

                        if (ifNeeded != null)
                            result = ifNeeded.ToString();
                        else
                            result = String.Empty;
                    }
                    else
                    {
                        result = String.Empty;
                    }

                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPluginManager Members
        public IPlugin FindPlugin(
            AppDomain appDomain,
            string name,
            Version version,
            byte[] publicKeyToken,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!HasPlugins(ref error))
                    return null;

                foreach (KeyValuePair<string, _Wrappers.Plugin> pair in plugins)
                {
                    IPlugin plugin = pair.Value;

                    if (plugin == null)
                        continue;

                    if (appDomain != null)
                    {
                        AppDomain pluginAppDomain = plugin.AppDomain;

                        if ((pluginAppDomain != null) &&
                            (pluginAppDomain.Id != appDomain.Id))
                        {
                            continue;
                        }
                    }

                    AssemblyName assemblyName;

#if ISOLATED_PLUGINS
                    if (AppDomainOps.IsIsolated(plugin))
                    {
                        assemblyName = plugin.AssemblyName;
                    }
                    else
#endif
                    {
                        Assembly assembly = plugin.Assembly;

                        if (assembly == null)
                            continue;

                        assemblyName = assembly.GetName();
                    }

                    if (assemblyName == null)
                        continue;

                    if ((name != null) &&
                        !String.Equals(assemblyName.Name, name,
                            StringOps.SystemStringComparisonType))
                    {
                        continue;
                    }

                    if ((version != null) &&
                        (PackageOps.VersionCompare(assemblyName.Version,
                            version) != 0))
                    {
                        continue;
                    }

                    if ((publicKeyToken != null) &&
                        !ArrayOps.Equals(
                            assemblyName.GetPublicKeyToken(), publicKeyToken))
                    {
                        continue;
                    }

                    return plugin;
                }
            }

            error = String.Format(
                "cannot find plugin {0} version {1} with public key token " +
                "{2} in application domain {3}", FormatOps.DisplayName(name),
                FormatOps.WrapOrNull(version), ArrayOps.ToHexadecimalString(
                publicKeyToken), FormatOps.WrapOrNull(appDomain));

            return null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode LoadPlugin(
            byte[] assemblyBytes,
            byte[] symbolBytes,
#if CAS_POLICY
            Evidence evidence,
#endif
            string typeName,
            IClientData clientData,
            PluginFlags flags,
            ref IPlugin plugin,
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Ok;

            if (assemblyBytes != null)
            {
                if (FlagOps.HasFlags(flags, PluginFlags.VerifiedOnly, true) &&
                    (FlagOps.HasFlags(flags, PluginFlags.SkipVerified, true) ||
                    !RuntimeOps.IsStrongNameVerified(assemblyBytes, true)))
                {
                    result = "plugin bytes are not strong name signed or cannot be verified";
                    return ReturnCode.Error;
                }

                if (FlagOps.HasFlags(flags, PluginFlags.TrustedOnly, true) &&
                    (FlagOps.HasFlags(flags, PluginFlags.SkipTrusted, true) ||
                    !RuntimeOps.IsFileTrusted(assemblyBytes)))
                {
                    result = "plugin bytes are not Authenticode signed or cannot be trusted";
                    return ReturnCode.Error;
                }

#if ISOLATED_PLUGINS
                bool isolated = FlagOps.HasFlags(flags, PluginFlags.Isolated, true);
#endif
                AppDomain appDomain = null;

#if ISOLATED_PLUGINS
                try
#endif
                {
                    code = AppDomainOps.GetOrCreate(
                        this,
                        FormatOps.AppDomainFriendlyName((string)null, typeName),
                        null,
#if CAS_POLICY
                        evidence,
#endif
                        clientData,
#if ISOLATED_PLUGINS
                        isolated,
#else
                        false,
#endif
                        true, ref appDomain, ref result);

                    if (code == ReturnCode.Ok)
                    {
#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Plugin, NotifyFlags.PreLoad,
                            new ObjectList(appDomain, assemblyBytes, symbolBytes,
                                typeName, flags, plugin), this,
                            clientData, null, null, ref result);
#endif

#if ISOLATED_PLUGINS
                        AssemblyName assemblyName = null;
                        Uri uri = null;
#endif
                        Assembly assembly = null;

                        try
                        {
                            PluginLoadHelper loadHelper = new PluginLoadHelper(
                                assemblyBytes, symbolBytes, null, typeName,
#if CAS_POLICY
                                isolated ? null : evidence,
#if !MONO && !MONO_HACKS
                                null, AssemblyHashAlgorithm.None,
#endif
#endif
                                new PluginPropertyHelper(), true,
                                FlagOps.HasFlags(flags, PluginFlags.Verbose, true));

#if CAS_POLICY
                            appDomain.DoCallBack(loadHelper.CasLoad3);
#else
                            appDomain.DoCallBack(loadHelper.NoCasLoad2);
#endif

#if ISOLATED_PLUGINS
                            if (isolated)
                            {
                                //
                                // NOTE: Get the plugin property helper for the plugin being
                                //       loaded from the plugin load helper.
                                //
                                PluginPropertyHelper propertyHelper = loadHelper.PropertyHelper;

                                if (propertyHelper != null)
                                {
                                    //
                                    // NOTE: Grab the name of the resolved and loaded assembly
                                    //       for the plugin being loaded from the plugin property
                                    //       helper.
                                    //
                                    assemblyName = propertyHelper.AssemblyName;

                                    //
                                    // NOTE: Grab the full name of the type for this plugin from
                                    //       the plugin property helper.  This is needed to
                                    //       determine exactly which class we need to create for
                                    //       the plugin being loaded in case a plugin assembly
                                    //       contains multiple plugins.
                                    //
                                    typeName = propertyHelper.TypeName;

                                    //
                                    // NOTE: Grab the URI for the plugin being loaded from the
                                    //       plugin property helper.  This is needed to pass to
                                    //       the constructor of the plugin type.
                                    //
                                    uri = propertyHelper.Uri;

                                    //
                                    // NOTE: Grab the extra plugin flags from the plugin property
                                    //       helper and combine them with the ones specified by
                                    //       the caller.
                                    //
                                    flags |= propertyHelper.PluginFlags;
                                }
                                else
                                {
                                    //
                                    // NOTE: We require the plugin property helper to be available
                                    //       and cannot continue to load the plugin without it.
                                    //
                                    result = "invalid plugin property helper";
                                    code = ReturnCode.Error;
                                }
                            }
                            else
#endif
                            {
                                //
                                // NOTE: Grab the loaded assembly directly from the plugin load
                                //       helper.  This is only legal (i.e. it will only work) when
                                //       we load the plugin assembly into the current application
                                //       domain.
                                //
                                assembly = loadHelper.Assembly;
                            }
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while loading plugin: {0}",
                                e);

                            code = ReturnCode.Error;
                        }

                        if ((code == ReturnCode.Ok) &&
#if ISOLATED_PLUGINS
                            !isolated &&
#endif
                            String.IsNullOrEmpty(typeName))
                        {
                            //
                            // NOTE: Introspect the assembly for types that implement the IPlugin
                            //       interface and simply default to loading the first one marked
                            //       as 'Primary' that we find.
                            //
                            code = RuntimeOps.FindPrimaryPlugin(assembly, ref typeName, ref result);
                        }

                        if (code == ReturnCode.Ok)
                        {
#if ISOLATED_PLUGINS
                            if (isolated)
                                code = CreatePlugin(
                                    appDomain, assemblyName, null, typeName,
                                    uri, clientData, flags, false, ref plugin, ref result);
                            else
#endif
                                code = CreatePlugin(
                                    appDomain, assembly, null, typeName, clientData,
                                    flags, ref plugin, ref result);

#if NOTIFY
                            if (code == ReturnCode.Ok)
                            {
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Plugin, NotifyFlags.Load,
                                    new ObjectList(appDomain, assemblyBytes, symbolBytes,
                                        typeName, flags, plugin), this,
                                    clientData, null, null, ref result);
                            }
#endif
                        }
                    }
                }
#if ISOLATED_PLUGINS
                finally
                {
                    if ((code != ReturnCode.Ok) && isolated && (appDomain != null))
                    {
                        ReturnCode unloadCode;
                        Result unloadError = null;

                        unloadCode = AppDomainOps.Unload(
                            appDomain, clientData, ref unloadError);

                        if (unloadCode != ReturnCode.Ok)
                            DebugOps.Complain(this, unloadCode, unloadError);
                    }
                }
#endif
            }
            else
            {
                result = "invalid assembly bytes";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [Obsolete()]
        public ReturnCode LoadPlugin( /* NOT USED */
            AssemblyName assemblyName,
#if CAS_POLICY
            Evidence evidence,
#endif
            string typeName,
            IClientData clientData,
            PluginFlags flags,
            ref IPlugin plugin,
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Ok;

            if (assemblyName != null)
            {
#if ISOLATED_PLUGINS
                bool isolated = FlagOps.HasFlags(flags, PluginFlags.Isolated, true);
#endif
                AppDomain appDomain = null;

#if ISOLATED_PLUGINS
                try
#endif
                {
                    code = AppDomainOps.GetOrCreate(
                        this,
                        FormatOps.AppDomainFriendlyName(assemblyName, typeName),
                        null,
#if CAS_POLICY
                        evidence,
#endif
                        clientData,
#if ISOLATED_PLUGINS
                        isolated,
#else
                        false,
#endif
                        true, ref appDomain, ref result);

                    if (code == ReturnCode.Ok)
                    {
#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Plugin, NotifyFlags.PreLoad,
                            new ObjectList(appDomain, assemblyName, typeName, flags, plugin), this,
                            clientData, null, null, ref result);
#endif

                        Assembly assembly = null;
                        string fileName = null;

                        try
                        {
                            //
                            // BUGBUG: This will not work when using isolated AppDomains
                            //         (which is mostly fine because we never load plugins
                            //         via this method overload anyhow).
                            //
                            assembly = appDomain.Load(
                                assemblyName
#if CAS_POLICY
                                , evidence
#endif
                            );

                            fileName = assembly.Location;
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while loading plugin: {0}",
                                e);

                            code = ReturnCode.Error;
                        }

                        if (code == ReturnCode.Ok)
                            code = CreatePlugin(
                                appDomain, assembly, fileName, typeName,
                                clientData, flags, ref plugin, ref result);

#if NOTIFY
                        if (code == ReturnCode.Ok)
                        {
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Plugin, NotifyFlags.Load,
                                new ObjectList(appDomain, fileName, typeName, flags, plugin), this,
                                clientData, null, null, ref result);
                        }
#endif
                    }
                }
#if ISOLATED_PLUGINS
                finally
                {
                    if ((code != ReturnCode.Ok) && isolated && (appDomain != null))
                    {
                        ReturnCode unloadCode;
                        Result unloadError = null;

                        unloadCode = AppDomainOps.Unload(
                            appDomain, clientData, ref unloadError);

                        if (unloadCode != ReturnCode.Ok)
                            DebugOps.Complain(this, unloadCode, unloadError);
                    }
                }
#endif
            }
            else
            {
                result = "invalid assembly name";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode LoadPlugin(
            string fileName,
#if CAS_POLICY
            Evidence evidence,
            byte[] hashValue,
            AssemblyHashAlgorithm hashAlgorithm,
#endif
            string typeName,
            IClientData clientData,
            PluginFlags flags,
            ref IPlugin plugin,
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code = ReturnCode.Ok;

            if (!String.IsNullOrEmpty(fileName) && File.Exists(fileName))
            {
                if (FlagOps.HasFlags(flags, PluginFlags.VerifiedOnly, true) &&
                    (FlagOps.HasFlags(flags, PluginFlags.SkipVerified, true) ||
                    !RuntimeOps.IsStrongNameVerified(fileName, true)))
                {
                    result = "plugin file is not strong name signed or cannot be verified";
                    return ReturnCode.Error;
                }

                if (FlagOps.HasFlags(flags, PluginFlags.TrustedOnly, true) &&
                    (FlagOps.HasFlags(flags, PluginFlags.SkipTrusted, true) ||
                    !RuntimeOps.IsFileTrusted(fileName, IntPtr.Zero)))
                {
                    result = "plugin file is not Authenticode signed or cannot be trusted";
                    return ReturnCode.Error;
                }

#if ISOLATED_PLUGINS
                bool isolated = FlagOps.HasFlags(flags, PluginFlags.Isolated, true);
#endif
                AppDomain appDomain = null;

#if ISOLATED_PLUGINS
                try
#endif
                {
                    code = AppDomainOps.GetOrCreate(
                        this,
                        FormatOps.AppDomainFriendlyName(fileName, typeName),
                        Path.GetDirectoryName(fileName),
#if CAS_POLICY
                        evidence,
#endif
                        clientData,
#if ISOLATED_PLUGINS
                        isolated,
#else
                        false,
#endif
                        true, ref appDomain, ref result);

                    if (code == ReturnCode.Ok)
                    {
#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Plugin, NotifyFlags.PreLoad,
                            new ObjectList(appDomain, fileName, typeName, flags, plugin), this,
                            clientData, null, null, ref result);
#endif

#if ISOLATED_PLUGINS
                        AssemblyName assemblyName = null;
                        Uri uri = null;
#endif
                        Assembly assembly = null;

                        try
                        {
                            PluginLoadHelper loadHelper = new PluginLoadHelper(
                                null, null, fileName, typeName,
#if CAS_POLICY
                                isolated ? null : evidence,
#if !MONO && !MONO_HACKS
                                hashValue, hashAlgorithm,
#endif
#endif
                                new PluginPropertyHelper(), true,
                                FlagOps.HasFlags(flags, PluginFlags.Verbose, true));

#if CAS_POLICY
#if !MONO && !MONO_HACKS
                            if (!CommonOps.Runtime.IsMono())
                                appDomain.DoCallBack(loadHelper.CasLoad4);
                            else
#endif
                                appDomain.DoCallBack(loadHelper.CasLoad2);
#else
                            appDomain.DoCallBack(loadHelper.NoCasLoad1);
#endif

#if ISOLATED_PLUGINS
                            if (isolated)
                            {
                                //
                                // NOTE: Get the plugin property helper for the plugin being
                                //       loaded from the plugin load helper.
                                //
                                PluginPropertyHelper propertyHelper = loadHelper.PropertyHelper;

                                if (propertyHelper != null)
                                {
                                    //
                                    // NOTE: Grab the name of the resolved and loaded assembly
                                    //       for the plugin being loaded from the plugin property
                                    //       helper.
                                    //
                                    assemblyName = propertyHelper.AssemblyName;

                                    //
                                    // NOTE: Grab the full name of the type for this plugin from
                                    //       the plugin property helper.  This is needed to
                                    //       determine exactly which class we need to create for
                                    //       the plugin being loaded in case a plugin assembly
                                    //       contains multiple plugins.
                                    //
                                    typeName = propertyHelper.TypeName;

                                    //
                                    // NOTE: Grab the URI for the plugin being loaded from the
                                    //       plugin property helper.  This is needed to pass to
                                    //       the constructor of the plugin type.
                                    //
                                    uri = propertyHelper.Uri;

                                    //
                                    // NOTE: Grab the extra plugin flags from the plugin property
                                    //       helper and combine them with the ones specified by
                                    //       the caller.
                                    //
                                    flags |= propertyHelper.PluginFlags;
                                }
                                else
                                {
                                    //
                                    // NOTE: We require the plugin property helper to be available
                                    //       and cannot continue to load the plugin without it.
                                    //
                                    result = "invalid plugin property helper";
                                    code = ReturnCode.Error;
                                }
                            }
                            else
#endif
                            {
                                //
                                // NOTE: Grab the loaded assembly directly from the plugin load
                                //       helper.  This is only legal (i.e. it will only work) when
                                //       we load the plugin assembly into the current application
                                //       domain.
                                //
                                assembly = loadHelper.Assembly;
                            }
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while loading plugin: {0}",
                                e);

                            code = ReturnCode.Error;
                        }

                        if ((code == ReturnCode.Ok) &&
#if ISOLATED_PLUGINS
                            !isolated &&
#endif
                            String.IsNullOrEmpty(typeName))
                        {
                            //
                            // NOTE: Introspect the assembly for types that implement the IPlugin
                            //       interface and simply default to loading the first one marked
                            //       as 'Primary' that we find.
                            //
                            code = RuntimeOps.FindPrimaryPlugin(assembly, ref typeName, ref result);
                        }

                        if (code == ReturnCode.Ok)
                        {
#if ISOLATED_PLUGINS
                            if (isolated)
                                code = CreatePlugin(
                                    appDomain, assemblyName, fileName, typeName,
                                    uri, clientData, flags, false, ref plugin, ref result);
                            else
#endif
                                code = CreatePlugin(
                                    appDomain, assembly, fileName, typeName, clientData,
                                    flags, ref plugin, ref result);

#if NOTIFY
                            if (code == ReturnCode.Ok)
                            {
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Plugin, NotifyFlags.Load,
                                    new ObjectList(appDomain, fileName, typeName, flags, plugin), this,
                                    clientData, null, null, ref result);
                            }
#endif
                        }
                    }
                }
#if ISOLATED_PLUGINS
                finally
                {
                    if ((code != ReturnCode.Ok) && isolated && (appDomain != null))
                    {
                        ReturnCode unloadCode;
                        Result unloadError = null;

                        unloadCode = AppDomainOps.Unload(
                            appDomain, clientData, ref unloadError);

                        if (unloadCode != ReturnCode.Ok)
                            DebugOps.Complain(this, unloadCode, unloadError);
                    }
                }
#endif
            }
            else
            {
                result = "invalid assembly file name";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnloadPlugin(
            IPlugin plugin,
            IClientData clientData,
            PluginFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin == null)
            {
                result = "invalid plugin";
                return ReturnCode.Error;
            }

            ReturnCode code;

#if ISOLATED_PLUGINS
            bool isolated = AppDomainOps.IsIsolated(plugin);
            AppDomain appDomain = isolated ? plugin.AppDomain : null;
#endif

            GlobalState.PushActiveInterpreter(this);

            try
            {
#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Plugin, NotifyFlags.PreUnload,
                    new ObjectPair(plugin, flags), this,
                    clientData, null, null, ref result);
#endif

                code = plugin.Terminate(this, (clientData != null) ?
                    clientData : plugin.ClientData, ref result);

                if (code == ReturnCode.Ok)
                {
#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Plugin, NotifyFlags.Unload,
                        new ObjectPair(plugin, flags), this,
                        clientData, null, null, ref result);
#endif
                }
            }
            catch (Exception e)
            {
                result = String.Format(
                    "caught exception while terminating plugin: {0}",
                    e);

                code = ReturnCode.Error;
            }
            finally
            {
                /* IGNORED */
                GlobalState.PopActiveInterpreter();
            }

#if ISOLATED_PLUGINS
            //
            // NOTE: This cannot be done completely without full AppDomain
            //       isolation of loaded plugin Assemblies.  At that point,
            //       we can simply call AppDomain.Unload to unload the plugin.
            //
            if ((code == ReturnCode.Ok) && isolated)
                code = AppDomainOps.Unload(
                    appDomain, clientData, ref result);
#endif

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnloadPlugin(
            long token,
            IClientData clientData,
            PluginFlags flags, /* NOT USED */
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code;
#if ISOLATED_PLUGINS
            IPlugin plugin = null;

            code = GetPlugin(token, LookupFlags.Unload, ref plugin, ref result);

            if (code == ReturnCode.Ok)
#endif
            {
#if ISOLATED_PLUGINS
                bool isolated = AppDomainOps.IsIsolated(plugin);
                AppDomain appDomain = isolated ? plugin.AppDomain : null;
#endif

                code = RemovePlugin(token, clientData, ref result);

#if ISOLATED_PLUGINS
                //
                // NOTE: This cannot be done completely without full AppDomain
                //       isolation of loaded plugin Assemblies.  At that point,
                //       we can simply call AppDomain.Unload to unload the plugin.
                //
                if ((code == ReturnCode.Ok) && isolated)
                    code = AppDomainOps.Unload(
                        appDomain, clientData, ref result);
#endif
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnloadPlugin(
            string name,
            IClientData clientData,
            PluginFlags flags, /* NOT USED */
            ref Result result
            )
        {
            CheckDisposed();

            ReturnCode code;
#if ISOLATED_PLUGINS
            IPlugin plugin = null;

            code = GetPlugin(name, LookupFlags.Unload, ref plugin, ref result);

            if (code == ReturnCode.Ok)
#endif
            {
#if ISOLATED_PLUGINS
                bool isolated = AppDomainOps.IsIsolated(plugin);
                AppDomain appDomain = isolated ? plugin.AppDomain : null;
#endif

                code = RemovePlugin(name, clientData, ref result);

#if ISOLATED_PLUGINS
                //
                // NOTE: This cannot be done completely without full AppDomain
                //       isolation of loaded plugin Assemblies.  At that point,
                //       we can simply call AppDomain.Unload to unload the plugin.
                //
                if ((code == ReturnCode.Ok) && isolated)
                    code = AppDomainOps.Unload(
                        appDomain, clientData, ref result);
#endif
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddCommands(
            IPlugin plugin,
            IClientData clientData,
            CommandFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                AppDomain appDomain = plugin.AppDomain;

                if (appDomain != null)
                {
                    CommandDataList commands = plugin.Commands;

                    if (commands != null)
                    {
                        //
                        // NOTE: Are we adding commands in command
                        //       restoration mode?
                        //
                        bool restore = FlagOps.HasFlags(
                            flags, CommandFlags.Restore, true);

#if ISOLATED_PLUGINS
                        //
                        // NOTE: Is this plugin supposed to be loaded
                        //       into an isolated application domain?
                        //
                        bool isolated = AppDomainOps.IsIsolated(plugin);
#endif

                        //
                        // NOTE: Is this interpreter marked as "safe"?
                        //
                        bool createSafe = FlagOps.HasFlags(
                            createFlags, CreateFlags.Safe, true);

                        //
                        // NOTE: Are we supposed to hide unsafe commands?
                        //
                        bool hideUnsafe = FlagOps.HasFlags(
                            createFlags, CreateFlags.HideUnsafe, true);

                        //
                        // NOTE: Is this interpreter marked as "standard"?
                        //
                        bool createStandard = FlagOps.HasFlags(
                            createFlags, CreateFlags.Standard, true);

                        //
                        // NOTE: Are we supposed to hide non-standard
                        //       commands?
                        //
                        bool hideNonStandard = FlagOps.HasFlags(
                            createFlags, CreateFlags.HideNonStandard, true);

                        //
                        // NOTE: Process each command in no particular order
                        //       (actually, the type of the command, which
                        //       currently equates to the same thing).
                        //
                        foreach (ICommandData commandData in commands)
                        {
                            //
                            // NOTE: Query the command flags associated with
                            //       this type.
                            //
                            CommandFlags commandFlags = commandData.Flags;

                            //
                            // NOTE: Check if this command is supposed to be
                            //       added to the interpreter.
                            //
                            bool noAdd = FlagOps.HasFlags(
                                commandFlags, CommandFlags.NoAdd, true);

                            //
                            // NOTE: If we are supposed to skip adding this
                            //       command altogether, then proceed no
                            //       further.
                            //
                            if (!noAdd)
                            {
                                string typeName = commandData.TypeName;

                                //
                                // NOTE: Check if this command has been marked as "safe" or
                                //       "unsafe" by its author.
                                //
                                bool safe = FlagOps.HasFlags(commandFlags, CommandFlags.Safe, true) &&
                                    !FlagOps.HasFlags(commandFlags, CommandFlags.Unsafe, true);

                                //
                                // NOTE: If the interpreter is "safe", make sure we only add
                                //       commands that are marked as "safe" and NOT marked as
                                //       "unsafe" unless we are merely hiding commands not
                                //       considered to be "safe".  In that case, we add all
                                //       commands, hidden them as necessary.
                                //
                                if (safe || !createSafe || hideUnsafe)
                                {
                                    //
                                    // NOTE: Check if this command is part of the "Tcl Standard"
                                    //       (i.e. it is largely (or completely) compatible with
                                    //       an identically named command from Tcl/Tk 8.4, 8.5,
                                    //       and/or 8.6).
                                    //
                                    bool standard = FlagOps.HasFlags(
                                        commandFlags, CommandFlags.Standard, true);

                                    //
                                    // NOTE: If the interpreter is "standard", make sure we only
                                    //       add commands that are marked as "standard" and NOT
                                    //       marked as "non-standard" unless we are merely hiding
                                    //       commands not considered to be "standard".  In that
                                    //       case, we add all commands, hidden them as necessary.
                                    //
                                    if (standard || !createStandard || hideNonStandard)
                                    {
                                        //
                                        // NOTE: Is the command named "Default" or "Core"?  If
                                        //       so, we need to skip over it because they are
                                        //       used as the base implementation for other
                                        //       commands.
                                        //
                                        if ((String.Compare(typeName, typeof(_Commands.Default).FullName,
                                                StringOps.SystemStringComparisonType) != 0) &&
                                            (String.Compare(typeName, typeof(_Commands._Delegate).FullName,
                                                StringOps.SystemStringComparisonType) != 0) &&
                                            (String.Compare(typeName, typeof(_Commands.Ensemble).FullName,
                                                StringOps.SystemStringComparisonType) != 0) &&
                                            (String.Compare(typeName, typeof(_Commands.Core).FullName,
                                                StringOps.SystemStringComparisonType) != 0) &&
                                            (String.Compare(typeName, typeof(_Commands.Alias).FullName,
                                                StringOps.SystemStringComparisonType) != 0))
                                        {
                                            //
                                            // NOTE: Grab the command name and make sure it is
                                            //       valid.  For now, we just ignore invalid
                                            //       command names (i.e. we skip adding the
                                            //       command).
                                            //
                                            string name = commandData.Name;

                                            if (name != null)
                                            {
                                                //
                                                // HACK: All core command names are lowercase;
                                                //       culture is invariant because these are
                                                //       "system" identifiers.
                                                //
                                                name = name.ToLowerInvariant();

                                                //
                                                // HACK: Remove leading underscore from core
                                                //       command names to accommodate the special
                                                //       circumstance where we were using a
                                                //       leading underscore to get around .NET
                                                //       Framework "reserved" type names (e.g.
                                                //       File, String, Object, etc).
                                                //
                                                if ((name.Length > 0) &&
                                                    (name[0] == Characters.Underscore))
                                                {
                                                    name = name.Substring(1);
                                                }

                                                //
                                                // NOTE: Always try to add the command unless we
                                                //       are in "restoration" mode, in that case
                                                //       only try to add the command if it does
                                                //       not already exist.
                                                //
                                                bool add = true;

                                                if (restore &&
                                                    (DoesCommandExist(name) == ReturnCode.Ok))
                                                {
                                                    add = false;
                                                }

                                                //
                                                // NOTE: Do we still want to add this command?
                                                //
                                                if (add)
                                                {
                                                    //
                                                    // NOTE: Start with the flags provided by the
                                                    //       caller and then mask off the command
                                                    //       restoration flag.
                                                    //
                                                    CommandFlags newFlags =
                                                        flags & ~CommandFlags.Restore;

                                                    //
                                                    // NOTE: If this command is not considered
                                                    //       "safe" and the caller instructed us
                                                    //       to hide such commands, do so now.
                                                    //
                                                    if (!safe && hideUnsafe)
                                                        newFlags |= CommandFlags.Hidden;
                                                    //
                                                    // NOTE: Otherwise, if this command is not
                                                    //       considered to be "standard" and the
                                                    //       caller instructed us to hide such
                                                    //       commands, do so now.
                                                    //
                                                    else if (!standard && hideNonStandard)
                                                        newFlags |= CommandFlags.Hidden;

#if ISOLATED_PLUGINS
                                                    //
                                                    // NOTE: If the plugin has been loaded into
                                                    //       an isolated AppDomain, the command
                                                    //       should be marked isolated as well.
                                                    //
                                                    if (isolated)
                                                        newFlags |= CommandFlags.Isolated;
#endif

                                                    //
                                                    // NOTE: Setup the argument array for the
                                                    //       command constructor.  The command
                                                    //       MUST expose a constructor that
                                                    //       accepts this argument type.  It
                                                    //       is also free to expose other
                                                    //       constructors; however, they will
                                                    //       not be used by the script engine.
                                                    //
                                                    object[] args = { new CommandData(name,
                                                        commandData.Group, commandData.Description,
                                                        commandData.ClientData, commandData.TypeName,
                                                        newFlags, commandData.Plugin,
                                                        EntityOps.GetToken(commandData))
                                                    };

                                                    //
                                                    // NOTE: Attempt to create an instance of
                                                    //       the command in the application
                                                    //       domain for the plugin.
                                                    //
                                                    ReturnCode code = ReturnCode.Ok;
                                                    ICommand command = null;

#if ISOLATED_PLUGINS
                                                    if (isolated)
                                                    {
                                                        AssemblyName assemblyName = plugin.AssemblyName;

                                                        if (assemblyName != null)
                                                        {
                                                            command = (ICommand)appDomain.CreateInstanceAndUnwrap(
                                                                assemblyName.ToString(), typeName, false,
                                                                RuntimeOps.CreateInstanceBindingFlags, null, args,
                                                                null, null, null);
                                                        }
                                                        else
                                                        {
                                                            result = "plugin has invalid assembly name";
                                                            code = ReturnCode.Error;
                                                        }
                                                    }
                                                    else
#endif
                                                    {
                                                        Assembly assembly = plugin.Assembly;

                                                        if (assembly != null)
                                                        {
                                                            command = (ICommand)assembly.CreateInstance(
                                                                typeName, false,
                                                                RuntimeOps.CreateInstanceBindingFlags,
                                                                null, args, null, null);
                                                        }
                                                        else
                                                        {
                                                            result = "plugin has invalid assembly";
                                                            code = ReturnCode.Error;
                                                        }
                                                    }

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        if (command != null)
                                                        {
                                                            //
                                                            // NOTE: Attempt to assign the the ObjectId
                                                            //       of the command to the Id property,
                                                            //       if necessary.
                                                            //
                                                            // FIXME: Maybe this should be moved into
                                                            //        AddCommand and similar functionality
                                                            //        added to AddFunction, etc?
                                                            //
                                                            if (command.Id.Equals(Guid.Empty))
                                                                command.Id = AttributeOps.GetObjectId(command);

                                                            //
                                                            // NOTE: Add the command to the interpreter.
                                                            //
                                                            long token = 0;

                                                            code = AddCommand(command, clientData, ref token, ref result);

                                                            if (code == ReturnCode.Ok)
                                                                EntityOps.SetToken(commandData, token);
                                                        }
                                                        else
                                                        {
                                                            result = String.Format(
                                                                "could not create command \"{0}\"",
                                                                typeName);

                                                            code = ReturnCode.Error;
                                                        }
                                                    }

                                                    if (code != ReturnCode.Ok)
                                                        return code;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }

#if ISOLATED_PLUGINS
                        //
                        // NOTE: Update the command data list for isolated plugins.
                        //
                        if (isolated)
                            plugin.Commands = commands;
#endif

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        result = "plugin has invalid command data list";
                    }
                }
                else
                {
                    result = "plugin has invalid application domain";
                }
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveCommands(
            IPlugin plugin,
            IClientData clientData,
            CommandFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                LongList localTokens = plugin.CommandTokens;

                if (localTokens != null)
                    localTokens = (LongList)localTokens.Clone();

                if (localTokens != null)
                {
                    foreach (long token in localTokens)
                    {
                        if (DoesCommandExist(token) == ReturnCode.Ok)
                        {
                            ReturnCode code = RemoveCommand(
                                token, clientData, ref result);

                            if (code != ReturnCode.Ok)
                                return code;
                        }
                        else
                        {
                            //
                            // NOTE: We must actually ignore "failures" here because,
                            //       in theory, the command could have been removed
                            //       using the [rename] script command or some other
                            //       mechanism.
                            //
                        }
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveFunctions(
            IPlugin plugin,
            IClientData clientData,
            FunctionFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                LongList localTokens = plugin.FunctionTokens;

                if (localTokens != null)
                    localTokens = (LongList)localTokens.Clone();

                if (localTokens != null)
                {
                    foreach (long token in localTokens)
                    {
                        if (DoesFunctionExist(token) == ReturnCode.Ok)
                        {
                            ReturnCode code = RemoveFunction(
                                token, clientData, ref result);

                            if (code != ReturnCode.Ok)
                                return code;
                        }
                        else
                        {
                            //
                            // NOTE: We must actually ignore "failures" here because,
                            //       in theory, the function could have been removed
                            //       using some other mechanism.
                            //
                        }
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddPolicies(
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                AppDomain appDomain = plugin.AppDomain;

                if (appDomain != null)
                {
                    PolicyDataList policies = plugin.Policies;

                    if (policies != null)
                    {
#if ISOLATED_PLUGINS
                        //
                        // NOTE: Is this plugin supposed to be loaded
                        //       into an isolated application domain?
                        //
                        bool isolated = AppDomainOps.IsIsolated(plugin);
#endif

                        //
                        // NOTE: Process each policy in no particular order
                        //       (actually, the type and method name of the
                        //       policy, which currently equates to the same
                        //       thing).
                        //
                        foreach (IPolicyData policyData in policies)
                        {
                            //
                            // NOTE: Query the flags associated with this
                            //       policy method.
                            //
                            MethodFlags methodFlags = policyData.MethodFlags;

                            //
                            // NOTE: Check if this policy is supposed to be
                            //       added to the interpreter.
                            //
                            bool noAdd = FlagOps.HasFlags(
                                methodFlags, MethodFlags.NoAdd, true);

                            //
                            // NOTE: If we are supposed to skip adding this
                            //       policy altogether, then proceed no
                            //       further.
                            //
                            if (!noAdd)
                            {
                                string typeName =
                                    typeof(Eagle._Policies.Core).FullName;

                                //
                                // NOTE: Setup the argument array for the
                                //       policy constructor.  The policy
                                //       MUST expose a constructor that
                                //       accepts this argument type.  It
                                //       is also free to expose other
                                //       constructors; however, they will
                                //       not be used by the script engine.
                                //
                                object[] args = { new PolicyData(
                                    policyData.Name, policyData.Group,
                                    policyData.Description, clientData,
                                    policyData.TypeName, policyData.MethodName,
                                    policyData.BindingFlags, policyData.MethodFlags,
                                    policyData.PolicyFlags, policyData.Plugin,
                                    EntityOps.GetToken(policyData))
                                };

                                //
                                // NOTE: Attempt to create an instance of
                                //       the policy in the application
                                //       domain for the plugin.
                                //
                                ReturnCode code = ReturnCode.Ok;
                                IPolicy policy = null;

#if ISOLATED_PLUGINS
                                if (isolated)
                                {
                                    AssemblyName assemblyName = GlobalState.GetAssemblyName();

                                    if (assemblyName != null)
                                    {
                                        policy = (IPolicy)appDomain.CreateInstanceAndUnwrap(
                                            assemblyName.ToString(), typeName, false,
                                            RuntimeOps.CreateInstanceBindingFlags, null, args,
                                            null, null, null);
                                    }
                                    else
                                    {
                                        //
                                        // HACK: This error message is not quite correct;
                                        //       however, it's close enough for now.
                                        //
                                        result = "plugin has invalid assembly name";
                                        code = ReturnCode.Error;
                                    }
                                }
                                else
#endif
                                {
                                    Assembly assembly = GlobalState.GetAssembly();

                                    if (assembly != null)
                                    {
                                        policy = (IPolicy)assembly.CreateInstance(
                                            typeName, false,
                                            RuntimeOps.CreateInstanceBindingFlags,
                                            null, args, null, null);
                                    }
                                    else
                                    {
                                        //
                                        // HACK: This error message is not quite correct;
                                        //       however, it's close enough for now.
                                        //
                                        result = "plugin has invalid assembly";
                                        code = ReturnCode.Error;
                                    }
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    if (policy != null)
                                    {
                                        //
                                        // NOTE: First, attempt to assign the the ObjectId
                                        //       of the policy to the Id property, if
                                        //       necessary.
                                        //
                                        // FIXME: Maybe this should be moved into AddPolicy
                                        //        and similar functionality added to
                                        //        AddFunction, etc?
                                        //
                                        if (policy.Id.Equals(Guid.Empty))
                                            policy.Id = AttributeOps.GetObjectId(policy);

                                        //
                                        // NOTE: Next, make sure the actual delegate is setup.
                                        //
                                        code = policy.Setup(ref result);

                                        //
                                        // NOTE: Finally, add the policy to the interpreter.
                                        //
                                        if (code == ReturnCode.Ok)
                                        {
                                            long token = 0;

                                            code = AddPolicy(policy, clientData, ref token, ref result);

                                            if (code == ReturnCode.Ok)
                                                EntityOps.SetToken(policyData, token);
                                        }
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "could not create policy \"{0}\"",
                                            typeName);

                                        code = ReturnCode.Error;
                                    }
                                }

                                if (code != ReturnCode.Ok)
                                    return code;
                            }
                        }

#if ISOLATED_PLUGINS
                        //
                        // NOTE: Update the policy data list for isolated plugins.
                        //
                        if (isolated)
                            plugin.Policies = policies;
#endif

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        result = "plugin has invalid policy data list";
                    }
                }
                else
                {
                    result = "plugin has invalid application domain";
                }
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemovePolicies(
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                LongList localTokens = (LongList)plugin.PolicyTokens;

                if (localTokens != null)
                    localTokens = (LongList)localTokens.Clone();

                if (localTokens != null)
                {
                    foreach (long token in localTokens)
                    {
                        if (DoesPolicyExist(token) == ReturnCode.Ok)
                        {
                            ReturnCode code = RemovePolicy(
                                token, clientData, ref result);

                            if (code != ReturnCode.Ok)
                                return code;
                        }
                        else
                        {
                            //
                            // NOTE: We should actually ignore "failures" here because,
                            //       in theory, the policy could have been removed using
                            //       some other mechanism.
                            //
                        }
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveTraces(
            IPlugin plugin,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            if (plugin != null)
            {
                LongList localTokens = (LongList)plugin.TraceTokens;

                if (localTokens != null)
                    localTokens = (LongList)localTokens.Clone();

                if (localTokens != null)
                {
                    foreach (long token in localTokens)
                    {
                        if (DoesTraceExist(token) == ReturnCode.Ok)
                        {
                            ReturnCode code = RemoveTrace(
                                token, clientData, ref result);

                            if (code != ReturnCode.Ok)
                                return code;
                        }
                        else
                        {
                            //
                            // NOTE: We should actually ignore "failures" here because,
                            //       in theory, the trace could have been removed using
                            //       some other mechanism.
                            //
                        }
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                result = "invalid plugin";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RestoreCorePlugin(
            bool strict,
            ref Result result
            )
        {
            CheckDisposed();

            IPlugin plugin = null;

            if (corePluginToken != 0)
            {
                if ((GetPlugin(corePluginToken, LookupFlags.Default, ref plugin, ref result) == ReturnCode.Ok) &&
                    (AddCommands(plugin, null, CommandFlags.Restore, ref result) == ReturnCode.Ok) &&
                    (MoveExposedAndHiddenCommands(ref result) == ReturnCode.Ok) &&
                    (!strict || (SetupFunctions(createFlags, ref result) == ReturnCode.Ok)))
                {
                    return ReturnCode.Ok;
                }
            }
            else
            {
                plugin = NewCorePlugin();

                if ((RuntimeOps.PrepareStaticPlugin(plugin, ref result) == ReturnCode.Ok) &&
                    (AddPlugin(plugin, null, ref corePluginToken, ref result) == ReturnCode.Ok) &&
                    (!strict || (SetupFunctions(createFlags, ref result) == ReturnCode.Ok)))
                {
                    return ReturnCode.Ok;
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal long InternalCorePluginToken
        {
            set { corePluginToken = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
        internal long InternalObjectPluginToken
        {
            set { objectPluginToken = value; }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUG
        internal long InternalTestPluginToken
        {
            set { testPluginToken = value; }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode CreatePlugin(
            AppDomain appDomain,
            AssemblyName assemblyName,
            string fileName,
            string typeName,
            Uri uri,
            IClientData clientData,
            PluginFlags flags,
            bool loadFrom,
            ref IPlugin plugin,
            ref Result error
            )
        {
            ReturnCode code;

            if (appDomain != null)
            {
                if (assemblyName != null)
                {
                    if (typeName != null)
                    {
                        if (uri != null)
                        {
                            try
                            {
                                //
                                // NOTE: Setup the arguments for the plugin constructor.
                                //       Unfortunately, constructors cannot be part of an interface;
                                //       however, we require all plugins to expose a constructor with
                                //       argument types compatible with the values we supply here.
                                //       If a plugin does not comply with this requirement then it
                                //       cannot be loaded successfully by the plugin loader and will
                                //       not be available for use by scripts.
                                //
                                // WARNING: Please do not change this because it will prevent any
                                //          plugins from loading that have not been updated to use
                                //          the new argument list.
                                //
                                object[] args = { new PluginData(
                                    FormatOps.PluginName(assemblyName.FullName, typeName),
                                    null, null, clientData, flags, assemblyName.Version, uri,
                                    null, null, assemblyName, fileName, typeName, null, null,
                                    null, null, null, null, null, 0)
                                };

                                //
                                // NOTE: Attempt to create an instance of the plugin.  If this throws
                                //       an exception then the plugin probably does not have a
                                //       constructor matching the arguments we are attempting to
                                //       supply; therefore, it is not in compliance with the plugin
                                //       loader interface and cannot be loaded.  Another common cause
                                //       of failures here is that the plugin has a different version
                                //       of the Eagle runtime library specified in its manifest than
                                //       the one currently running.
                                //
                                if (loadFrom)
                                {
                                    plugin = (IPlugin)appDomain.CreateInstanceFromAndUnwrap(
                                        assemblyName.ToString(), typeName, false,
                                        RuntimeOps.CreateInstanceBindingFlags, null, args,
                                        null, null, null);
                                }
                                else
                                {
                                    plugin = (IPlugin)appDomain.CreateInstanceAndUnwrap(
                                        assemblyName.ToString(), typeName, false,
                                        RuntimeOps.CreateInstanceBindingFlags, null, args,
                                        null, null, null);
                                }

                                if (plugin != null)
                                {
                                    //
                                    // NOTE: All plugins must have an ObjectId attribute.  Attempt
                                    //       to assign the ObjectId attribute to the Id property now.
                                    //
                                    if (plugin.Id.Equals(Guid.Empty))
                                        plugin.Id = AttributeOps.GetObjectId(plugin);

                                    //
                                    // NOTE: We need the plugin to have a valid assembly within it so
                                    //       that the command and policy loaders will be able to use
                                    //       it.
                                    //
                                    PluginCreateHelper createHelper =
                                        new PluginCreateHelper(plugin, assemblyName);

                                    appDomain.DoCallBack(createHelper.Setup);

                                    code = ReturnCode.Ok;
                                }
                                else
                                {
                                    error = "invalid plugin";
                                    code = ReturnCode.Error;
                                }
                            }
                            catch (Exception e)
                            {
                                error = e;
                                code = ReturnCode.Error;
                            }
                        }
                        else
                        {
                            error = "invalid uri";
                            code = ReturnCode.Error;
                        }
                    }
                    else
                    {
                        error = "invalid type name";
                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    error = "invalid assembly name";
                    code = ReturnCode.Error;
                }
            }
            else
            {
                error = "invalid application domain";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode CreatePlugin(
            AppDomain appDomain,
            Assembly assembly,
            string fileName,
            string typeName,
            IClientData clientData,
            PluginFlags flags,
            ref IPlugin plugin,
            ref Result error
            )
        {
            ReturnCode code;

            if (appDomain != null)
            {
                if (assembly != null)
                {
                    AssemblyName assemblyName = assembly.GetName();

                    if (assemblyName != null)
                    {
                        if (typeName != null)
                        {
                            try
                            {
                                Type type = assembly.GetType(typeName, true, false);

                                if (type != null)
                                {
                                    //
                                    // NOTE: Get the plugin flags related to the assembly itself and
                                    //       combine them with the ones we already have.
                                    //
                                    flags |= RuntimeOps.GetAssemblyPluginFlags(assembly,
                                        RuntimeOps.GetSkipCheckPluginFlags());

                                    //
                                    // NOTE: Check if the plugin assembly contains a an AssemblyUri
                                    //       attribute.
                                    //
                                    Uri uri = AttributeOps.GetAssemblyUri(assembly);

                                    //
                                    // NOTE: If the plugin assembly does NOT contain an AssemblyUri
                                    //       attribute, use the location.
                                    //
                                    if (uri == null)
                                        uri = new Uri(assembly.Location); /* throw */

                                    //
                                    // NOTE: Setup the arguments for the plugin constructor.
                                    //       Unfortunately, constructors cannot be part of an interface;
                                    //       however, we require all plugins to expose a constructor with
                                    //       argument types compatible with the values we supply here.
                                    //       If a plugin does not comply with this requirement then it
                                    //       cannot be loaded successfully by the plugin loader and will
                                    //       not be available for use by scripts.
                                    //
                                    // WARNING: Please do not change this because it will prevent any
                                    //          plugins from loading that have not been updated to use
                                    //          the new argument list.
                                    //
                                    object[] args = { new PluginData(
                                        FormatOps.PluginName(assemblyName.FullName, typeName),
                                        null, null, clientData, flags, assemblyName.Version, uri,
                                        appDomain, assembly, assemblyName, fileName, typeName, null,
                                        null, null, null, null, null, null, 0)
                                    };

                                    //
                                    // NOTE: Attempt to create an instance of the plugin.  If this throws
                                    //       an exception then the plugin probably does not have a
                                    //       constructor matching the arguments we are attempting to
                                    //       supply; therefore, it is not in compliance with the plugin
                                    //       loader interface and cannot be loaded.  Another common cause
                                    //       of failures here is that the plugin has a different version
                                    //       of the Eagle runtime library specified in its manifest than
                                    //       the one currently running.
                                    //
                                    plugin = (IPlugin)assembly.CreateInstance(type.FullName, false,
                                        RuntimeOps.CreateInstanceBindingFlags, null, args, null, null);

                                    if (plugin != null)
                                    {
                                        //
                                        // NOTE: All plugins must have an ObjectId attribute.  Attempt
                                        //       to assign the ObjectId attribute to the Id property now.
                                        //
                                        if (plugin.Id.Equals(Guid.Empty))
                                            plugin.Id = AttributeOps.GetObjectId(plugin);

                                        code = RuntimeOps.PopulatePluginCommands(plugin, ref error);

                                        if (code == ReturnCode.Ok)
                                            code = RuntimeOps.PopulatePluginPolicies(plugin, ref error);
                                    }
                                    else
                                    {
                                        error = "invalid plugin";
                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    error = "type not found";
                                    code = ReturnCode.Error;
                                }
                            }
                            catch (Exception e)
                            {
                                error = e;
                                code = ReturnCode.Error;
                            }
                        }
                        else
                        {
                            error = "invalid type name";
                            code = ReturnCode.Error;
                        }
                    }
                    else
                    {
                        error = "invalid assembly name";
                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    error = "invalid assembly";
                    code = ReturnCode.Error;
                }
            }
            else
            {
                error = "invalid application domain";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetPluginCommands( /* POLICY HELPER METHOD */
            IPlugin plugin,
            ref List<ICommand> commands,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (plugin != null)
                {
                    if (HasCommands(ref error))
                    {
                        List<ICommand> localCommands = new List<ICommand>();

                        foreach (ICommandData commandData in plugin.Commands)
                        {
                            ICommand command = null;

                            if (GetCommand(
                                    EntityOps.GetToken(commandData),
                                    LookupFlags.Default, ref command,
                                    ref error) == ReturnCode.Ok)
                            {
                                localCommands.Add(command);
                            }
                            else if (GetHiddenCommand(
                                    EntityOps.GetToken(commandData),
                                    LookupFlags.Default, ref command,
                                    ref error) == ReturnCode.Ok)
                            {
                                localCommands.Add(command);
                            }
                            else
                            {
                                return ReturnCode.Error;
                            }
                        }

                        if (commands == null)
                            commands = new List<ICommand>(localCommands);
                        else
                            commands.AddRange(localCommands);

                        return ReturnCode.Ok;
                    }
                }
                else
                {
                    error = "invalid plugin";
                }

                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IPlugin GetCorePlugin(
            ref Result error
            )
        {
            if (corePluginToken != 0)
            {
                IPlugin plugin = null;

                if (GetPlugin(corePluginToken, LookupFlags.Default,
                        ref plugin, ref error) == ReturnCode.Ok)
                {
                    return plugin;
                }
            }
            else
            {
                error = "invalid core plugin token";
            }

            return null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private IPlugin NewCorePlugin()
        {
            Assembly assembly = GlobalState.GetAssembly();
            string typeName = typeof(_Plugins.Core).FullName;

            return new _Plugins.Core(new PluginData(
                FormatOps.PluginName(GlobalState.GetAssemblyFullName(), typeName),
                null, null, ClientData.Empty, RuntimeOps.GetAssemblyPluginFlags(assembly,
                RuntimeOps.GetSkipCheckPluginFlags()), GlobalState.GetAssemblyVersion(),
                GlobalState.GetAssemblyUri(), appDomain, assembly,
                GlobalState.GetAssemblyName(), GlobalState.GetAssemblyLocation(),
                typeName, null, null, null, null, null, null, resourceManager, 0));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
        private IPlugin NewObjectPlugin()
        {
            Assembly assembly = GlobalState.GetAssembly();
            string typeName = typeof(_Plugins.Object).FullName;

            return new _Plugins.Object(new PluginData(
                FormatOps.PluginName(GlobalState.GetAssemblyFullName(), typeName),
                null, null, ClientData.Empty, RuntimeOps.GetAssemblyPluginFlags(assembly,
                RuntimeOps.GetSkipCheckPluginFlags()), GlobalState.GetAssemblyVersion(),
                GlobalState.GetAssemblyUri(), appDomain, assembly,
                GlobalState.GetAssemblyName(), GlobalState.GetAssemblyLocation(),
                typeName, null, null, null, null, null, null, resourceManager, 0));
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUG
        internal IPlugin GetTestPlugin(
            ref Result error
            )
        {
            if (testPluginToken != 0)
            {
                IPlugin plugin = null;

                if (GetPlugin(testPluginToken, LookupFlags.Default,
                        ref plugin, ref error) == ReturnCode.Ok)
                {
                    return plugin;
                }
            }
            else
            {
                error = "invalid test plugin token";
            }

            return null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private IPlugin NewTestPlugin()
        {
            Assembly assembly = GlobalState.GetAssembly();
            string typeName = typeof(_Plugins.Test).FullName;

            return new _Plugins.Test(new PluginData(
                FormatOps.PluginName(GlobalState.GetAssemblyFullName(), typeName),
                null, null, ClientData.Empty, RuntimeOps.GetAssemblyPluginFlags(assembly,
                RuntimeOps.GetSkipCheckPluginFlags()), GlobalState.GetAssemblyVersion(),
                GlobalState.GetAssemblyUri(), appDomain, assembly,
                GlobalState.GetAssemblyName(), GlobalState.GetAssemblyLocation(),
                typeName, null, null, null, null, null, null, resourceManager, 0));
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region PluginPropertyHelper Class (MarshalByRefObject)
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("0a332e4c-1619-45ce-b624-14099e37cb7a")]
        private sealed class PluginPropertyHelper
#if ISOLATED_INTERPRETERS || ISOLATED_PLUGINS
            : ScriptMarshalByRefObject
#endif
        {
            #region Private Data
            private AssemblyName assemblyName;
            private string fileName;
            private string typeName;
            private Uri uri;
            private PluginFlags pluginFlags;
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Constructors
            public PluginPropertyHelper()
            {
                // do nothing.
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Properties
            public AssemblyName AssemblyName
            {
                get { return assemblyName; }
                set { assemblyName = value; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public string FileName
            {
                get { return fileName; }
                set { fileName = value; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public string TypeName
            {
                get { return typeName; }
                set { typeName = value; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public Uri Uri
            {
                get { return uri; }
                set { uri = value; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public PluginFlags PluginFlags
            {
                get { return pluginFlags; }
                set { pluginFlags = value; }
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region PluginCreateHelper Class (Serializable)
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("44989f7c-828c-4170-8655-404ee607460e")]
        private sealed class PluginCreateHelper
        {
            #region Private Constants
            private const string InvalidPluginError = "invalid plugin";
            private const string InvalidAssemblyNameError = "invalid assembly name";
            private const string PluginAppDomainAlreadySetError = "plugin application domain already set";
            private const string PluginAssemblyAlreadySetError = "plugin assembly name already set";
            private const string CouldNotPopulatePluginCommandsError = "could not populate plugin commands";
            private const string CouldNotPopulatePluginPoliciesError = "could not populate plugin policies";
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Private Data
            private IPlugin plugin; /* in */
            private AssemblyName assemblyName; /* in */
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Constructors
            public PluginCreateHelper(
                IPlugin plugin,
                AssemblyName assemblyName
                )
            {
                this.plugin = plugin;
                this.assemblyName = assemblyName;
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Methods
            public void Setup()
            {
                if (plugin == null)
                    throw new InvalidOperationException(InvalidPluginError);

                if (assemblyName == null)
                    throw new InvalidOperationException(InvalidAssemblyNameError);

                if (plugin.AppDomain != null)
                    throw new InvalidOperationException(PluginAppDomainAlreadySetError);

                if (plugin.Assembly != null)
                    throw new InvalidOperationException(PluginAssemblyAlreadySetError);

                //
                // NOTE: Setup the application domain and assembly for the
                //       plugin.
                //
                AppDomain appDomain = AppDomain.CurrentDomain;

                plugin.AppDomain = appDomain;
                plugin.Assembly = AssemblyOps.FindInAppDomain(
                    appDomain, assemblyName);

                //
                // NOTE: Get the command and policy type metadata for this
                //       plugin now because this cannot be done from the
                //       primary application domain.
                //
                ReturnCode code;
                Result error = null;

                code = RuntimeOps.PopulatePluginCommands(plugin, ref error);

                if (code != ReturnCode.Ok)
                    throw new TypeLoadException(
                        CouldNotPopulatePluginCommandsError,
                        new ScriptException(code, error));

                code = RuntimeOps.PopulatePluginPolicies(plugin, ref error);

                if (code != ReturnCode.Ok)
                    throw new TypeLoadException(
                        CouldNotPopulatePluginPoliciesError,
                        new ScriptException(code, error));
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region PluginLoadHelper Class (Serializable)
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("532f533d-6b21-45d8-8139-54c7a4be4dbd")]
        private sealed class PluginLoadHelper
        {
            #region Private Constants
            private const string AppDomainNotAvailableError = "application domain not available";
            private const string AssemblyNotLoadedError = "assembly not loaded";
            private const string AssemblyAlreadyLoadedError = "assembly already loaded";
            private const string AssemblyNameAlreadySetError = "assembly name already set";
            private const string TypeAlreadySetError = "type already set";
            private const string PrimaryPluginTypeNotFoundError = "primary plugin type not found";
            private const string UriAlreadySetError = "uri already set";
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Private Data
#if SERIALIZATION
            [NonSerialized()]
#endif
            private AppDomain appDomain;

            private bool viaBytes;

            private byte[] assemblyBytes; /* in */
            private byte[] symbolBytes; /* in */

            private string fileName; /* in */
            private string typeName; /* in, out */

#if CAS_POLICY
#if SERIALIZATION
            [NonSerialized()]
#endif
            private Evidence evidence; /* in */

#if !MONO && !MONO_HACKS
            private byte[] hashValue; /* in */
            private AssemblyHashAlgorithm hashAlgorithm; /* in */
#endif
#endif

            private PluginPropertyHelper propertyHelper; /* in, out */
            private bool setup; /* in */
            private bool verbose; /* in */

#if SERIALIZATION
            [NonSerialized()]
#endif
            private Assembly assembly; /* out */

#if SERIALIZATION
            [NonSerialized()]
#endif
            private Type type; /* out */

            private AssemblyName assemblyName; /* out */
            private Uri uri; /* out */
            private PluginFlags pluginFlags; /* out */
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Constructors
            public PluginLoadHelper(
                byte[] assemblyBytes,
                byte[] symbolBytes,
                string fileName,
                string typeName,
#if CAS_POLICY
                Evidence evidence,
#if !MONO && !MONO_HACKS
                byte[] hashValue,
                AssemblyHashAlgorithm hashAlgorithm,
#endif
#endif
                PluginPropertyHelper propertyHelper,
                bool setup,
                bool verbose
                )
            {
                this.assemblyBytes = assemblyBytes;
                this.symbolBytes = symbolBytes;

                this.fileName = fileName;
                this.typeName = typeName;

#if CAS_POLICY
                this.evidence = evidence;

#if !MONO && !MONO_HACKS
                this.hashValue = hashValue;
                this.hashAlgorithm = hashAlgorithm;
#endif
#endif

                this.propertyHelper = propertyHelper;
                this.setup = setup;
                this.verbose = verbose;
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Private Event Handlers
#if ISOLATED_PLUGINS
            private Assembly AssemblyResolve(
                object sender,
                ResolveEventArgs args
                )
            {
                if ((args == null) || (assemblyName == null))
                    return null;

                //
                // NOTE: This event handler does not resolve assemblies that
                //       already have a context (i.e. the Load or LoadFrom
                //       contexts used to load via an AssemblyName or file
                //       name, respectively).
                //
                if ((assemblyBytes == null) || (fileName != null))
                    return null;

                //
                // TODO: Is this the right string comparison to use here?
                //
                if (String.Equals(args.Name, assemblyName.FullName,
                        StringOps.SystemStringComparisonType))
                {
                    return assembly;
                }

                return null;
            }
#endif
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Private Methods
            private void SetupAppDomain()
            {
                if (appDomain == null)
                {
                    //
                    // NOTE: Use the current application domain.  This is correct
                    //       because this method should only ever called when the
                    //       correct application domain is on the call stack.
                    //
                    appDomain = AppDomain.CurrentDomain;

                    ///////////////////////////////////////////////////////////////////////////////////

#if ISOLATED_PLUGINS
                    //
                    // NOTE: Setup our assembly resolution event handler so that
                    //       it can deal with resolving an assemblies loaded via
                    //       a byte array (i.e. which has no context).
                    //
                    appDomain.AssemblyResolve += new ResolveEventHandler(
                        AssemblyResolve);
#endif
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private void Setup() /* throw */
            {
                SetupAppDomain();

                if (verbose)
                    DebugOps.DumpAppDomain(appDomain);

                SetupAssemblyName(); /* throw */
                SetupTypeName(); /* throw */
                SetupUri(); /* throw */
                SetupAssemblyPluginFlags(); /* throw */

                //
                // NOTE: If the property helper was provided, use it to send our
                //       output data back to the other application domain.
                //
                if (propertyHelper != null)
                {
                    propertyHelper.AssemblyName = assemblyName;
                    propertyHelper.FileName = fileName;
                    propertyHelper.TypeName = typeName;
                    propertyHelper.Uri = uri;
                    propertyHelper.PluginFlags = pluginFlags;
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private void SetupAssemblyName()
            {
                if (assembly == null)
                    throw new InvalidOperationException(AssemblyNotLoadedError);

                if (assemblyName != null)
                    throw new InvalidOperationException(AssemblyNameAlreadySetError);

                //
                // NOTE: Get the full name of the assembly and store it for
                //       later use by the plugin loader.
                //
                assemblyName = assembly.GetName();
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private void SetupAssemblyPluginFlags()
            {
                if (assembly == null)
                    throw new InvalidOperationException(AssemblyNotLoadedError);

                if (viaBytes)
                {
                    pluginFlags |= RuntimeOps.GetAssemblyPluginFlags(assembly,
                        assemblyBytes, RuntimeOps.GetSkipCheckPluginFlags());
                }
                else
                {
                    pluginFlags |= RuntimeOps.GetAssemblyPluginFlags(assembly,
                        RuntimeOps.GetSkipCheckPluginFlags());
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private void SetupTypeName()
            {
                if (assembly == null)
                    throw new InvalidOperationException(AssemblyNotLoadedError);

                if (type != null)
                    throw new InvalidOperationException(TypeAlreadySetError);

                //
                // NOTE: Do they want a specific plugin type or simply the
                //       default one?
                //
                if (!String.IsNullOrEmpty(typeName))
                {
                    type = assembly.GetType(typeName, true, false); /* throw */

                    //
                    // NOTE: Did we find the type?  For now, this should already be
                    //       true because the above code should throw an exception
                    //       if the type is not found.
                    //
                    if (type != null)
                        typeName = type.FullName;
                }
                else
                {
                    ReturnCode code;
                    Result error = null;

                    code = RuntimeOps.FindPrimaryPlugin(assembly, ref typeName, ref error);

                    if (code == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Attempt to get the type from the assembly now.
                        //
                        type = assembly.GetType(typeName, true, false); /* throw */
                    }
                    else
                    {
                        throw new TypeLoadException(
                            PrimaryPluginTypeNotFoundError,
                            new ScriptException(code, error));
                    }
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private void SetupUri()
            {
                if (assembly == null)
                    throw new InvalidOperationException(AssemblyNotLoadedError);

                if (uri != null)
                    throw new InvalidOperationException(UriAlreadySetError);

                //
                // NOTE: Check if the plugin assembly contains a an AssemblyUri
                //       attribute.
                //
                uri = AttributeOps.GetAssemblyUri(assembly);

                //
                // NOTE: If the plugin assembly does NOT contain an AssemblyUri
                //       attribute, use the location.
                //
                if (uri == null)
                    uri = new Uri(assembly.Location); /* throw */
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Properties
            public AppDomain AppDomain
            {
                get { SetupAppDomain(); return appDomain; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public Assembly Assembly
            {
                get { return assembly; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public PluginPropertyHelper PropertyHelper
            {
                get { return propertyHelper; }
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Methods
#if !CAS_POLICY
            public void NoCasLoad1()
            {
                if (assembly != null)
                    throw new InvalidOperationException(AssemblyAlreadyLoadedError);

                //
                // NOTE: Load the assembly into this AppDomain now.
                //
                assembly = Assembly.LoadFrom(fileName); /* throw */

                //
                // NOTE: This assembly was NOT loaded via an array of bytes.
                //
                viaBytes = false;

                //
                // NOTE: Perform the post-load setup steps?
                //
                if (setup)
                    Setup(); /* throw */
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public void NoCasLoad2()
            {
                if (assembly != null)
                    throw new InvalidOperationException(AssemblyAlreadyLoadedError);

                SetupAppDomain();

                if (appDomain == null)
                    throw new InvalidOperationException(AppDomainNotAvailableError);

                //
                // NOTE: Load the raw assembly into this AppDomain now.
                //
                assembly = appDomain.Load(assemblyBytes, symbolBytes);

                //
                // NOTE: This assembly was loaded via an array of bytes.
                //
                viaBytes = true;

                //
                // NOTE: Perform the post-load setup steps?
                //
                if (setup)
                    Setup(); /* throw */
            }
#endif

            ///////////////////////////////////////////////////////////////////////////////////////////

#if CAS_POLICY
            public void CasLoad2()
            {
                if (assembly != null)
                    throw new InvalidOperationException(AssemblyAlreadyLoadedError);

                //
                // NOTE: Load the assembly into this AppDomain using the
                //       provided evidence now.
                //
                assembly = Assembly.LoadFrom(fileName, evidence); /* throw */

                //
                // NOTE: This assembly was NOT loaded via an array of bytes.
                //
                viaBytes = false;

                //
                // NOTE: Perform the post-load setup steps?
                //
                if (setup)
                    Setup(); /* throw */
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public void CasLoad3()
            {
                if (assembly != null)
                    throw new InvalidOperationException(AssemblyAlreadyLoadedError);

                SetupAppDomain();

                if (appDomain == null)
                    throw new InvalidOperationException(AppDomainNotAvailableError);

                //
                // NOTE: Load the raw assembly into this AppDomain using the
                //       provided evidence now.
                //
                assembly = appDomain.Load(
                    assemblyBytes, symbolBytes, evidence); /* throw */

                //
                // NOTE: This assembly was loaded via an array of bytes.
                //
                viaBytes = true;

                //
                // NOTE: Perform the post-load setup steps?
                //
                if (setup)
                    Setup(); /* throw */
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

#if !MONO && !MONO_HACKS
            public void CasLoad4()
            {
                if (assembly != null)
                    throw new InvalidOperationException(AssemblyAlreadyLoadedError);

                //
                // NOTE: Load the assembly into this AppDomain using the
                //       provided evidence and hash parameters now.
                //
                assembly = Assembly.LoadFrom(
                    fileName, evidence, hashValue, hashAlgorithm); /* throw */

                //
                // NOTE: This assembly was NOT loaded via an array of bytes.
                //
                viaBytes = false;

                //
                // NOTE: Perform the post-load setup steps?
                //
                if (setup)
                    Setup(); /* throw */
            }
#endif
#endif
            #endregion
        }
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IPropertyManager Members
        public object ApplicationObject
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return applicationObject;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    applicationObject = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public object PolicyObject
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return policyObject;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    policyObject = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public object ResolverObject
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return resolverObject;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    resolverObject = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public object UserObject
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return userObject;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    userObject = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public StringDictionary RuntimeOptions
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return runtimeOptions;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    runtimeOptions = value;
                }

                //
                // NOTE: Do not create the variable if we have been prohibited
                //       from doing so.
                //
                VariableFlags flags = VariableFlags.ViaProperty;

                if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                    FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                {
                    flags |= VariableFlags.NoCreate;
                }

                //
                // NOTE: Update script-level informational variable.
                //
                SetLibraryVariableValue2(
                    flags, Vars.Platform.Name, Vars.Platform.RuntimeOptions,
                    value.ToString());
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool HasRuntimeOption(
            string name
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (String.IsNullOrEmpty(name))
                    return false;

                return (runtimeOptions != null) &&
                    runtimeOptions.ContainsKey(name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool ClearRuntimeOptions()
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false))
                    return false;

                if (runtimeOptions != null)
                {
                    runtimeOptions.Clear();

                    //
                    // NOTE: Do not create the variable if we have been prohibited
                    //       from doing so.
                    //
                    VariableFlags flags = VariableFlags.ViaProperty;

                    if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                        FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                    {
                        flags |= VariableFlags.NoCreate;
                    }

                    //
                    // NOTE: Update script-level informational variable.
                    //
                    /* IGNORED */
                    SetLibraryVariableValue2(flags, Vars.Platform.Name,
                        Vars.Platform.RuntimeOptions,
                        runtimeOptions.ToString());

                    return true;
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool AddRuntimeOption(
            string name
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true))
                    return false;

                if (String.IsNullOrEmpty(name))
                    return false;

                if ((runtimeOptions != null) &&
                    !runtimeOptions.ContainsKey(name)) /* EXEMPT */
                {
                    runtimeOptions.Add(name, null);

                    //
                    // NOTE: Do not create the variable if we have been prohibited
                    //       from doing so.
                    //
                    VariableFlags flags = VariableFlags.ViaProperty;

                    if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                        FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                    {
                        flags |= VariableFlags.NoCreate;
                    }

                    //
                    // NOTE: Update script-level informational variable.
                    //
                    /* IGNORED */
                    SetLibraryVariableValue2(flags, Vars.Platform.Name,
                        Vars.Platform.RuntimeOptions,
                        runtimeOptions.ToString());

                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool RemoveRuntimeOption(
            string name
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false))
                    return false;

                if (String.IsNullOrEmpty(name))
                    return false;

                if ((runtimeOptions != null) &&
                    runtimeOptions.ContainsKey(name))
                {
                    bool result = runtimeOptions.Remove(name);

                    //
                    // NOTE: Do not create the variable if we have been prohibited
                    //       from doing so.
                    //
                    VariableFlags flags = VariableFlags.ViaProperty;

                    if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                        FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                    {
                        flags |= VariableFlags.NoCreate;
                    }

                    //
                    // NOTE: Update script-level informational variable.
                    //
                    /* IGNORED */
                    SetLibraryVariableValue2(flags, Vars.Platform.Name,
                        Vars.Platform.RuntimeOptions,
                        runtimeOptions.ToString());

                    return result;
                }
                else
                {
                    return false;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool ChangeRuntimeOption(
            string name
            )
        {
            CheckDisposed();

            if (String.IsNullOrEmpty(name))
                return false;

            switch (name[0])
            {
                case Characters.PlusSign:
                    {
                        if (name.Length > 1)
                            return AddRuntimeOption(name.Substring(1));

                        break;
                    }
                case Characters.MinusSign:
                    {
                        if (name.Length > 1)
                            return RemoveRuntimeOption(name.Substring(1));

                        break;
                    }
                case Characters.EqualSign:
                    {
                        if (name.Length > 1)
                            return ClearRuntimeOptions() &&
                                AddRuntimeOption(name.Substring(1));

                        break;
                    }
                default:
                    {
                        if (Parser.IsIdentifier(name[0]))
                            return AddRuntimeOption(name);

                        break;
                    }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool ThrowOnFeatureNotSupported
        {
            get
            {
                lock (syncRoot)
                {
                    return throwOnFeatureNotSupported;
                }
            }
            set
            {
                lock (syncRoot)
                {
                    throwOnFeatureNotSupported = value;
                }
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IResolveManager Members
        #region Variable Frame Resolution (WARNING: EXPERIMENTAL)
        public ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags,         /* in */
            ref ICallFrame frame,            /* in, out */
            ref string varName,              /* in, out */
            ref VariableFlags variableFlags, /* in, out */
            ref Result error                 /* out */
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasResolvers(ref  error))
                {
                    ResultList errors = null;

                    foreach (IResolve resolve in resolvers)
                    {
                        if (resolve != null)
                        {
                            Result localError = null;

                            try
                            {
                                ReturnCode code = resolve.GetVariableFrame(
                                    ref frame, ref varName, ref variableFlags,
                                    ref localError);

                                if (code == ReturnCode.Ok)
                                    return ReturnCode.Ok;
                            }
                            catch (Exception e)
                            {
                                if (FlagOps.HasFlags(
                                        lookupFlags, LookupFlags.Verbose, true))
                                {
                                    localError = e;
                                }
                            }

                            if (errors == null)
                                errors = new ResultList();

                            if (localError != null)
                                errors.Add(localError);
                        }
                    }

                    if (errors != null)
                        error = errors;
                    else
                        error = "no resolvers defined";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags, /* in */
            ref ICallFrame frame,    /* in, out */
            ref Result error         /* out */
            )
        {
            string varName = null;
            VariableFlags variableFlags = VariableFlags.None;

            return GetVariableFrameViaResolvers(
                LookupFlags.Default, ref frame, ref varName, ref variableFlags,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags, /* in */
            ref ICallFrame frame,    /* in, out */
            ref string varName,      /* in, out */
            ref Result error         /* out */
            )
        {
            VariableFlags variableFlags = VariableFlags.None;

            return GetVariableFrameViaResolvers(
                LookupFlags.Default, ref frame, ref varName, ref variableFlags,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags,
            ref ICallFrame frame
            )
        {
            string varName = null;
            VariableFlags variableFlags = VariableFlags.None;
            Result error = null;

            return GetVariableFrameViaResolvers(
                LookupFlags.Default, ref frame, ref varName, ref variableFlags,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags,
            ref ICallFrame frame,
            ref VariableFlags variableFlags
            )
        {
            string varName = null;
            Result error = null;

            return GetVariableFrameViaResolvers(
                LookupFlags.Default, ref frame, ref varName, ref variableFlags,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags,
            ref ICallFrame frame,
            ref VariableFlags variableFlags,
            ref Result error
            )
        {
            string varName = null;

            return GetVariableFrameViaResolvers(
                LookupFlags.Default, ref frame, ref varName, ref variableFlags,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableFrameViaResolvers(
            LookupFlags lookupFlags,
            ref ICallFrame frame,
            ref string varName,
            ref VariableFlags variableFlags
            )
        {
            Result error = null;

            return GetVariableFrameViaResolvers(
                lookupFlags, ref frame, ref varName, ref variableFlags, ref error);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace Management (WARNING: EXPERIMENTAL)
        //
        // WARNING: *EXPERIMENTAL* This API may change until the
        //          resolver subsystem is completed.
        //
        public ReturnCode GetGlobalNamespace(
            LookupFlags lookupFlags, /* NOTE: NOT USED. */
            ref INamespace @namespace,
            ref Result result /* NOTE: NOT USED, cannot currently fail. */
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                @namespace = globalNamespace;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: *EXPERIMENTAL* This API may change until the
        //          resolver subsystem is completed.
        //
        public ReturnCode GetCurrentNamespaceViaResolvers(
            ICallFrame frame,
            LookupFlags lookupFlags,
            ref INamespace @namespace,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasResolvers(ref  error))
                {
                    ResultList errors = null;

                    foreach (IResolve resolve in resolvers)
                    {
                        if (resolve != null)
                        {
                            Result localError = null;

                            try
                            {
                                ReturnCode code = resolve.GetCurrentNamespace(
                                    frame, ref @namespace, ref localError);

                                if (code == ReturnCode.Ok)
                                    return ReturnCode.Ok;
                            }
                            catch (Exception e)
                            {
                                if (FlagOps.HasFlags(
                                        lookupFlags, LookupFlags.Verbose, true))
                                {
                                    localError = e;
                                }
                            }

                            if (errors == null)
                                errors = new ResultList();

                            if (localError != null)
                                errors.Add(localError);
                        }
                    }

                    if (errors != null)
                        error = errors;
                    else
                        error = "no resolvers defined";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool IsGlobalNamespace(
            INamespace @namespace
            )
        {
            return Object.ReferenceEquals(
                @namespace, globalNamespace);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetCurrentNamespaceViaResolvers(
            ICallFrame frame,
            LookupFlags lookupFlags,
            ref INamespace @namespace
            )
        {
            Result result = null;

            return GetCurrentNamespaceViaResolvers(
                frame, lookupFlags, ref @namespace, ref result);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Call Frame Management (WARNING: EXPERIMENTAL)
        //
        // WARNING: *EXPERIMENTAL* This API may change until the
        //          resolver subsystem is completed.
        //
        public ReturnCode GetCallFrame( /* EXPERIMENTAL */
            bool absolute,              /* in */
            int level,                  /* in */
            CallFrameFlags hasFlags,    /* in */
            CallFrameFlags notHasFlags, /* in */
            bool hasAll,                /* in */
            bool notHasAll,             /* in */
            ref ICallFrame frame,       /* in, out */
            ref Result error            /* out */
            )
        {
            CheckDisposed();

#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                ICallFrame currentFrame =
                    (frame != null) ? frame : CurrentFrame;

                return CallFrameOps.GetOrFind(
                    CallStack, GlobalFrame, currentFrame, absolute, level,
                    hasFlags, notHasFlags, hasAll, notHasAll, ref frame,
                    ref error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal FrameResult GetCallFrame(
            string text,
            ref ICallFrame otherFrame,
            ref Result error
            )
        {
            //
            // BUGBUG: Why not use the NoVariables (Tracking) flag here?
            //
            return Value.GetCallFrame(text,
                LevelFlags.All, CallStack, GlobalFrame, CurrentFrame,
                CallFrameFlags.Variables, CallFrameFlags.Invisible |
                CallFrameFlags.NoVariables, false, false,
                Value.GetCallFrameValueFlags(false), CultureInfo,
                ref otherFrame, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal FrameResult GetCallFrame(
            string text,
            ref bool mark,
            ref bool absolute,
            ref int level,
            ref ICallFrame currentFrame,
            ref ICallFrame otherFrame,
            ref Result error
            )
        {
            //
            // BUGBUG: Why not use the NoVariables (Tracking) flag here?
            //
            currentFrame = CurrentFrame;

            return Value.GetCallFrame(
                text, LevelFlags.All, CallStack, GlobalFrame,
                currentFrame, CallFrameFlags.Variables,
                CallFrameFlags.Invisible | CallFrameFlags.NoVariables,
                false, false, Value.GetCallFrameValueFlags(false),
                CultureInfo, ref mark, ref absolute, ref level,
                ref otherFrame, ref error);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Command & Variable Resolution (WARNING: EXPERIMENTAL)
        //
        // WARNING: *EXPERIMENTAL* This API may change until the
        //          resolver subsystem is completed.
        //
        public ReturnCode GetIExecuteViaResolvers( /* EXPERIMENTAL */
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasResolvers(ref error))
                {
                    ResultList errors = null;

                    foreach (IResolve resolve in resolvers)
                    {
                        if (resolve != null)
                        {
                            Result localError = null;

                            try
                            {
                                ReturnCode code = resolve.GetIExecute(frame,
                                    engineFlags, name, arguments, lookupFlags,
                                    ref ambiguous, ref token, ref execute,
                                    ref localError);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Success, return the entity that
                                    //       this resolver found.
                                    //
                                    return ReturnCode.Ok;
                                }
                                else if (code == ReturnCode.Return)
                                {
                                    //
                                    // NOTE: Failure, return the error that
                                    //       this resolver returned verbatim.
                                    //
                                    error = localError;

                                    return ReturnCode.Error;
                                }
                                else if (code == ReturnCode.Break)
                                {
                                    //
                                    // NOTE: Failure, skip all other resolvers
                                    //       for this entity and return all the
                                    //       previously collected errors.
                                    //
                                    break;
                                }
                                else if (code == ReturnCode.Continue)
                                {
                                    //
                                    // NOTE: Failure, keep trying; however, do
                                    //       not add the error message from this
                                    //       resolver.
                                    //
                                    continue;
                                }
                            }
                            catch (Exception e)
                            {
                                if (FlagOps.HasFlags(
                                        lookupFlags, LookupFlags.Verbose, true))
                                {
                                    localError = e;
                                }
                            }

                            if (errors == null)
                                errors = new ResultList();

                            if (localError != null)
                                errors.Add(localError);
                        }
                    }

                    if (errors != null)
                        error = errors;
                    else
                        error = "no resolvers defined";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: *EXPERIMENTAL* This API may change until the
        //          resolver subsystem is completed.
        //
        public ReturnCode GetVariableViaResolvers( /* EXPERIMENTAL */
            ICallFrame frame,
            string varName,
            string varIndex,
            ref VariableFlags flags,
            ref IVariable variable,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (HasResolvers(ref error))
                {
                    bool resolveNull = FlagOps.HasFlags(
                        flags, VariableFlags.ResolveNull, true);

                    ResultList errors = null;

                    foreach (IResolve resolve in resolvers)
                    {
                        if (resolve != null)
                        {
                            Result localError = null;

                            try
                            {
                                ReturnCode code = resolve.GetVariable(
                                    frame, varName, varIndex, ref flags,
                                    ref variable, ref localError);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Success, return the entity that
                                    //       this resolver found.  If the
                                    //       entity is now null and that is
                                    //       disallowed via the flags, fail.
                                    //
                                    if (!resolveNull && (variable == null))
                                    {
                                        error = String.Format(
                                            "can't resolve {0}: variable is invalid",
                                            FormatOps.ErrorVariableName(varName, varIndex));

                                        return ReturnCode.Error;
                                    }

                                    return ReturnCode.Ok;
                                }
                                else if (code == ReturnCode.Return)
                                {
                                    //
                                    // NOTE: Failure, return the error that
                                    //       this resolver returned verbatim.
                                    //
                                    error = localError;

                                    return ReturnCode.Error;
                                }
                                else if (code == ReturnCode.Break)
                                {
                                    //
                                    // NOTE: Failure, skip all other resolvers
                                    //       for this entity and return all the
                                    //       previously collected errors.
                                    //
                                    break;
                                }
                                else if (code == ReturnCode.Continue)
                                {
                                    //
                                    // NOTE: Failure, keep trying; however, do
                                    //       not add the error message from this
                                    //       resolver.
                                    //
                                    continue;
                                }
                            }
                            catch (Exception e)
                            {
                                localError = e;
                            }

                            if (errors == null)
                                errors = new ResultList();

                            if (localError != null)
                                errors.Add(localError);
                        }
                    }

                    if (errors != null)
                        error = errors;
                    else
                        error = "no resolvers defined";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal EngineFlags GetResolveEngineFlags(
            bool exact
            )
        {
            return GetResolveEngineFlags(engineFlags, exact);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private EngineFlags GetResolveEngineFlags(
            EngineFlags engineFlags,
            bool exact
            )
        {
            return Engine.GetResolveFlags(engineFlags, exact);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private EngineFlags GetMatchAnyEngineFlags(
            EngineFlags engineFlags,
            bool exact
            )
        {
            EngineFlags result = engineFlags;

            if (exact)
            {
                if (Engine.HasMatchHidden(result))
                    result |= EngineFlags.GetHidden;
            }
            else
            {
                if (Engine.HasGetHidden(result))
                    result |= EngineFlags.MatchHidden;
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool MaybeUnwrapIExecute(
            LookupFlags lookupFlags, /* in */
            IExecute executeWrapper, /* in */
            ref IExecute execute     /* out */
            )
        {
            Result error = null;

            return MaybeUnwrapIExecute(
                lookupFlags, executeWrapper, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool MaybeUnwrapIExecute(
            LookupFlags lookupFlags, /* in */
            IExecute executeWrapper, /* in */
            ref IExecute execute,    /* out */
            ref Result error         /* out */
            )
        {
            if (FlagOps.HasFlags(lookupFlags, LookupFlags.Wrapper, true))
            {
                //
                // NOTE: The caller, PrivateMatchAnyIExecute, must make sure
                //       the "executeWrapper" parameter is in fact a wrapper.
                //
                execute = executeWrapper;
            }
            else
            {
                IWrapper wrapper = executeWrapper as IWrapper;

                if (wrapper != null)
                    execute = wrapper.Object as IExecute;
                else
                    execute = null;
            }

            //
            // NOTE: At this point, either the IExecute must be valid -OR-
            //       the Validate lookup flag must be unset; otherwise, this
            //       method has failed (i.e. thus emulating the behavior of
            //       the associated PrivateGet* methods).
            //
            if ((execute == null) &&
                FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true))
            {
                error = "invalid execute";
                return false;
            }

            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if EXECUTE_CACHE
        private bool PrivateTryGetIExecuteFromCache(
            string newName,
            LookupFlags lookupFlags,
            bool useHidden,
            ref IExecute execute
            )
        {
            lock (syncRoot)
            {
                IExecute localExecute = null;

                if (useHidden)
                {
                    if (hiddenExecuteCache != null)
                    {
                        if (hiddenExecuteCache.TryGet(newName,
                                FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true),
                                ref localExecute))
                        {
                            if (MaybeUnwrapIExecute(
                                    lookupFlags, localExecute, ref localExecute))
                            {
#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref hiddenExecuteCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                                execute = localExecute;
                                return true;
                            }
#if CACHE_STATISTICS
                            else
                            {
                                Interlocked.Increment(
                                    ref hiddenExecuteCache.cacheCounts[(int)CacheCountType.Miss]);
                            }
#endif
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref hiddenExecuteCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
                else
                {
                    if (executeCache != null)
                    {
                        if (executeCache.TryGet(newName,
                                FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true),
                                ref localExecute))
                        {
                            if (MaybeUnwrapIExecute(
                                    lookupFlags, localExecute, ref localExecute))
                            {
#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref executeCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                                execute = localExecute;
                                return true;
                            }
#if CACHE_STATISTICS
                            else
                            {
                                Interlocked.Increment(
                                    ref executeCache.cacheCounts[(int)CacheCountType.Miss]);
                            }
#endif
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref executeCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateGetAnyIExecute(
            ICallFrame frame, /* NOT USED */
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            string newName = ScriptOps.MakeCommandName(name);

#if EXECUTE_CACHE
            bool noCache = Engine.HasNoCache(engineFlags);
#endif

            bool useHidden = Engine.HasUseHidden(engineFlags);

#if EXECUTE_CACHE
            if (!noCache &&
                PrivateTryGetIExecuteFromCache(newName, lookupFlags, useHidden, ref execute))
            {
                return ReturnCode.Ok;
            }
#endif

            if (Engine.HasUseIExecutes(engineFlags) &&
                 ((useHidden && (GetHiddenIExecute(
                    newName, lookupFlags, ref execute) == ReturnCode.Ok)) ||
                 (!useHidden && (GetIExecute(
                    newName, lookupFlags, ref execute) == ReturnCode.Ok))))
            {
                return ReturnCode.Ok;
            }
            else
            {
                IProcedure procedure = null;

                if (Engine.HasUseProcedures(engineFlags) &&
                    ((useHidden && (GetHiddenProcedure(
                        newName, lookupFlags, ref procedure) == ReturnCode.Ok)) ||
                    (!useHidden && (GetProcedure(
                        newName, lookupFlags, ref procedure) == ReturnCode.Ok))))
                {
                    execute = procedure;

                    return ReturnCode.Ok;
                }
                else
                {
                    ICommand command = null;

                    if (Engine.HasUseCommands(engineFlags) &&
                        ((useHidden && (GetHiddenCommand(
                            newName, lookupFlags, ref command) == ReturnCode.Ok)) ||
                        (!useHidden && (GetCommand(
                            newName, lookupFlags, ref command) == ReturnCode.Ok))))
                    {
                        execute = command;

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            String.Format(
                                "invalid {0}command name \"{1}\"",
                                useHidden ? "hidden " : String.Empty,
                                FormatOps.DisplayName(name)) :
                            "invalid command name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateMatchAnyIExecute(
            ICallFrame frame, /* NOT USED */
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref IExecute execute,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                //
                // NOTE: *WARNING* Empty command/procedure names are allowed,
                //       please do not change this to "!String.IsNullOrEmpty".
                //
                if (name != null)
                {
                    string newName = ScriptOps.MakeCommandName(name);

#if EXECUTE_CACHE
                    bool noCache = Engine.HasNoCache(engineFlags);
#endif

                    bool useHidden = Engine.HasUseHidden(engineFlags);

#if EXECUTE_CACHE
                    if (!noCache &&
                        PrivateTryGetIExecuteFromCache(newName, lookupFlags, useHidden, ref execute))
                    {
                        return ReturnCode.Ok;
                    }
#endif

                    string exactName = null;
                    ExecuteDictionary matches = new ExecuteDictionary();

                    if (exactName == null)
                    {
                        if (Engine.HasUseIExecutes(engineFlags))
                        {
                            ExecuteWrapperDictionary localExecutes = useHidden ?
                                hiddenExecutes : executes;

                            if ((localExecutes != null) && (localExecutes.Count > 0))
                            {
                                _Wrappers._Execute localExecute;

                                if (localExecutes.TryGetValue(newName, out localExecute))
                                {
                                    //
                                    // NOTE: Exact execute match.
                                    //
                                    exactName = newName;

                                    //
                                    // NOTE: Store the exact execute match in the results
                                    //       dictionary.
                                    //
                                    matches.Add(newName, localExecute);
                                }
                                else
                                {
                                    foreach (KeyValuePair<string, _Wrappers._Execute> pair in localExecutes)
                                    {
                                        if (String.Compare(
                                                pair.Key, 0, newName, 0, newName.Length,
                                                StringOps.SystemStringComparisonType) == 0)
                                        {
                                            //
                                            // NOTE: Was the key valid (this should always succeed).
                                            //
                                            if (pair.Key != null)
                                            {
                                                //
                                                // NOTE: It was a match; however, was it an exact match?
                                                //
                                                if (pair.Key.Length == newName.Length)
                                                    //
                                                    // NOTE: Preserve match, it may differ in case.
                                                    //
                                                    exactName = pair.Key;

                                                //
                                                // NOTE: Was it an exact match or did we match at least one
                                                //       character in a partial match?
                                                //
                                                if ((pair.Key.Length == newName.Length) || (newName.Length > 0))
                                                    //
                                                    // NOTE: Store the exact or partial match in the results
                                                    //       dictionary.
                                                    //
                                                    matches.Add(pair.Key, pair.Value);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    bool matchHidden = Engine.HasMatchHidden(engineFlags);

                    if (exactName == null)
                    {
                        if (Engine.HasUseProcedures(engineFlags))
                        {
                            ProcedureWrapperDictionary localProcedures = useHidden ?
                                hiddenProcedures : procedures;

                            if ((localProcedures != null) && (localProcedures.Count > 0))
                            {
                                _Wrappers.Procedure localProcedure;

                                if (localProcedures.TryGetValue(newName, out localProcedure) &&
                                    (matchHidden || !EntityOps.IsHidden(localProcedure)))
                                {
                                    //
                                    // NOTE: Exact procedure match.
                                    //
                                    exactName = newName;

                                    //
                                    // NOTE: Store the exact procedure match in the results
                                    //       dictionary.
                                    //
                                    matches.Add(newName, localProcedure);
                                }
                                else
                                {
                                    foreach (KeyValuePair<string, _Wrappers.Procedure> pair in localProcedures)
                                    {
                                        if (String.Compare(
                                                pair.Key, 0, newName, 0, newName.Length,
                                                StringOps.SystemStringComparisonType) == 0)
                                        {
                                            //
                                            // NOTE: Is the procedure visible or are we allowed to
                                            //       find hidden procedures?
                                            //
                                            if (matchHidden || !EntityOps.IsHidden(pair.Value))
                                            {
                                                //
                                                // NOTE: Was the key valid (this should always succeed).
                                                //
                                                if (pair.Key != null)
                                                {
                                                    //
                                                    // NOTE: It was a match; however, was it an exact match?
                                                    //
                                                    if (pair.Key.Length == newName.Length)
                                                        //
                                                        // NOTE: Preserve match, it may differ in case.
                                                        //
                                                        exactName = pair.Key;

                                                    //
                                                    // NOTE: Was it an exact match or did we match at least one
                                                    //       character in a partial match?
                                                    //
                                                    if ((pair.Key.Length == newName.Length) || (newName.Length > 0))
                                                        //
                                                        // NOTE: Store the exact or partial match in the results
                                                        //       dictionary.
                                                        //
                                                        matches.Add(pair.Key, pair.Value);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (exactName == null)
                    {
                        if (Engine.HasUseCommands(engineFlags))
                        {
                            CommandWrapperDictionary localCommands = useHidden ?
                                hiddenCommands : commands;

                            if ((localCommands != null) && (localCommands.Count > 0))
                            {
                                _Wrappers.Command localCommand;

                                if (localCommands.TryGetValue(newName, out localCommand) &&
                                    (matchHidden || !EntityOps.IsHidden(localCommand)))
                                {
                                    //
                                    // NOTE: Exact command match.
                                    //
                                    exactName = newName;

                                    //
                                    // NOTE: Store the exact command match in the results
                                    //       dictionary.
                                    //
                                    matches.Add(newName, localCommand);
                                }
                                else
                                {
                                    foreach (KeyValuePair<string, _Wrappers.Command> pair in localCommands)
                                    {
                                        if (String.Compare(
                                                pair.Key, 0, newName, 0, newName.Length,
                                                StringOps.SystemStringComparisonType) == 0)
                                        {
                                            //
                                            // NOTE: Is the command visible or are we allowed to
                                            //       find hidden command?
                                            //
                                            if (matchHidden || !EntityOps.IsHidden(pair.Value))
                                            {
                                                //
                                                // NOTE: Was the key valid (this should always succeed).
                                                //
                                                if (pair.Key != null)
                                                {
                                                    //
                                                    // NOTE: It was a match; however, was it an exact match?
                                                    //
                                                    if (pair.Key.Length == newName.Length)
                                                        //
                                                        // NOTE: Preserve match, it may differ in case.
                                                        //
                                                        exactName = pair.Key;

                                                    //
                                                    // NOTE: Was it an exact match or did we match at least one
                                                    //       character in a partial match?
                                                    //
                                                    if ((pair.Key.Length == newName.Length) || (newName.Length > 0))
                                                        //
                                                        // NOTE: Store the exact or partial match in the results
                                                        //       dictionary.
                                                        //
                                                        matches.Add(pair.Key, pair.Value);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //
                    // NOTE: If there was an exact match, just use it.
                    //
                    // BUGFIX: We need to make 100% sure that we get the wrapper here
                    //         because that is what we want to store in the execute
                    //         cache.  Otherwise, the cache cannot satisfy requests
                    //         for the wrapper later (i.e. based on the lookup flags
                    //         for each call).
                    //
                    LookupFlags localLookupFlags = lookupFlags | LookupFlags.Wrapper;

                    if (exactName != null)
                    {
                        //
                        // NOTE: Exact match, return the matching command or
                        //       procedure.
                        //
                        IExecute match = matches[exactName];

                        if (match is _Wrappers._Execute)
                        {
                            long localToken = 0;
                            IExecute localExecute = null;

                            if ((useHidden && PrivateGetHiddenIExecute(
                                    exactName, localLookupFlags, ref localToken,
                                    ref localExecute, ref error) == ReturnCode.Ok) ||
                                (!useHidden && PrivateGetIExecute(
                                    exactName, localLookupFlags, ref localToken,
                                    ref localExecute, ref error) == ReturnCode.Ok))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(exactName, localExecute, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(exactName, localExecute, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, localExecute, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenIExecute : NotifyType.IExecute),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, localExecute, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else if (match is _Wrappers.Procedure)
                        {
                            long localToken = 0;
                            IProcedure procedure = null;
                            IExecute localExecute = null;

                            if ((useHidden && PrivateGetHiddenProcedure(
                                    exactName, localLookupFlags, ref localToken,
                                    ref procedure, ref error) == ReturnCode.Ok) ||
                                (!useHidden && PrivateGetProcedure(
                                    exactName, localLookupFlags, ref localToken,
                                    ref procedure, ref error) == ReturnCode.Ok))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(exactName, procedure, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(exactName, procedure, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, procedure, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenProcedure : NotifyType.Procedure),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, procedure, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else if (match is _Wrappers.Command)
                        {
                            long localToken = 0;
                            ICommand command = null;
                            IExecute localExecute = null;

                            if ((useHidden && PrivateGetHiddenCommand(
                                    exactName, localLookupFlags, ref localToken,
                                    ref command, ref error) == ReturnCode.Ok) ||
                                (!useHidden && PrivateGetCommand(
                                    exactName, localLookupFlags, ref localToken,
                                    ref command, ref error) == ReturnCode.Ok))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(exactName, command, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(exactName, command, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, command, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenCommand : NotifyType.Command),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, exactName, command, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "object \"{0}\" is not an execute, procedure, or command wrapper",
                                    exactName) :
                                "object is not an execute, procedure, or command wrapper";
                        }
                    }
                    else if (matches.Count == 1)
                    {
                        string key = new StringList(matches.Keys)[0];

                        //
                        // NOTE: Normal case, exactly one command matched.
                        //
                        if (matches[key] is _Wrappers._Execute)
                        {
                            long localToken = 0;
                            IExecute localExecute = null;

                            if ((useHidden && (PrivateGetHiddenIExecute(
                                    key, localLookupFlags, ref localToken,
                                    ref localExecute, ref error) == ReturnCode.Ok)) ||
                                (!useHidden && (PrivateGetIExecute(
                                    key, localLookupFlags, ref localToken,
                                    ref localExecute, ref error) == ReturnCode.Ok)))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(key, localExecute, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(key, localExecute, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, localExecute, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenIExecute : NotifyType.IExecute),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, key, localExecute, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else if (matches[key] is _Wrappers.Procedure)
                        {
                            long localToken = 0;
                            IProcedure procedure = null;
                            IExecute localExecute = null;

                            if ((useHidden && (PrivateGetHiddenProcedure(
                                    key, localLookupFlags, ref localToken,
                                    ref procedure, ref error) == ReturnCode.Ok)) ||
                                (!useHidden && (PrivateGetProcedure(
                                    key, localLookupFlags, ref localToken,
                                    ref procedure, ref error) == ReturnCode.Ok)))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(key, procedure, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(key, procedure, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, procedure, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenProcedure : NotifyType.Procedure),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, key, procedure, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else if (matches[key] is _Wrappers.Command)
                        {
                            long localToken = 0;
                            ICommand command = null;
                            IExecute localExecute = null;

                            if ((useHidden && (PrivateGetHiddenCommand(
                                    key, localLookupFlags, ref localToken,
                                    ref command, ref error) == ReturnCode.Ok)) ||
                                (!useHidden && (PrivateGetCommand(
                                    key, localLookupFlags, ref localToken,
                                    ref command, ref error) == ReturnCode.Ok)))
                            {
#if EXECUTE_CACHE
                                if (!noCache)
                                {
                                    if (useHidden)
                                    {
                                        if (hiddenExecuteCache != null)
                                            hiddenExecuteCache.AddOrUpdate(key, command, false);
                                    }
                                    else
                                    {
                                        if (executeCache != null)
                                            executeCache.AddOrUpdate(key, command, false);
                                    }
                                }
#endif

                                if (MaybeUnwrapIExecute(
                                        lookupFlags, command, ref localExecute, ref error))
                                {
#if NOTIFY
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Resolver | (useHidden ? NotifyType.HiddenCommand : NotifyType.Command),
                                        NotifyFlags.Matched | (useHidden ? NotifyFlags.Hidden : NotifyFlags.None),
                                        new ObjectList(engineFlags, name, key, command, localToken), this, null, null, null,
                                        ref error);
#endif

                                    token = localToken;
                                    execute = localExecute;

                                    return ReturnCode.Ok;
                                }
                            }
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "object \"{0}\" is not an execute, procedure, or command wrapper",
                                    key) :
                                "object is not an execute, procedure, or command wrapper";
                        }
                    }
                    else if (matches.Count > 1)
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            ScriptOps.BadValue(
                                "ambiguous", useHidden ?
                                "hidden command" : "command", name, matches.Keys,
                                null, null) :
                            (Result)"ambiguous command";

                        ambiguous = true;
                    }
                    else
                    {
                        error = FlagOps.HasFlags(
                            lookupFlags, LookupFlags.Verbose, true) ?
                            String.Format(
                                "invalid {0}command name \"{1}\"",
                                useHidden ? "hidden " : String.Empty, name) :
                            "invalid command name";
                    }
                }
                else
                {
                    error = "invalid command name";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetAnyIExecute(
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref long token,
            ref IExecute execute,
            ref Result error
            ) /* USED BY CORE RESOLVER */
        {
            /* CheckDisposed(); */

            //
            // NOTE: When searching for [non-hidden] commands, fallback to
            //       searching the hidden commands also to give the policies,
            //       if any, a chance to allow or deny their execution;
            //       however, only do this if the appropriate flag (i.e. the
            //       MatchHidden flag) is set.
            //
            Result localError = null;

            if (PrivateGetAnyIExecute(
                    frame, engineFlags, name, lookupFlags, ref token,
                    ref execute, ref localError) == ReturnCode.Ok)
            {
                return ReturnCode.Ok;
            }
            else if (RuntimeOps.ShouldResolveHidden(engineFlags, false))
            {
                Result localError2 = null; /* VALUE NOT USED */

                if (PrivateGetAnyIExecute(
                        frame, engineFlags | EngineFlags.UseHidden,
                        name, lookupFlags, ref token, ref execute,
                        ref localError2) == ReturnCode.Ok)
                {
                    return ReturnCode.Ok;
                }
            }

            error = localError;
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode MatchAnyIExecute(
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref long token,
            ref IExecute execute,
            ref Result error
            ) /* USED BY CORE RESOLVER */
        {
            /* CheckDisposed(); */

            //
            // BUGFIX: Always try for an exact match first.  This produces the
            //         correct behavior when a single name prefix is an exact
            //         match for a hidden command and is also a prefix match
            //         for a different, visible command.  Currently, this is
            //         hard-coded behavior that cannot be disabled at runtime.
            //
            Result localError = null;

            if (GetAnyIExecute(frame,
                    GetMatchAnyEngineFlags(engineFlags, true),
                    name, lookupFlags, ref token, ref execute,
                    ref localError) == ReturnCode.Ok)
            {
                return ReturnCode.Ok;
            }

            //
            // NOTE: When searching for [non-hidden] commands, fallback to
            //       searching the hidden commands also to give the policies,
            //       if any, a chance to allow or deny their execution;
            //       however, only do this if the appropriate flag (i.e. the
            //       MatchHidden flag) is set.
            //
            if (PrivateMatchAnyIExecute(
                        frame, GetMatchAnyEngineFlags(engineFlags, false),
                        name, lookupFlags, ref ambiguous, ref token,
                        ref execute, ref localError) == ReturnCode.Ok)
            {
                return ReturnCode.Ok;
            }
            else if (RuntimeOps.ShouldResolveHidden(engineFlags, false))
            {
                Result localError2 = null; /* VALUE NOT USED */

                if (PrivateMatchAnyIExecute(
                        frame, GetMatchAnyEngineFlags(engineFlags, false) |
                        EngineFlags.UseHidden, name, lookupFlags,
                        ref ambiguous, ref token, ref execute,
                        ref localError2) == ReturnCode.Ok)
                {
                    return ReturnCode.Ok;
                }
            }

            error = localError;
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ListAnyIExecute(
            string pattern,
            bool noCase,
            bool hidden,
            bool strict,
            ref ObjectDictionary dictionary,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                ResultList errors = null;
                ObjectDictionary localDictionary = null;
                Result localError = null;

                ///////////////////////////////////////////////////////////////////////////////////////

                if (HasCommands(ref localError))
                {
                    if (commands.ToDictionary(
                            pattern, noCase, ref localDictionary,
                            ref localError) != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }
                }
                else if (strict)
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(localError);
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (HasProcedures(ref localError))
                {
                    if (procedures.ToDictionary(
                            pattern, noCase, ref localDictionary,
                            ref localError) != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }
                }
                else if (strict)
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(localError);
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (HasIExecutes(ref localError))
                {
                    if (executes.ToDictionary(
                            pattern, noCase, ref localDictionary,
                            ref localError) != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }
                }
                else if (strict)
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(localError);
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (hidden)
                {
                    if (HasHiddenCommands(ref localError))
                    {
                        if (hiddenCommands.ToDictionary(
                                pattern, noCase, ref localDictionary,
                                ref localError) != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(localError);
                        }
                    }
                    else if (strict)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }

                    ///////////////////////////////////////////////////////////////////////////////////

                    if (HasHiddenProcedures(ref localError))
                    {
                        if (hiddenProcedures.ToDictionary(
                                pattern, noCase, ref localDictionary,
                                ref localError) != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(localError);
                        }
                    }
                    else if (strict)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }

                    ///////////////////////////////////////////////////////////////////////////////////

                    if (HasHiddenIExecutes(ref localError))
                    {
                        if (hiddenExecutes.ToDictionary(
                                pattern, noCase, ref localDictionary,
                                ref localError) != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(localError);
                        }
                    }
                    else if (strict)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(localError);
                    }
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (errors != null)
                {
                    error = errors;
                    return ReturnCode.Error;
                }

                dictionary = localDictionary;
                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetIExecuteViaResolvers(
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref IExecute execute
            )
        {
            return GetIExecuteViaResolvers(
                null, engineFlags, name, arguments, lookupFlags, ref execute);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetIExecuteViaResolvers(
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref IExecute execute
            )
        {
            Result error = null;

            return GetIExecuteViaResolvers(
                frame, engineFlags, name, arguments, lookupFlags, ref execute,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetIExecuteViaResolvers(
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref IExecute execute,
            ref Result error
            )
        {
            return GetIExecuteViaResolvers(
                null, engineFlags, name, arguments, lookupFlags, ref execute,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetIExecuteViaResolvers(
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref IExecute execute,
            ref Result error
            )
        {
            bool ambiguous = false;

            return GetIExecuteViaResolvers(
                frame, engineFlags, name, arguments, lookupFlags, ref ambiguous,
                ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetIExecuteViaResolvers(
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref IExecute execute,
            ref Result error
            )
        {
            return GetIExecuteViaResolvers(
                null, engineFlags, name, arguments, lookupFlags, ref ambiguous,
                ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetIExecuteViaResolvers(
            ICallFrame frame,
            EngineFlags engineFlags,
            string name,
            ArgumentList arguments,
            LookupFlags lookupFlags,
            ref bool ambiguous,
            ref IExecute execute,
            ref Result error
            )
        {
            long token = 0;

            return GetIExecuteViaResolvers(
                frame, engineFlags, name, arguments, lookupFlags, ref ambiguous,
                ref token, ref execute, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableViaResolversWithSplit(
            ICallFrame frame,
            string name,
            ref IVariable variable
            )
        {
            VariableFlags flags = VariableFlags.None;
            Result error = null;

            return GetVariableViaResolversWithSplit(
                frame, name, null, ref flags, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableViaResolversWithSplit(
            string name,
            ref VariableFlags variableFlags,
            ref IVariable variable
            )
        {
            Result error = null;

            return GetVariableViaResolversWithSplit(
                name, ref variableFlags, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableViaResolversWithSplit(
            string name,
            ref VariableFlags variableFlags,
            ref IVariable variable,
            ref Result error
            )
        {
            return GetVariableViaResolversWithSplit(
                null, name, null, ref variableFlags, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetVariableViaResolversWithSplit(
            ICallFrame frame,
            string name,
            ref VariableFlags variableFlags,
            ref IVariable variable,
            ref Result error
            )
        {
            return GetVariableViaResolversWithSplit(
                frame, name, null, ref variableFlags, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetVariableViaResolversWithSplit(
            ICallFrame frame,
            string name,
            string index,
            ref VariableFlags variableFlags,
            ref IVariable variable,
            ref Result error
            )
        {
            string varName = null;
            string varIndex = null;

            return GetVariableViaResolversWithSplit(
                frame, name, index, ref varName, ref varIndex, ref variableFlags,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetVariableViaResolversWithSplit(
            ICallFrame frame,
            string name,
            string index,
            ref string varName,
            ref string varIndex,
            ref VariableFlags variableFlags,
            ref IVariable variable,
            ref Result error
            )
        {
            //
            // NOTE: Reset the error related flags because we have not
            //       actually searched for the variable yet.
            //
            variableFlags &= ~VariableFlags.ErrorMask;

            //
            // BUGFIX: Prevent any custom resolvers from returning a null
            //         variable along with a successful return code.
            //
            variableFlags &= ~VariableFlags.ResolveNull;

            //
            // BUGFIX: Block all attempts to use an array element reference
            //         in the variable name if an explicit array element
            //         index has been explicitly specified by the caller.
            //
            if (index != null)
                variableFlags |= VariableFlags.NoElement;

            //
            // NOTE: Perform a split of the name (which may refer to an array
            //       element) into the base variable name and the array index,
            //       if any.
            //
            if (ScriptOps.SplitVariableName(
                    this, variableFlags, name, ref varName,
                    ref varIndex, ref error) == ReturnCode.Ok)
            {
                //
                // NOTE: The caller may need to know if the variable name
                //       refers to an array element.
                //
                if (varIndex != null)
                    variableFlags |= VariableFlags.WasElement;

                return GetVariableViaResolvers(
                    frame, varName, varIndex, ref variableFlags,
                    ref variable, ref error);
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Resolver Management (WARNING: EXPERIMENTAL)
        public bool HasResolvers(ref Result error)
        {
            CheckDisposed();

            bool result = (resolvers != null);

            if (!result)
                error = "resolvers not available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ResetResolvers(
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(false, ref error))
                    return ReturnCode.Error;

                if (!HasResolvers(ref error))
                    return ReturnCode.Error;

                InternalResetResolvers(ref error);
                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetResolver(
            Priority priority,
            ref IResolve resolve,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!HasResolvers(ref error))
                    return ReturnCode.Error;

                if (priority == Priority.Lowest)
                    priority = (Priority)resolvers.Count - 1;
                else if (priority == Priority.None)
                    priority = Priority.Highest;

                if (((int)priority < 0) ||
                    ((int)priority > resolvers.Count))
                {
                    error = "invalid priority";
                    return ReturnCode.Error;
                }

                resolve = resolvers[(int)priority];
                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddResolver(
            IResolve resolve,
            IClientData clientData,
            Priority priority,
            ref Result result
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if (!IsModifiable(true, ref result))
                    return ReturnCode.Error;

                if (resolve == null)
                {
                    result = "invalid resolve";
                    return ReturnCode.Error;
                }

                if (!HasResolvers(ref result))
                    return ReturnCode.Error;

                if (priority == Priority.Lowest)
                {
                    resolvers.Add(resolve);
                    EntityOps.SetToken(resolve, resolvers.Count - 1);
                }
                else
                {
                    if (priority == Priority.None)
                        priority = Priority.Highest;

                    if (((int)priority < 0) ||
                        ((int)priority > resolvers.Count))
                    {
                        result = "invalid priority";
                        return ReturnCode.Error;
                    }

                    resolvers.Insert((int)priority, resolve);
                    EntityOps.SetToken(resolve, (long)priority);
                }

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Resolve, NotifyFlags.Added,
                    new ObjectPair(resolve, priority), this,
                    clientData, null, null, ref result);
#endif

                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private bool HasResolvers()
        {
            Result error = null;

            return HasResolvers(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void InternalResetResolvers(
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (HasResolvers())
                {
                    IResolve resolve = RuntimeOps.NewResolver(
                        this, GlobalFrame, globalNamespace, createFlags);

                    resolvers.Clear();
                    resolvers.Add(resolve);

                    EntityOps.SetToken(resolve, (long)Priority.Highest);

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Resolve, NotifyFlags.Reset,
                        null, this, null, null, null, ref error);
#endif
                }
            }
        }
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IResourceManager Members
        public string GetString(
            string name
            )
        {
            CheckDisposed();

            return GetString(null, name);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string GetString(
            IPlugin plugin,
            string name
            )
        {
            CheckDisposed();

            //
            // NOTE: Use the culture configured for this interpreter.
            //
            return GetString(plugin, name, cultureInfo);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string GetString(
            IPlugin plugin,
            string name,
            ref Result error
            )
        {
            CheckDisposed();

            //
            // NOTE: Use the culture configured for this interpreter.
            //
            return GetString(plugin, name, cultureInfo, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string GetString(
            IPlugin plugin,
            string name,
            CultureInfo cultureInfo
            )
        {
            CheckDisposed();

            Result error = null;

            return GetString(plugin, name, cultureInfo, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string GetString(
            IPlugin plugin,
            string name,
            CultureInfo cultureInfo,
            ref Result error
            )
        {
            CheckDisposed();

            return RuntimeOps.GetString(
                plugin, resourceManager, name, cultureInfo, ref error);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IScriptManager Members
        public string LibraryPath
        {
            get { CheckDisposed(); lock (syncRoot) { return libraryPath; } }
            set { CheckDisposed(); lock (syncRoot) { libraryPath = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public StringList AutoPathList
        {
            get { CheckDisposed(); lock (syncRoot) { return autoPathList; } }
            set { CheckDisposed(); lock (syncRoot) { autoPathList = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode PreInitialize(
            bool force,      /* in */
            ref Result error /* out */
            )
        {
            CheckDisposed();

            return PrivatePreInitialize(force, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode Initialize(
            bool force,      /* in */
            ref Result error /* out */
            )
        {
            CheckDisposed();

            return PrivateInitialize(force, false, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL
        public ReturnCode InitializeShell(
            bool force,      /* in */
            ref Result error /* out */
            )
        {
            CheckDisposed();

            return PrivateInitializeShell(force, false, ref error);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetScript(
            string name,
            ref ScriptFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            if (FlagOps.HasFlags(flags, ScriptFlags.Library, true))
                return ScriptOps.GetLibrary(this, host, name, ref flags, ref result);
            else
                return HostOps.GetScript(this, host, name, ref flags, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private ReturnCode PrivatePreInitialize(
            bool force,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Ok;
            bool wasInitialized;
            bool didInitialize = false;

            lock (syncRoot)
            {
                wasInitialized = preInitialized;
            }

            if (force || !wasInitialized)
            {
                #region Phase 0: Pre-Initialization Script (Optional)
                string text;

                lock (syncRoot)
                {
                    text = preInitializeText;
                }

                if (text != null)
                {
                    Result localResult = null;

                    code = EvaluateScript(text, ref localResult); /* EXEMPT */

                    if (code == ReturnCode.Ok)
                        didInitialize = true;
                    else
                        error = localResult;
                }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Phase 1: Set Library Pre-Initialized Flag
                //
                // NOTE: Has everything succeeded?
                //
                if (code == ReturnCode.Ok)
                {
                    lock (syncRoot)
                    {
                        if (!preInitialized)
                            preInitialized = true;
                    }

#if NOTIFY && NOTIFY_GLOBAL
                    if (this.GlobalNotify)
                        /* IGNORED */
                        CheckNotifications(
                            null, false, NotifyType.Interpreter |
                            NotifyType.Library, NotifyFlags.PreInitialized,
                            new ObjectTriplet(force, text, didInitialize),
                            this, null, null, null, ref error);
#endif
                }
                #endregion
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: PrivatePreInitialize: interpreter = {1}, force = {2}, " +
                "wasInitialized = {3}, didInitialize = {4}, code = {5}, " +
                "error = {6}{7}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(this),
                force, wasInitialized, didInitialize, code,
                FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                typeof(Interpreter).Name);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string GetScript(
            string name,
            ref ScriptFlags flags
            )
        {
            Result result = null;

            if (GetScript(name, ref flags, ref result) != ReturnCode.Ok)
                result = null; /* NOTE: Discard error message. */

            return result;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ISecurityManager Members
        public StringList TrustedPaths
        {
            get { CheckDisposed(); return trustedPaths; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ObjectDictionary TrustedTypes
        {
            get { CheckDisposed(); return trustedTypes; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public PolicyDecision CommandDecision
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return commandDecision;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    commandDecision = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public PolicyDecision ScriptDecision
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return scriptDecision;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    scriptDecision = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public PolicyDecision FileDecision
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return fileDecision;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    fileDecision = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public PolicyDecision StreamDecision
        {
            get
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    return streamDecision;
                }
            }
            set
            {
                CheckDisposed();

                lock (syncRoot)
                {
                    streamDecision = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsSafe()
        {
            CheckDisposed();

            return FlagOps.HasFlags(createFlags, CreateFlags.Safe, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MakeSafe(
            MakeFlags makeFlags,
            bool safe,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if ((commands != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeCommands, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Command> pair in commands)
                    {
                        if (pair.Value != null)
                        {
                            CommandFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, CommandFlags.Safe, true) ||
                                FlagOps.HasFlags(flags, CommandFlags.Unsafe, true))
                            {
                                if (safe)
                                    flags |= CommandFlags.Hidden;
                                else
                                    flags &= ~CommandFlags.Hidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                if ((procedures != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeProcedures, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Procedure> pair in procedures)
                    {
                        if (pair.Value != null)
                        {
                            ProcedureFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, ProcedureFlags.Safe, true) ||
                                FlagOps.HasFlags(flags, ProcedureFlags.Unsafe, true))
                            {
                                if (safe)
                                    flags |= ProcedureFlags.Hidden;
                                else
                                    flags &= ~ProcedureFlags.Hidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                if ((functions != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeFunctions, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Function> pair in functions)
                    {
                        if (pair.Value != null)
                        {
                            FunctionFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, FunctionFlags.Safe, true) ||
                                FlagOps.HasFlags(flags, FunctionFlags.Unsafe, true))
                            {
                                if (safe)
                                    flags |= FunctionFlags.DisabledAndHidden;
                                else
                                    flags &= ~FunctionFlags.DisabledAndHidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                //
                // NOTE: Move all the newly hidden and exposed commands to their proper
                //       internal collections.
                //
                if (MoveExposedAndHiddenCommands(ref error) == ReturnCode.Ok)
                {
                    //
                    // BUGBUG: Removal of the "unsafe" variables and array elements
                    //         from the global call frame is currently a one-way
                    //         street, just like in Tcl.  We make no attempt to
                    //         restore the deleted variables if/when the interpreter
                    //         is made "unsafe" again.
                    //
                    if (safe &&
                        FlagOps.HasFlags(makeFlags, MakeFlags.IncludeVariables, true))
                    {
                        ICallFrame variableFrame = GlobalFrame;

                        if (variableFrame != null)
                        {
                            VariableDictionary variables = variableFrame.Variables;

                            if (variables != null)
                            {
                                bool reset = FlagOps.HasFlags(
                                    makeFlags, MakeFlags.ResetValue, true);

                                bool zero = HasZeroString() && HasZeroString(makeFlags);

                                foreach (KeyValuePair<string, IVariable> pair in variables)
                                {
                                    if (pair.Value != null)
                                    {
                                        VariableFlags flags = pair.Value.Flags;

                                        if ((!FlagOps.HasFlags(flags, VariableFlags.Safe, true) ||
                                            FlagOps.HasFlags(flags, VariableFlags.Unsafe, true)) &&
                                            !ScriptOps.IsSafeVariableName(pair.Key))
                                        {
                                            //
                                            // NOTE: Mark this "unsafe" variable for removal.
                                            //
                                            if (reset && (pair.Value is Variable))
                                                ((Variable)pair.Value).ResetValue(this, zero);

                                            EntityOps.SetUndefined(pair.Value, true);
                                        }
                                        else if ((String.Compare(pair.Key, TclVars.Platform.Name,
                                                StringOps.SystemStringComparisonType) == 0))
                                        {
                                            //
                                            // NOTE: Prepare to remove the "unsafe" array
                                            //       elements from the "tcl_platform" array.
                                            //
                                            ElementDictionary arrayValue = pair.Value.ArrayValue;

                                            if (arrayValue != null)
                                            {
                                                //
                                                // NOTE: This must be done in two phases because
                                                //       we cannot modify the dictionary while we
                                                //       enumerate it.
                                                //
                                                StringList keys = new StringList();

                                                foreach (KeyValuePair<string, object> pair2 in arrayValue)
                                                {
                                                    if (!ScriptOps.IsSafeTclPlatformElementName(pair2.Key))
                                                    {
                                                        keys.Add(pair2.Key);
                                                    }
                                                }

                                                //
                                                // NOTE: Purge the "unsafe" array elements.
                                                //
                                                foreach (string key in keys)
                                                {
                                                    if (reset)
                                                    {
                                                        /* IGNORED */
                                                        arrayValue.ResetValue(
                                                            this, key, zero);
                                                    }
                                                    else
                                                    {
                                                        /* IGNORED */
                                                        arrayValue.Remove(key);
                                                    }
                                                }
                                            }
                                        }
                                        else if ((String.Compare(pair.Key, Vars.Platform.Name,
                                                StringOps.SystemStringComparisonType) == 0))
                                        {
                                            //
                                            // NOTE: Prepare to remove the "unsafe" array
                                            //       elements from the "eagle_platform" array.
                                            //
                                            ElementDictionary arrayValue = pair.Value.ArrayValue;

                                            if (arrayValue != null)
                                            {
                                                //
                                                // NOTE: This must be done in two phases because
                                                //       we cannot modify the dictionary while we
                                                //       enumerate it.
                                                //
                                                StringList keys = new StringList();

                                                foreach (KeyValuePair<string, object> pair2 in arrayValue)
                                                {
                                                    if (!ScriptOps.IsSafeEaglePlatformElementName(pair2.Key))
                                                    {
                                                        keys.Add(pair2.Key);
                                                    }
                                                }

                                                //
                                                // NOTE: Purge the "unsafe" array elements.
                                                //
                                                foreach (string key in keys)
                                                {
                                                    if (reset)
                                                    {
                                                        /* IGNORED */
                                                        arrayValue.ResetValue(
                                                            this, key, zero);
                                                    }
                                                    else
                                                    {
                                                        /* IGNORED */
                                                        arrayValue.Remove(key);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }

                                //
                                // NOTE: Purge all the undefined (i.e. deleted)
                                //       variables from the [global] call frame.
                                //
                                /* IGNORED */
                                CallFrameOps.Cleanup(variableFrame, variableFrame, false);
                            }
                        }
                    }

                    if (safe)
                        createFlags |= CreateFlags.SafeAndHideUnsafe;
                    else
                        createFlags &= ~CreateFlags.SafeAndHideUnsafe;
                }
                else
                {
                    return ReturnCode.Error;
                }
            }

            //
            // NOTE: *WARNING* Please do not move this inside of the lock
            //       statement.
            //
            if (safe &&
                FlagOps.HasFlags(makeFlags, MakeFlags.IncludeLibrary, true))
            {
                //
                // NOTE: Finally, attempt to evaluate the safe interpreter
                //       initialization script (i.e. "safe.eagle").
                //
                ScriptFlags scriptFlags = ScriptFlags.CoreLibraryRequiredFile;

                ReturnCode code = EvaluateScript(this, FileName.Safe, true,
                    ref scriptFlags, ref error);

                if (code != ReturnCode.Ok)
                    return code;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MarkTrusted(ref Result error)
        {
            CheckDisposed();

            lock (syncRoot)
            {
                createFlags &= ~CreateFlags.Safe;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode LockAndMarkTrusted(ref Result error)
        {
            CheckDisposed();

            if (syncRoot == null)
            {
                error = "invalid interpreter synchronization object";
                return ReturnCode.Error;
            }

            if (!Monitor.TryEnter(syncRoot)) /* EXEMPT */
            {
                error = "could not obtain interpreter lock";
                return ReturnCode.Error;
            }

            if (!FlagOps.HasFlags(createFlags, CreateFlags.Safe, true))
            {
                error = "interpreter is already marked as trusted";
                Monitor.Exit(syncRoot); /* EXEMPT */
                return ReturnCode.Error;
            }

            /* LOCK HELD */
            createFlags &= ~CreateFlags.Safe;

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MarkSafeAndUnlock(ref Result error)
        {
            CheckDisposed();

            if (syncRoot == null)
            {
                error = "invalid interpreter synchronization object";
                return ReturnCode.Error;
            }

            if (!Monitor.TryEnter(syncRoot)) /* EXEMPT */
            {
                error = "could not obtain interpreter lock";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true))
            {
                error = "interpreter is already marked as safe";
                Monitor.Exit(syncRoot); /* EXEMPT */
                return ReturnCode.Error;
            }

            /* LOCK HELD */
            createFlags |= CreateFlags.Safe;
            Monitor.Exit(syncRoot); /* EXEMPT */
            Monitor.Exit(syncRoot); /* EXEMPT */
            /* LOCK NOT HELD */

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsStandard()
        {
            CheckDisposed();

            return FlagOps.HasFlags(createFlags, CreateFlags.Standard, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode MakeStandard(
            MakeFlags makeFlags,
            bool standard,
            ref Result error
            )
        {
            CheckDisposed();

            lock (syncRoot)
            {
                if ((commands != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeCommands, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Command> pair in commands)
                    {
                        if (pair.Value != null)
                        {
                            CommandFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, CommandFlags.Standard, true) ||
                                FlagOps.HasFlags(flags, CommandFlags.NonStandard, true))
                            {
                                if (standard)
                                    flags |= CommandFlags.Hidden;
                                else
                                    flags &= ~CommandFlags.Hidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                if ((functions != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeFunctions, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Function> pair in functions)
                    {
                        if (pair.Value != null)
                        {
                            FunctionFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, FunctionFlags.Standard, true) ||
                                FlagOps.HasFlags(flags, FunctionFlags.NonStandard, true))
                            {
                                if (standard)
                                    flags |= FunctionFlags.DisabledAndHidden;
                                else
                                    flags &= ~FunctionFlags.DisabledAndHidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                if ((operators != null) &&
                    FlagOps.HasFlags(makeFlags, MakeFlags.IncludeOperators, true))
                {
                    foreach (KeyValuePair<string, _Wrappers.Operator> pair in operators)
                    {
                        if (pair.Value != null)
                        {
                            OperatorFlags flags = pair.Value.Flags;

                            if (!FlagOps.HasFlags(flags, OperatorFlags.Standard, true) ||
                                FlagOps.HasFlags(flags, OperatorFlags.NonStandard, true))
                            {
                                if (standard)
                                    flags |= OperatorFlags.DisabledAndHidden;
                                else
                                    flags &= ~OperatorFlags.DisabledAndHidden;

                                pair.Value.Flags = flags;
                            }
                        }
                    }
                }

                if (standard)
                    createFlags |= CreateFlags.StandardAndHideNonStandard;
                else
                    createFlags &= ~CreateFlags.StandardAndHideNonStandard;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool InternalPreSetup
        {
            get { return preSetup; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool PrivateSetup /* NOT USED */
        {
            get { return setup; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool PrivateInitialized
        {
            get { return initialized; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string InternalInitializedPath
        {
            get { return initializedPath; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool PrivateInitializedShell /* NOT USED */
        {
            get { return initializedShell; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private string PrivateInitializedShellPath /* NOT USED */
        {
            get { return initializedShellPath; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool HasZeroString(
            MakeFlags makeFlags
            )
        {
#if !MONO && NATIVE && WINDOWS
            return FlagOps.HasFlags(
                makeFlags, MakeFlags.ZeroString, true);
#else
            return false;
#endif
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IShellManager Members
#if SHELL
        public ArgumentCallback ArgumentCallback
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ArgumentCallback;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return argumentCallback;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ArgumentCallback = value;
#else
                lock (syncRoot)
                {
                    argumentCallback = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public EvaluateScriptCallback EvaluateScriptCallback
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.EvaluateScriptCallback;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return evaluateScriptCallback;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.EvaluateScriptCallback = value;
#else
                lock (syncRoot)
                {
                    evaluateScriptCallback = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public EvaluateFileCallback EvaluateFileCallback
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.EvaluateFileCallback;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return evaluateFileCallback;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.EvaluateFileCallback = value;
#else
                lock (syncRoot)
                {
                    evaluateFileCallback = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public EvaluateEncodedFileCallback EvaluateEncodedFileCallback
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.EvaluateEncodedFileCallback;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return evaluateEncodedFileCallback;
                }
#endif
            }
            set
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.EvaluateEncodedFileCallback = value;
#else
                lock (syncRoot)
                {
                    evaluateEncodedFileCallback = value;
                }
#endif
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ISynchronize Members
        public object SyncRoot
        {
            //
            // TODO: Rethink this strategy.  Should calls for the interpreter
            //       lock from inside the interpreter methods be able to throw
            //       an exception?  If so, why?  If not, why not?
            //
            get { CheckDisposed(); return syncRoot; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal void TryLock( /* NOTE: For DebugOps/HostOps USE ONLY. */
            ref bool locked
            )
        {
            if (syncRoot == null)
                return;

            locked = Monitor.TryEnter(syncRoot);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void ExitLock( /* NOTE: For DebugOps/HostOps USE ONLY. */
            ref bool locked
            )
        {
            if (locked)
            {
                if (syncRoot == null)
                    return;

                Monitor.Exit(syncRoot);
                locked = false;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal object InternalSyncRoot
        {
            get { return syncRoot; }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ITclEntityManager Members
#if NATIVE && TCL
        #region Tcl Interpreter Support
        public bool HasTclInterpreters(ref Result error)
        {
            CheckDisposed();

            bool result = (tclInterps != null);

            if (!result)
                error = "no Tcl interpreters available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesTclInterpreterExist(string name)
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;
            Result error = null;

            return GetTclInterpreter(name, LookupFlags.Exists, ref interp, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetTclInterpreter(
            string name,
            LookupFlags lookupFlags,
            ref IntPtr interp,
            ref Result error
            )
        {
            CheckDisposed();

            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty Tcl interpreter names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (tclInterps.TryGetValue(name, out interp) &&
                            ((interp != IntPtr.Zero) ||
                            !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true)))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "invalid Tcl interpreter \"{0}\"",
                                    name) :
                                "invalid Tcl interpreter";
                        }
                    }
                    else
                    {
                        error = "invalid Tcl interpreter name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CreateTclInterpreter(
            bool initialize,
            bool memory,
            bool safe,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(true, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref result))
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
                        IntPtr interp = IntPtr.Zero;

                        if (TclWrapper.CreateInterpreter(tclApi, initialize, memory, safe,
                                ref interp, ref result) == ReturnCode.Ok)
                        {
                            string name = FormatOps.Id(
                                safe ? tclSafeInterpPrefix : tclInterpPrefix, null, NextId());

                            tclInterps.Add(name, interp);
                            result = name;

#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Tcl | NotifyType.Interpreter, NotifyFlags.Added,
                                //
                                // BUGBUG: In order to use this class for notification
                                //         parameters, it really should probably be
                                //         made public.
                                //
                                new ObjectList(initialize, safe, name, interp), this,
                                null, null, null, ref result);
#endif

                            return ReturnCode.Ok;
                        }
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DeleteTclInterpreter(
            string name,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(false, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref result))
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
                        IntPtr interp = IntPtr.Zero;

                        if (GetTclInterpreter(
                                name, LookupFlags.Default, ref interp, ref result) == ReturnCode.Ok)
                        {
                            if (
#if NATIVE_PACKAGE
                                !NativePackage.ShouldDeleteTclInterpreter(name, interp) ||
#endif
                                TclWrapper.DeleteInterpreter(
                                    tclApi, false, ref interp, ref result) == ReturnCode.Ok)
                            {
                                tclInterps.Remove(name);
                                result = String.Empty;

#if NOTIFY
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Tcl | NotifyType.Interpreter, NotifyFlags.Removed,
                                    new ObjectPair(name, interp), this,
                                    null, null, null, ref result);
#endif

                                return ReturnCode.Ok;
                            }
                        }
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool HasTclInterpreters()
        {
            Result error = null;
            return HasTclInterpreters(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetTclInterpreter(
            string name,
            LookupFlags lookupFlags,
            ref IntPtr interp
            )
        {
            Result error = null;

            return GetTclInterpreter(name, lookupFlags, ref interp, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetTclMasterInterpreter(
            LookupFlags lookupFlags,
            ref string name,
            ref IntPtr interp,
            ref Result error
            )
        {
            /* CheckDisposed(); */

            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref error))
                {
                    //
                    // HACK: Use the convention that we always prefix the
                    //       master Tcl interpreter with a specially formatted
                    //       name in order to find it (we cannot simply use the
                    //       Tcl interpreter at index zero because the Tcl
                    //       interpreters are maintained in a dictionary).
                    //
                    string pattern = FormatOps.Id(tclMasterInterpPrefix, null,
                        Characters.Asterisk.ToString());

                    //
                    // NOTE: Search all the Tcl interpreters in this interpreter
                    //       for the master Tcl interp stopping as soon as we
                    //       find a valid one (there should only be one valid
                    //       master Tcl interpreter per interpreter at any given
                    //       time).
                    //
                    string key = null;
                    IntPtr value = IntPtr.Zero;

                    foreach (KeyValuePair<string, IntPtr> pair in tclInterps)
                    {
                        //
                        // NOTE: Hard-coded match mode is OK here.
                        //
                        if (StringOps.Match(
                                this, MatchMode.Glob, pair.Key, pattern, false) &&
                            (pair.Value != IntPtr.Zero))
                        {
                            key = pair.Key;
                            value = pair.Value;
                            break;
                        }
                    }

                    //
                    // NOTE: Did we find the handle for the master Tcl
                    //       interpreter?
                    //
                    if (key != null)
                    {
                        name = key;
                        interp = value;

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = "Tcl master interpreter is not available";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Used by the Execute method of the _Commands.Tcl class to help
        //       implement the [tcl master] sub-command.
        //
        internal ReturnCode GetAnyTclMasterInterpreter(
            LookupFlags lookupFlags,
            ref string name,
            ref IntPtr interp,
            ref Result error
            )
        {
            ResultList errors = null;
            Result localError = null;

            if (GetTclMasterInterpreter(
                    lookupFlags, ref name, ref interp,
                    ref localError) == ReturnCode.Ok)
            {
                return ReturnCode.Ok;
            }
            else
            {
                if (errors == null)
                    errors = new ResultList();

                errors.Add(localError);
            }

#if NATIVE_PACKAGE
            localError = null;

            if (NativePackage.GetMasterTclInterpreter(
                    this, ref name, ref interp,
                    ref localError) == ReturnCode.Ok)
            {
                return ReturnCode.Ok;
            }
            else
            {
                if (errors == null)
                    errors = new ResultList();

                errors.Add(localError);
            }
#endif

            error = errors;
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the TclApi class only.
        //
        internal void AddTclInterpreter(
            string interpName,
            IntPtr interp
            )
        {
            lock (tclSyncRoot)
            {
                if (tclInterps == null)
                    return;

                tclInterps.Add(interpName, interp);
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Thread Support
#if TCL_THREADS
        public bool HasTclThreads(ref Result error)
        {
            CheckDisposed();

            bool result = (tclThreads != null);

            if (!result)
                error = "no Tcl threads available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesTclThreadExist(string name)
        {
            CheckDisposed();

            TclThread thread = null;
            Result error = null;

            return GetTclThread(name, LookupFlags.Exists, ref thread, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TCL_WRAPPER
        public
#else
        internal
#endif
        ReturnCode GetTclThread(
            string name,
            LookupFlags lookupFlags,
            ref TclThread thread,
            ref Result error
            )
        {
#if TCL_WRAPPER
            CheckDisposed();
#endif

            lock (tclSyncRoot)
            {
                if (HasTclThreads(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty Tcl thread names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (tclThreads.TryGetValue(name, out thread) &&
                            ((thread != null) ||
                            !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true)))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "invalid Tcl thread \"{0}\"",
                                    name) :
                                "invalid Tcl thread";
                        }
                    }
                    else
                    {
                        error = "invalid Tcl thread name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CreateTclThread(
            ResultCallback callback,
            IClientData clientData,
            int timeout,
            bool generic,
            bool debug,
            bool wait,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(true, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclThreads(ref result))
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
                        string name = FormatOps.Id(tclThreadPrefix, null,
                            GlobalState.NextThreadId(this));

                        TclThread thread = TclThread.Create(
                            this, callback, clientData, timeout, name, generic,
                            debug, ref result);

                        if (thread != null)
                        {
                            tclThreads.Add(name, thread);
                            result = name;

#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Tcl | NotifyType.Thread, NotifyFlags.Added,
                                new ObjectPair(name, thread), this,
                                null, null, null, ref result);
#endif

                            //
                            // HACK: Always wait for the thread to fully start by
                            //       using the default join timeout instead of the
                            //       timeout value specified by the caller.
                            //
                            if (wait)
                                thread.WaitForStart(ThreadOps.DefaultJoinTimeout);

                            return ReturnCode.Ok;
                        }
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DeleteTclThread(
            string name,
            bool strict,
            ref Result result
            )
        {
            CheckDisposed();

            TclThread thread = null;

            if (!IsModifiable(false, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclThreads(ref result))
                {
                    if ((GetTclThread(name, LookupFlags.Default, ref thread, ref result) == ReturnCode.Ok) &&
                        (thread == null))
                    {
                        result = "invalid Tcl thread";
                    }
                }
            }

            //
            // NOTE: If we managed to find the thread above then attempt
            //       to shut it down now.  We do this without holding a
            //       lock on the interpreter to avoid a deadlock with the
            //       other thread when it attempts to use the Tcl API
            //       object associated with this interpreter.
            //
            if (thread != null)
            {
                GlobalState.PushActiveInterpreter(this);

                try
                {
                    if (thread.Shutdown(
                            GetTclBridges(thread.Interp, null, null), true, false,
                            strict, ref result) == ReturnCode.Ok)
                    {
                        lock (tclSyncRoot)
                        {
                            tclThreads.Remove(name);
                        }

                        result = String.Empty;

#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Tcl | NotifyType.Thread, NotifyFlags.Removed,
                            new ObjectPair(name, thread), this,
                            null, null, null, ref result);
#endif

                        return ReturnCode.Ok;
                    }
                }
                finally
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string TclThreadsToString(
            string pattern,
            bool noCase
            )
        {
            lock (tclSyncRoot)
            {
                if (tclThreads != null)
                    return tclThreads.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool HasTclThreads()
        {
            Result error = null;
            return HasTclThreads(ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetTclThread(
            string name,
            LookupFlags lookupFlags,
            ref TclThread thread
            )
        {
            Result error = null;

            return GetTclThread(name, lookupFlags, ref thread, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: The returned Tcl interpreter may only be used in conjunction with the Tcl
        //          C API on the thread that it was created on.  This restriction is NOT
        //          enforced by this function as we are merely returning the pointer to it.
        //
        private ReturnCode GetTclInterpreterOrThread(
            string name,
            LookupFlags lookupFlags,
            ref IntPtr interp,
            ref bool fromThread,
            ref Result error
            )
        {
            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty Tcl interpreter and thread names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (tclInterps.TryGetValue(name, out interp) &&
                            ((interp != IntPtr.Zero) ||
                            !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true)))
                        {
                            fromThread = false;
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            if (HasTclThreads(ref error))
                            {
                                TclThread thread;

                                if (tclThreads.TryGetValue(name, out thread) &&
                                    ((thread != null) ||
                                    !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true)))
                                {
                                    interp = thread.Interp;
                                    fromThread = true;
                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    error = FlagOps.HasFlags(
                                        lookupFlags, LookupFlags.Verbose, true) ?
                                        String.Format(
                                            "invalid Tcl interpreter or thread \"{0}\"",
                                            name) :
                                        "invalid Tcl interpreter or thread";
                                }
                            }
                        }
                    }
                    else
                    {
                        error = "invalid Tcl interpreter or thread name";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetTclInterpreters(
            string pattern,
            LookupFlags lookupFlags,
            bool noCase,
            bool strict,
            ref IntPtrDictionary interps,
            ref Result error
            )
        {
            lock (tclSyncRoot)
            {
                Result localError = null;

                if (HasTclInterpreters(ref localError))
                {
                    if (interps == null)
                        interps = new IntPtrDictionary();

                    foreach (KeyValuePair<string, IntPtr> pair in tclInterps)
                    {
                        if ((pattern == null) ||
                            StringOps.Match(
                                this, MatchMode.Glob, pair.Key, pattern, noCase))
                        {
                            interps.Add(pair.Key, pair.Value);
                        }
                    }

                    return ReturnCode.Ok;
                }
                else if (strict)
                {
                    error = localError;
                    return ReturnCode.Error;
                }
                else
                {
                    return ReturnCode.Ok;
                }
            }
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Command Support
        public bool HasTclBridges(ref Result error)
        {
            CheckDisposed();

            bool result = (tclBridges != null);

            if (!result)
                error = "no Tcl bridges available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode DoesTclBridgeExist(string name)
        {
            CheckDisposed();

            TclBridge tclBridge = null;
            Result error = null;

            return GetTclBridge(name, LookupFlags.Exists, ref tclBridge, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddTclBridge(
            IExecute execute,
            string interpName,
            string commandName,
            IClientData clientData,
            bool forceDelete,
            bool noComplain,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(true, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (execute == null)
                {
                    result = "invalid execute";
                    return ReturnCode.Error;
                }

                if (!HasTclInterpreters(ref result))
                    return ReturnCode.Error;

                if (!HasTclBridges(ref result))
                    return ReturnCode.Error;

                IntPtr interp = IntPtr.Zero;

                //
                // NOTE: *THREADING* Get the Tcl interpreter even if it is in an isolated thread.
                //       If the Tcl interpreter is from an isolated thread then this method may
                //       only be called from that thread.
                //
                bool fromThread = false;

#if TCL_THREADS
                if (GetTclInterpreterOrThread(
                        interpName, LookupFlags.Default, ref interp,
                        ref fromThread, ref result) != ReturnCode.Ok)
#else
                if (GetTclInterpreter(
                        interpName, LookupFlags.Default, ref interp,
                        ref result) != ReturnCode.Ok)
#endif
                {
                    return ReturnCode.Error;
                }

                string bridgeName =
                    FormatOps.TclBridgeName(interpName, commandName);

                if (bridgeName == null)
                {
                    result = "invalid bridge name";
                    return ReturnCode.Error;
                }

                if (DoesTclBridgeExist(bridgeName) == ReturnCode.Ok)
                {
                    result = String.Format(
                        "can't add \"{0}\": command already exists in Tcl interpreter \"{1}\"",
                        commandName, interpName);

                    return ReturnCode.Error;
                }

                GlobalState.PushActiveInterpreter(this);

                try
                {
                    TclBridge tclBridge = TclBridge.Create(this, execute,
                        (clientData != null) ? clientData : ObjectOps.GetClientData(execute),
                        interp, commandName, fromThread, forceDelete, noComplain, ref result);

                    if (tclBridge == null)
                        return ReturnCode.Error;

                    tclBridges.Add(bridgeName, tclBridge);

#if NOTIFY
                    /* IGNORED */
                    CheckNotifications(
                        NotifyType.Tcl | NotifyType.Command, NotifyFlags.Added,
                        //
                        // BUGBUG: In order to use this class for notification
                        //         parameters, it really should probably be
                        //         made public.
                        //
                        new ObjectList(execute, interpName, commandName, bridgeName,
                            forceDelete, tclBridge), this,
                        clientData, null, null, ref result);
#endif

                    result = bridgeName;
                }
                finally
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode AddStandardTclBridge(
            string interpName,
            string commandName,
            IClientData clientData,
            bool forceDelete,
            bool noComplain,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(true, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                //
                // NOTE: Lookup and fetch a reference to the Eagle [eval]
                //       command, if available.
                //
                ICommand command = null;

                if (GetCommand(
                        typeof(_Commands.Eval), LookupFlags.Default,
                        ref command, ref result) == ReturnCode.Ok)
                {
                    //
                    // NOTE: Create a "bridge" between the Eagle [eval] command
                    //       and the native Tcl [eagle] command.  This allows a
                    //       native Tcl script to execute Eagle commands.
                    //
                    if (commandName == null)
                        commandName = GlobalState.GetPackageNameNoCase();

                    if (!String.IsNullOrEmpty(commandName))
                    {
                        return AddTclBridge(
                            command, interpName, commandName, null,
                            forceDelete, noComplain, ref result);
                    }

                    result = "invalid command name";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RemoveTclBridge(
            string interpName,
            string commandName,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(false, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclBridges(ref result))
                {
                    string bridgeName =
                        FormatOps.TclBridgeName(interpName, commandName);

                    TclBridge tclBridge = null;

                    if (GetTclBridge(
                            bridgeName, LookupFlags.Remove, ref tclBridge,
                            ref result) == ReturnCode.Ok)
                    {
                        GlobalState.PushActiveInterpreter(this);

                        try
                        {
                            if (tclBridge != null)
                            {
                                tclBridge.Dispose(); /* throw */
                                tclBridge = null;
                            }

                            tclBridges.Remove(bridgeName);

#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Tcl | NotifyType.Command, NotifyFlags.Removed,
                                //
                                // BUGBUG: In order to use this class for notification
                                //         parameters, it really should probably be
                                //         made public.
                                //
                                new ObjectList(interpName, commandName, bridgeName, tclBridge), this,
                                clientData, null, null, ref result);
#endif

                            result = String.Empty;
                            return ReturnCode.Ok;
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing Tcl bridge: {0}",
                                e);

                            return ReturnCode.Error;
                        }
                        finally
                        {
                            /* IGNORED */
                            GlobalState.PopActiveInterpreter();
                        }
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal string TclBridgesToString(
            string pattern,
            bool noCase
            )
        {
            lock (tclSyncRoot)
            {
                if (tclBridges != null)
                    return tclBridges.ToString(pattern, noCase);
                else
                    return null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal TclBridgeDictionary CopyTclBridges()
        {
            lock (tclSyncRoot)
            {
                return new TclBridgeDictionary(tclBridges);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void AddTclBridge(
            string name,
            TclBridge tclBridge
            )
        {
            if (name != null)
            {
                lock (tclSyncRoot)
                {
                    if (tclBridges != null)
                        tclBridges.Add(name, tclBridge);
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int RemoveTclBridges(
            TclBridge tclBridge
            )
        {
            int result = 0;

            lock (tclSyncRoot)
            {
                if (tclBridges != null)
                {
                    StringList keys = new StringList();

                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the TclBridges collection in the containing interpreter.
                    //
                    foreach (KeyValuePair<string, TclBridge> pair in tclBridges)
                        if (Object.ReferenceEquals(pair.Value, tclBridge))
                            keys.Add(pair.Key);

                    //
                    // NOTE: Cleanup, PASS #2, remove all the TclBridge objects we found
                    //       from PASS #1 (above).  Please note that since all of these
                    //       are assumed to refer to the same TclBridge object, dispose is
                    //       called [exactly once] after the TclBridge collection cleanup
                    //       has been completed.
                    //
                    foreach (string key in keys)
                        if (tclBridges.Remove(key))
                            result++;
                }
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetTclBridge(
            string name,
            LookupFlags lookupFlags,
            ref TclBridge tclBridge
            )
        {
            Result error = null;

            return GetTclBridge(name, lookupFlags, ref tclBridge, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetTclBridge(
            string name,
            LookupFlags lookupFlags,
            ref TclBridge tclBridge,
            ref Result error
            )
        {
            lock (tclSyncRoot)
            {
                if (HasTclBridges(ref error))
                {
                    //
                    // NOTE: *WARNING* Empty Tcl command names are allowed,
                    //       please do not change this to "!String.IsNullOrEmpty".
                    //
                    if (name != null)
                    {
                        if (tclBridges.TryGetValue(name, out tclBridge) &&
                            ((tclBridge != null) ||
                            !FlagOps.HasFlags(lookupFlags, LookupFlags.Validate, true)))
                        {
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = FlagOps.HasFlags(
                                lookupFlags, LookupFlags.Verbose, true) ?
                                String.Format(
                                    "invalid Tcl command \"{0}\"",
                                    name) :
                                "invalid Tcl command";
                        }
                    }
                    else
                    {
                        error = "invalid Tcl command name";
                    }
                }
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ITclManager Members
#if NATIVE && TCL
        #region Tcl Synchronization Support
        public object TclSyncRoot
        {
            //
            // TODO: Rethink this strategy.  Should calls for the interpreter
            //       lock from inside the interpreter methods be able to throw
            //       an exception?  If so, why?  If not, why not?
            //
            get { CheckDisposed(); return tclSyncRoot; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal object InternalTclSyncRoot
        {
            get { return tclSyncRoot; }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Loader Support
        public bool HasTcl(ref Result error)
        {
            CheckDisposed();

            bool result = (tclApi != null);

            if (!result)
                error = "no Tcl available";

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsTclThread()
        {
            CheckDisposed();

            return IsPrimaryThread();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetTclPatchLevel(
            ref Version patchLevel,
            ref Result error
            )
        {
            CheckDisposed();

            lock (tclSyncRoot)
            {
                if (tclApi != null)
                {
                    TclBuild build = tclApi.Build;

                    if (build != null)
                    {
                        patchLevel = build.PatchLevel;
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = "invalid Tcl build object";
                    }
                }
                else
                {
                    error = "invalid Tcl API object";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode LoadTcl(
            FindFlags flags,
            string path,
            Version minimumRequired,
            Version maximumRequired,
            Version unknown,
            IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            if (!IsModifiable(true, ref result))
                return ReturnCode.Error;

            lock (tclSyncRoot)
            {
                if (HasTclInterpreters(ref result))
                {
                    if (IsTclThread())
                    {
                        GlobalState.PushActiveInterpreter(this);

                        try
                        {
#if NOTIFY
                            /* IGNORED */
                            CheckNotifications(
                                NotifyType.Tcl, NotifyFlags.PreLoad,
                                //
                                // BUGBUG: In order to use this class for notification
                                //         parameters, it really should probably be
                                //         made public.
                                //
                                new ObjectList(flags, path, minimumRequired, maximumRequired, unknown), this,
                                null, null, null, ref result);
#endif

                            IntPtr interp = IntPtr.Zero;

                            if (TclWrapper.Load(this, flags, null, path, minimumRequired,
                                    maximumRequired, unknown, clientData, ref tclApi,
                                    ref interp, ref result) == ReturnCode.Ok)
                            {
                                string name = FormatOps.Id(tclMasterInterpPrefix, null, NextId());

                                //
                                // NOTE: Even though the master Tcl interpreter is not really intended
                                //       for general purpose scripting use, add it anyhow so that we
                                //       can keep track of it and delete it later.  This Tcl interpreter
                                //       is always considered to be "fully trusted" and has the full set
                                //       of Tcl commands available to it.
                                //
                                tclInterps.Add(name, interp);
                                result = name;

#if NOTIFY
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Tcl, NotifyFlags.Load,
                                    //
                                    // BUGBUG: In order to use this class for notification
                                    //         parameters, it really should probably be
                                    //         made public.
                                    //
                                    new ObjectList(flags, path, minimumRequired, maximumRequired, unknown), this,
                                    null, null, null, ref result);
#endif

                                return ReturnCode.Ok;
                            }
                        }
                        finally
                        {
                            /* IGNORED */
                            GlobalState.PopActiveInterpreter();
                        }
                    }
                    else
                    {
                        result = "cannot load Tcl, wrong thread";
                    }
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnloadTcl(
            UnloadFlags flags, /* in */
            ref Result error   /* out */
            )
        {
            CheckDisposed();

            if (!IsModifiable(false, ref error))
                return ReturnCode.Error;

            //
            // BUGFIX: Holding this lock while disposing of isolated Tcl
            //         threads can very easily result in a deadlock.
            //
            // lock (tclSyncRoot)
            {
                if (IsTclThread())
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Tcl, NotifyFlags.PreUnload,
                            flags, this,
                            null, null, null, ref error);
#endif

                        //
                        // NOTE: First, attempt to cleanup and/or dispose
                        //       any Tcl related objects.
                        //
                        if (DisposeTcl(false, false, false, ref error) == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Since the Tcl master interpreter should
                            //       already be deleted now, just [implicitly]
                            //       pass an invalid Tcl interpreter handle to
                            //       Unload here, which will cause it to skip
                            //       attempting to delete the Tcl master
                            //       interpreter.  After this call it may no
                            //       longer be safe to use the Tcl API because
                            //       we may be holding the last reference to it
                            //       and this call will then cause it to be
                            //       completely unloaded from memory.
                            //
                            if (TclWrapper.Unload(this, flags, ref tclApi,
                                    ref error) == ReturnCode.Ok)
                            {
#if NOTIFY
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Tcl, NotifyFlags.Unload,
                                    flags, this,
                                    null, null, null, ref error);
#endif

                                return ReturnCode.Ok;
                            }
                        }
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
                else
                {
                    error = "cannot unload Tcl, wrong thread";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TCL_WRAPPER
        public ITclApi TclApi
        {
            get
            {
                CheckDisposed();

                lock (tclSyncRoot)
                {
                    return tclApi;
                }
            }
            set
            {
                CheckDisposed();

                lock (tclSyncRoot)
                {
                    tclApi = value;
                }
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal ITclApi InternalTclApi
        {
            get { return tclApi; }
            set { tclApi = value; }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Interpreter Support
        public bool IsTclInterpreterReady(
            string name,
            ref Result error
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            if (GetTclInterpreter(name, LookupFlags.Default, ref interp, ref error) == ReturnCode.Ok)
                return TclWrapper.IsReady(tclApi, interp, ref error);

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool IsTclInterpreterActive(
            string name
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            if (GetTclInterpreter(name, LookupFlags.Default, ref interp) == ReturnCode.Ok)
                return TclWrapper.GetInterpActive(tclApi, interp);

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int GetTclInterpreterErrorLine(
            string name
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            if (GetTclInterpreter(name, LookupFlags.Default, ref interp) == ReturnCode.Ok)
                return TclWrapper.GetErrorLine(tclApi, interp);

            return 0;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal bool IsTclInterpreterReady(
            string name
            )
        {
            Result error = null;

            return IsTclInterpreterReady(name, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool FindTclInterpreterThreadId(
            IntPtr interp,
            ref int threadId
            )
        {
            IntPtrList interps = null;
#if TCL_THREADS
            TclThreadList threads = null;
#endif

            //
            // BUGBUG: This is likely to be a serious performance bottleneck
            //         since this method must be called for every Tcl API
            //         function call that involves a Tcl interpreter or a Tcl
            //         object.
            //
            lock (tclSyncRoot)
            {
                //
                // NOTE: Get the list of Tcl interps from the
                //       interpreter.
                //
                if (HasTclInterpreters())
                    interps = new IntPtrList(tclInterps.Values);

#if TCL_THREADS
                //
                // NOTE: Get the list of Tcl threads from the
                //       interpreter.
                //
                if (HasTclThreads())
                    threads = new TclThreadList(tclThreads.Values);
#endif
            }

            //
            // NOTE: First, check the Tcl interps that belong to the
            //       primary thread for this interpreter.
            //
            if (interps != null)
            {
                foreach (IntPtr localInterp in interps)
                {
                    if (localInterp == interp)
                    {
                        //
                        // NOTE: Return the primary thread Id.
                        //
                        threadId = this.threadId;

                        //
                        // NOTE: Success, we found the Tcl interpreter.
                        //
                        return true;
                    }
                }
            }

#if TCL_THREADS
            //
            // NOTE: Next, check the Tcl threads that belong to this
            //       interpreter.  Each one of these threads has an
            //       isolated Tcl interpreter.
            //
            if (threads != null)
            {
                foreach (TclThread thread in threads)
                {
                    if ((thread != null) && (thread.Interp == interp))
                    {
                        //
                        // NOTE: Return the specified thread Id for this Tcl
                        //       interpreter.
                        //
                        threadId = thread.ThreadId;

                        //
                        // NOTE: Success, we found the Tcl interpreter.
                        //
                        return true;
                    }
                }
            }
#endif

#if TCL_WRAPPER
            // lock (syncRoot) /* NOTE: Avoid deadlock? */
            {
                //
                // NOTE: In "Tcl wrapper" mode, we assume that any Tcl
                //       interpreter we cannot otherwise locate was
                //       created on the main thread of the Eagle
                //       interpreter.
                //
                if (FlagOps.HasFlags(createFlags, CreateFlags.TclWrapper, true))
                {
                    //
                    // NOTE: Return the primary thread Id.
                    //
                    threadId = this.threadId;

                    return true;
                }
            }
#endif

            //
            // NOTE: Failure, we did not find the Tcl interpreter.
            //
            return false;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Thread Event Support
#if TCL_THREADS
        public ReturnCode QueueTclThreadEvent(
            string threadName,
            EventType type,
            EventFlags flags,
            object data,
            bool synchronous,
            ref Result result
            )
        {
            CheckDisposed();

            int errorLine = 0;

            return QueueTclThreadEvent(
                threadName, type, flags, data, synchronous, ref result, ref errorLine);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode QueueTclThreadEvent(
            string threadName,
            EventType type,
            EventFlags flags,
            object data,
            bool synchronous,
            ref Result result,
            ref int errorLine
            )
        {
            CheckDisposed();

            TclThread thread = null;

            if (GetTclThread(threadName, LookupFlags.Default, ref thread, ref result) == ReturnCode.Ok)
            {
                if (thread != null)
                {
                    if (thread.QueueEvent(type, flags, data, synchronous,
                            ref result, ref errorLine) == ReturnCode.Ok)
                    {
#if NOTIFY
                        /* IGNORED */
                        CheckNotifications(
                            NotifyType.Tcl | NotifyType.Thread | NotifyType.Event, NotifyFlags.Queued,
                            new ObjectList(threadName, thread, type, flags, data, synchronous),
                            this, null, null, null, ref result);
#endif

                        return ReturnCode.Ok;
                    }
                }
                else
                {
                    result = "invalid Tcl thread";
                }
            }

            return ReturnCode.Error;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Thread Miscellaneous Support
#if !TCL_THREADS
        internal bool IsPrimaryTclThread(
            ref int threadId /* in, out */
            )
        {
            //
            // NOTE: Is the thread Id provided by the caller the same as the
            //       primary one for this interpreter?
            //
            bool result = (threadId == this.threadId);

            //
            // NOTE: Now that we know the result, overwrite the thread Id
            //       provided by the caller with the primary one for this
            //       interpreter, if necessary (for their use).
            //
            if (!result) /* NOTE: Skip if already the same. */
                threadId = this.threadId;

            //
            // NOTE: Done, return the result.
            //
            return result;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Script Support
        public ReturnCode CancelTclEvaluate(
            string interpName,
            bool unwind,
            Result result,
            ref Result error
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return CancelTclEvaluate(interpName, unwind, result, ref clientData, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode CancelTclEvaluate(
            string interpName,
            bool unwind,
            Result result,
            ref IClientData clientData,
            ref Result error
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                code = TclWrapper.CancelEvaluate(
                    tclApi, interp, unwind, result, ref clientData, ref error);
            }

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.Tcl | NotifyType.Script, NotifyFlags.Canceled,
                new ObjectTriplet(unwind, result, code), this,
                null, null, null, ref error);
#endif

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclExpression(
            string interpName,
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclExpression(interpName, text, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclExpression(
            string interpName,
            string text,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return EvaluateTclExpression(interpName, text, exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclExpression(
            string interpName,
            string text,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclExpression(
                interpName, text, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclExpression(
            string interpName,
            string text,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                string name = StringList.MakeList("tcl expr", interpName);

                ICallFrame frame = NewTrackingCallFrame(name,
                    CallFrameFlags.Expression | CallFrameFlags.Tcl);

                PushAutomaticCallFrame(frame);

                code = TclWrapper.EvaluateExpression(
                    tclApi, interp, text, exceptions, ref clientData, ref result);

                if (code == ReturnCode.Error)
                {
                    Result errorInfo = null;

                    if (TclWrapper.GetVariable(tclApi, interp, Tcl_VarFlags.TCL_GLOBAL_ONLY,
                            TclVars.ErrorInfo, ref errorInfo, ref errorInfo) == ReturnCode.Ok)
                    {
                        Engine.AddErrorInformation(this, null,
                            String.Format("{0}{1}", HasErrorInProgress()
                                ? Environment.NewLine : String.Empty, errorInfo));
                    }

                    Engine.AddErrorInformation(this, result,
                        String.Format("{0}    (\"tcl expr\" body line {1})",
                            Environment.NewLine, TclWrapper.GetErrorLine(tclApi, interp)));
                }

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Expression, NotifyFlags.Evaluated,
                    new ObjectTriplet(interpName, text, code), this,
                    null, null, null, ref result);
#endif

                //
                // NOTE: Pop the original call frame that we pushed above and
                //       any intervening scope call frames that may be leftover
                //       (i.e. they were not explicitly closed).
                //
                /* IGNORED */
                PopCallFrame(CallFrameFlags.Scope, true);
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool TclExceptions
        {
            get
            {
                CheckDisposed();

                lock (tclSyncRoot)
                {
                    return (tclApi != null) ? tclApi.Exceptions : false;
                }
            }
            set
            {
                CheckDisposed();

                lock (tclSyncRoot)
                {
                    if (tclApi != null) tclApi.Exceptions = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(
                interpName, text, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(interpName, text, Tcl_EvalFlags.TCL_EVAL_NONE,
                exceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(
                interpName, text, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(interpName, text, Tcl_EvalFlags.TCL_EVAL_NONE,
                exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(
                interpName, text, flags, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return EvaluateTclScript(interpName, text, flags, exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclScript(
                interpName, text, flags, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                string name = StringList.MakeList("tcl eval", interpName);

                ICallFrame frame = NewTrackingCallFrame(name,
                    CallFrameFlags.Evaluate | CallFrameFlags.Tcl);

                PushAutomaticCallFrame(frame);

                code = TclWrapper.EvaluateScript(
                    tclApi, interp, text, flags, exceptions, ref clientData, ref result);

                if (code == ReturnCode.Error)
                {
                    Result errorInfo = null;

                    if (TclWrapper.GetVariable(tclApi, interp, Tcl_VarFlags.TCL_GLOBAL_ONLY,
                            TclVars.ErrorInfo, ref errorInfo, ref errorInfo) == ReturnCode.Ok)
                    {
                        Engine.AddErrorInformation(this, null,
                            String.Format("{0}{1}", HasErrorInProgress()
                                ? Environment.NewLine : String.Empty, errorInfo));
                    }

                    Engine.AddErrorInformation(this, result,
                        String.Format("{0}    (\"tcl eval\" body line {1})",
                            Environment.NewLine, TclWrapper.GetErrorLine(tclApi, interp)));
                }

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Script, NotifyFlags.Evaluated,
                    new ObjectTriplet(interpName, text, flags), this,
                    null, null, null, ref result);
#endif

                //
                // NOTE: Pop the original call frame that we pushed above and
                //       any intervening scope call frames that may be leftover
                //       (i.e. they were not explicitly closed).
                //
                /* IGNORED */
                PopCallFrame(CallFrameFlags.Scope, true);
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclFile(
            string interpName,
            string fileName,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclFile(
                interpName, fileName, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclFile(
            string interpName,
            string fileName,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return EvaluateTclFile(interpName, fileName, exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclFile(
            string interpName,
            string fileName,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return EvaluateTclFile(
                interpName, fileName, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode EvaluateTclFile(
            string interpName,
            string fileName,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                string name = StringList.MakeList("tcl source", interpName, fileName);

                ICallFrame frame = NewTrackingCallFrame(name,
                    CallFrameFlags.Source | CallFrameFlags.Tcl);

                PushAutomaticCallFrame(frame);

                code = TclWrapper.EvaluateFile(
                    tclApi, interp, fileName, exceptions, ref clientData, ref result);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.File, NotifyFlags.Evaluated,
                    new ObjectPair(interpName, fileName), this,
                    null, null, null, ref result);
#endif

                //
                // NOTE: Pop the original call frame that we pushed above and
                //       any intervening scope call frames that may be leftover
                //       (i.e. they were not explicitly closed).
                //
                /* IGNORED */
                PopCallFrame(CallFrameFlags.Scope, true);
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(
                interpName, text, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(interpName, text, Tcl_EvalFlags.TCL_EVAL_NONE,
                exceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(
                interpName, text, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(interpName, text, Tcl_EvalFlags.TCL_EVAL_NONE,
                exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(
                interpName, text, flags, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return RecordAndEvaluateTclScript(
                interpName, text, flags, exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return RecordAndEvaluateTclScript(
                interpName, text, flags, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode RecordAndEvaluateTclScript(
            string interpName,
            string text,
            Tcl_EvalFlags flags,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                string name = StringList.MakeList("tcl record", interpName);

                ICallFrame frame = NewTrackingCallFrame(name,
                    CallFrameFlags.Evaluate | CallFrameFlags.Tcl);

                PushAutomaticCallFrame(frame);

                code = TclWrapper.RecordAndEvaluateScript(
                    tclApi, interp, text, flags, exceptions, ref clientData, ref result);

                if (code == ReturnCode.Error)
                {
                    Result errorInfo = null;

                    if (TclWrapper.GetVariable(tclApi, interp, Tcl_VarFlags.TCL_GLOBAL_ONLY,
                            TclVars.ErrorInfo, ref errorInfo, ref errorInfo) == ReturnCode.Ok)
                    {
                        Engine.AddErrorInformation(this, null,
                            String.Format("{0}{1}", HasErrorInProgress()
                                ? Environment.NewLine : String.Empty, errorInfo));
                    }

                    Engine.AddErrorInformation(this, result,
                        String.Format("{0}    (\"tcl record\" body line {1})",
                            Environment.NewLine, TclWrapper.GetErrorLine(tclApi, interp)));
                }

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Script, NotifyFlags.Evaluated,
                    new ObjectTriplet(interpName, text, flags), this,
                    null, null, null, ref result);
#endif

                //
                // NOTE: Pop the original call frame that we pushed above and
                //       any intervening scope call frames that may be leftover
                //       (i.e. they were not explicitly closed).
                //
                /* IGNORED */
                PopCallFrame(CallFrameFlags.Scope, true);
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteTclString(
                interpName, text, TclExceptions, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return SubstituteTclString(interpName, text, exceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteTclString(
                interpName, text, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteTclString(interpName, text, Tcl_SubstFlags.TCL_SUBST_ALL, exceptions,
                ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            Tcl_SubstFlags flags,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return SubstituteTclString(interpName, text, flags, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            Tcl_SubstFlags flags,
            bool exceptions,
            ref Result result
            )
        {
            CheckDisposed();

            IClientData clientData = null;

            return SubstituteTclString(interpName, text, flags, exceptions, ref clientData,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            Tcl_SubstFlags flags,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            return SubstituteTclString(
                interpName, text, flags, TclExceptions, ref clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SubstituteTclString(
            string interpName,
            string text,
            Tcl_SubstFlags flags,
            bool exceptions,
            ref IClientData clientData,
            ref Result result
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref result);

            if (code == ReturnCode.Ok)
            {
                string name = StringList.MakeList("tcl subst", interpName);

                ICallFrame frame = NewTrackingCallFrame(name,
                    CallFrameFlags.Substitute | CallFrameFlags.Tcl);

                PushAutomaticCallFrame(frame);

                code = TclWrapper.SubstituteString(
                    tclApi, interp, text, flags, exceptions, ref clientData, ref result);

                if (code == ReturnCode.Error)
                {
                    Result errorInfo = null;

                    if (TclWrapper.GetVariable(tclApi, interp, Tcl_VarFlags.TCL_GLOBAL_ONLY,
                            TclVars.ErrorInfo, ref errorInfo, ref errorInfo) == ReturnCode.Ok)
                    {
                        Engine.AddErrorInformation(this, null,
                            String.Format("{0}{1}", HasErrorInProgress()
                                ? Environment.NewLine : String.Empty, errorInfo));
                    }

                    Engine.AddErrorInformation(this, result,
                        String.Format("{0}    (\"tcl subst\" body line {1})",
                            Environment.NewLine, TclWrapper.GetErrorLine(tclApi, interp)));
                }

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.String, NotifyFlags.Substituted,
                    new ObjectTriplet(interpName, text, code), this,
                    null, null, null, ref result);
#endif

                //
                // NOTE: Pop the original call frame that we pushed above and
                //       any intervening scope call frames that may be leftover
                //       (i.e. they were not explicitly closed).
                //
                /* IGNORED */
                PopCallFrame(CallFrameFlags.Scope, true);
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Variable Support
        public ReturnCode GetTclVariableValue(
            string interpName,
            Tcl_VarFlags flags,
            string name,
            ref Result value,
            ref Result error
            )
        {
            CheckDisposed();

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref error);

            if (code == ReturnCode.Ok)
            {
                code = TclWrapper.GetVariable(
                    tclApi, interp, flags, name, ref value, ref error);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Variable, NotifyFlags.GetVariable,
                    new ObjectList(interpName, flags, name, value), this,
                    null, null, null, ref error);
#endif
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetTclVariableValue(
            string interpName,
            Tcl_VarFlags flags,
            string name,
            ref Result value,
            ref Result error
            )
        {
            CheckDisposed();

            if (!IsModifiable(false, ref error))
                return ReturnCode.Error;

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref error);

            if (code == ReturnCode.Ok)
            {
                code = TclWrapper.SetVariable(
                    tclApi, interp, flags, name, ref value, ref error);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Variable, NotifyFlags.SetVariable,
                    new ObjectList(interpName, flags, name, value), this,
                    null, null, null, ref error);
#endif
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnsetTclVariableValue(
            string interpName,
            Tcl_VarFlags flags,
            string name,
            ref Result error
            )
        {
            CheckDisposed();

            if (!IsModifiable(false, ref error))
                return ReturnCode.Error;

            IntPtr interp = IntPtr.Zero;

            ReturnCode code = GetTclInterpreter(
                interpName, LookupFlags.Default, ref interp, ref error);

            if (code == ReturnCode.Ok)
            {
                code = TclWrapper.UnsetVariable(
                    tclApi, interp, flags, name, ref error);

#if NOTIFY
                /* IGNORED */
                CheckNotifications(
                    NotifyType.Tcl | NotifyType.Variable, NotifyFlags.UnsetVariable,
                    new ObjectTriplet(interpName, flags, name), this,
                    null, null, null, ref error);
#endif
            }

            return code;
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IVariableManager Members
        #region Variable Checking
        public ReturnCode DoesVariableExist(VariableFlags flags, string name)
        {
            CheckDisposed();

            IVariable variable = null;

            return DoesVariableExist(flags, name, ref variable);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Variable Performance
        public ReturnCode MakeVariableFast(
            string name,
            bool fast,
            ref Result error
            )
        {
            CheckDisposed();

            ReturnCode code;

            lock (syncRoot) /* TRANSACTIONAL */
            {
                VariableFlags flags = VariableFlags.NoElement;
                IVariable variable = null;

                code = GetVariableViaResolversWithSplit(
                    name, ref flags, ref variable, ref error);

                if (code == ReturnCode.Ok)
                {
                    if (EntityOps.IsLink(variable))
                        variable = EntityOps.FollowLinks(variable, flags);

                    if (fast)
                        variable.Flags |= VariableFlags.FastMask;
                    else
                        variable.Flags &= ~VariableFlags.FastMask;
                }
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Variable Management (Single)
        public ReturnCode AddVariable(
            VariableFlags flags,
            string name,
            TraceList traces,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            IVariable variable = null;

            return AddVariable2(
                flags, name, traces, strict, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode GetVariableValue(
            VariableFlags flags,
            string name,
            ref Result value,
            ref Result error
            )
        {
            CheckDisposed();

            IVariable variable = null;

            return GetVariableValue2(
                flags, name, null, ref variable, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode ResetVariable(
            VariableFlags flags,
            string name,
            ref Result error
            )
        {
            CheckDisposed();

            return ResetVariable2(flags, null, name, null, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetVariableLink(
            VariableFlags flags,
            string name,
            MemberInfo memberInfo,
            object @object,
            ref Result error
            )
        {
            CheckDisposed();

            IVariable variable = null;

            return SetVariableLink2(
                flags, null, name, null, memberInfo, @object, ref variable,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetVariableSystemArray(
            VariableFlags flags,
            string name,
            Array array,
            ref Result error
            )
        {
            CheckDisposed();

            IVariable variable = null;

            return SetVariableSystemArray2(
                flags, null, name, array, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetVariableValue(
            VariableFlags flags,
            string name,
            string value,
            TraceList traces,
            ref Result error
            )
        {
            CheckDisposed();

            IVariable variable = null;

            return SetVariableValue(
                flags, name, value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnsetVariable(
            VariableFlags flags,
            string name,
            ref Result error
            )
        {
            CheckDisposed();

            return UnsetVariable2(flags, name, null, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode WaitVariable(
            VariableFlags flags,    /* in */
            string name,            /* in */
            int limit,              /* in */
            EventWaitHandle @event, /* in, optional */
            bool noCancel,          /* in */
            bool stopOnError,       /* in */
            bool errorOnEmpty,      /* in */
            bool userInterface,     /* in */
            ref Result error        /* out */
            ) /* THREAD-SAFE */
        {
            CheckDisposed();

            ReturnCode code;

            if (EnterWait() > 0)
            {
                //
                // NOTE: *WARNING* Empty variable names are allowed, please do not change
                //       these to "!String.IsNullOrEmpty".
                //
                if (name != null)
                {
                    //
                    // NOTE: *WARNING* Sanity check the user-interface flag here.  We MUST
                    //       pump messages if this is an STA thread.
                    //
                    if (!userInterface && ThreadOps.IsStaThread())
                    {
                        userInterface = true;

                        if (FlagOps.HasFlags(flags, VariableFlags.WaitTrace, true))
                        {
                            //
                            // HACK: Uses the interpreter "id" field directly, to avoid
                            //       disposal exception issues.
                            //
                            TraceOps.DebugTrace(String.Format(
                                "{0}: WaitVariable: detected STA thread, user-interface " +
                                "flag forcibly enabled, interpreter = {1}, flags = {2}, " +
                                "name = {3}, limit = {4}, noCancel = {5}, stopOnError = {6}, " +
                                "errorOnEmpty = {7}, userInterface = {8}, waitCount = {9}, " +
                                "waitSpinCount = {10}, error = {11}{12}",
                                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(id),
                                FormatOps.WrapOrNull(flags), FormatOps.WrapOrNull(name),
                                limit, noCancel, stopOnError, errorOnEmpty, userInterface,
                                waitCount, waitSpinCount, FormatOps.WrapOrNull(true, true, error),
                                Environment.NewLine), typeof(Interpreter).Name);
                        }
                    }

                    //
                    // NOTE: Has the existence of the variable been checked?
                    //
                    bool once = false;

                    //
                    // NOTE: NOTE: Does the variable currently exist?
                    //
                    bool exists = false;

                    //
                    // NOTE: Has the variable been added, modified, or unset since we
                    //       started waiting?
                    //
                    bool dirty = false;

                    //
                    // NOTE: Create the array of event handles to wait on.  The first event
                    //       is signaled when any variable is set or unset in the interpreter.
                    //       The second event is signaled when the queue managed by the event
                    //       manager is empty.  The third [and final] event is signaled when
                    //       an event is queued to the queue managed by the event manager.
                    //
                    EventWaitHandle[] events = GetEventWaitHandles(@event, true);

                    //
                    // NOTE: Keep track of the iterations of main loop of this method (for
                    //       diagnostic purposes only).
                    //
                    int localWaitSpinCount = 0;

                    //
                    // NOTE: Keep waiting for the variable until one of the following
                    //       conditions is true:
                    //
                    //       1. The interpreter is no longer ready (i.e. canceled, deleted,
                    //          halted, exited, etc).
                    //
                    //       2. The variable is created, deleted, or changed.
                    //
                    //       3. Any error is raised while processing events.
                    //
                    while (((code = EventReady(this, noCancel, ref error)) == ReturnCode.Ok) &&
                           ((code = IsVariableNameDirty(this, name, flags, ref once, ref exists,
                                ref dirty, ref error)) == ReturnCode.Ok) && !dirty)
                    {
                        //
                        // NOTE: We need a local result because we do not want to change
                        //       the caller's result based on random async events that
                        //       get processed while waiting for their variable to become
                        //       "signaled".  However, we will change the caller's result
                        //       if an error is encountered.
                        //
                        Result localResult = null;

                        //
                        // NOTE: Attempt to process all pending events stopping if an error
                        //       is encountered.  This grabs and uses the current wait event
                        //       flags without locking.
                        //
                        code = EventOps.DoOneEvent(
                            this, waitEventFlags, EventPriority.WaitVariable, limit,
                            stopOnError, errorOnEmpty, userInterface, ref localResult);

                        //
                        // NOTE: If we encountered an error processing events, break out
                        //       of the loop and return the error code and result to the
                        //       caller.
                        //
                        if (code != ReturnCode.Ok)
                        {
                            error = localResult;
                            break;
                        }

                        //
                        // NOTE: Get the configured sleep time for this interpreter [or
                        //       the minimum possible sleep time].
                        //
                        int milliseconds = GetMinimumSleepTime();

                        //
                        // NOTE: We always yield to other running threads.  This also
                        //       gives them an opportunity to cancel any script being
                        //       evaluated on this thread and/or update the variable we
                        //       are waiting for.
                        //
                        if (events != null)
                        {
#if NATIVE && WINDOWS
                            /* IGNORED */
                            WindowOps.WaitForMultipleHandles(
                                events, milliseconds, userInterface);
#else
                            /* IGNORED */
                            ThreadOps.WaitAnyEvent(events, milliseconds);
#endif
                        }
                        else
                        {
                            HostOps.Sleep(this, milliseconds);
                        }

                        //
                        // NOTE: Keep track of how many times we actually waited for an
                        //       event.  This does not currently distinguish between a
                        //       timeout and one of the event handles being signaled.
                        //
                        localWaitSpinCount++; /* THREAD-SAFE */
                        Interlocked.Increment(ref waitSpinCount);
                    }

                    ClearVariableNameWait(this, name, flags);

                    //
                    // NOTE: Show diagnostic information about this wait operation?
                    //
                    if (FlagOps.HasFlags(flags, VariableFlags.WaitTrace, true))
                    {
                        //
                        // HACK: Uses the interpreter "id" field directly, to avoid disposal
                        //       exception issues.
                        //
                        TraceOps.DebugTrace(String.Format(
                            "{0}: WaitVariable: interpreter = {1}, code = {2}, flags = {3}, " +
                            "name = {4}, limit = {5}, noCancel = {6}, stopOnError = {7}, " +
                            "errorOnEmpty = {8}, once = {9}, exists = {10}, dirty = {11}, " +
                            "waitCount = {12}, localWaitSpinCount = {13}, waitSpinCount = {14}, " +
                            "error = {15}{16}", GlobalState.GetCurrentThreadId(),
                            FormatOps.WrapOrNull(id), code, FormatOps.WrapOrNull(flags),
                            FormatOps.WrapOrNull(name), limit, noCancel, stopOnError,
                            errorOnEmpty, once, exists, dirty, waitCount, localWaitSpinCount,
                            waitSpinCount, FormatOps.WrapOrNull(true, true, error),
                            Environment.NewLine), typeof(Interpreter).Name);
                    }
                }
                else
                {
                    error = "invalid variable name";
                    code = ReturnCode.Error;
                }

                /* IGNORED */
                ExitWait();
            }
            else
            {
                error = "wait subsystem locked";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        internal StringList VariablesToList(
            VariableFlags flags,
            string pattern,
            bool noCase
            )
        {
            lock (syncRoot)
            {
                bool globalOnly = FlagOps.HasFlags(
                    flags, VariableFlags.GlobalOnly, true);

                ICallFrame variableFrame = null;
                VariableFlags frameFlags = VariableFlags.None;
                INamespace @namespace = null;
                string qualifiers = null;
                bool qualified = false;
                bool absolute = false;

                if (globalOnly)
                {
                    if (pattern != null)
                        pattern = ScriptOps.MakeVariableName(pattern);

                    variableFrame = GlobalFrame;
                }
                else
                {
                    bool useNamespaces = AreNamespacesEnabled();

                    if (useNamespaces && (pattern != null))
                    {
                        string tail = null;
                        NamespaceFlags namespaceFlags = NamespaceFlags.None;

                        if (NamespaceOps.SplitName(
                                pattern, ref qualifiers, ref tail,
                                ref namespaceFlags) != ReturnCode.Ok)
                        {
                            return null;
                        }

                        qualified = FlagOps.HasFlags(
                            namespaceFlags, NamespaceFlags.Qualified, true);

                        absolute = FlagOps.HasFlags(
                            namespaceFlags, NamespaceFlags.Absolute, true);

                        @namespace = NamespaceOps.Lookup(
                            this, qualifiers, false, false);

                        if (@namespace == null)
                            return null;

                        if (qualified || absolute)
                        {
                            if (IsGlobalNamespace(@namespace))
                            {
                                variableFrame = GlobalFrame;
                                frameFlags |= VariableFlags.GlobalOnly;
                            }
                            else
                            {
                                variableFrame = @namespace.VariableFrame;
                            }
                        }
                        else
                        {
                            variableFrame = GetVariableFrame(null, frameFlags);

                            if (GetVariableFrameViaResolvers(
                                    LookupFlags.Default, ref variableFrame,
                                    ref frameFlags) != ReturnCode.Ok)
                            {
                                return null;
                            }
                        }

                        pattern = tail;
                    }
                    else
                    {
                        if (useNamespaces &&
                            GetCurrentNamespaceViaResolvers(
                                null, LookupFlags.Default,
                                ref @namespace) != ReturnCode.Ok)
                        {
                            return null;
                        }

                        variableFrame = GetVariableFrame(null,
                            ref pattern, ref frameFlags);

                        if (GetVariableFrameViaResolvers(
                                LookupFlags.Default, ref variableFrame,
                                ref frameFlags) != ReturnCode.Ok)
                        {
                            return null;
                        }
                    }
                }

                if (variableFrame == null)
                    return null;

                VariableDictionary variables = variableFrame.Variables;

                if (variables == null)
                    return null;

                StringList list = new StringList();

                bool linksOnly = FlagOps.HasFlags(flags,
                    VariableFlags.Link, true);

                bool systemOnly = FlagOps.HasFlags(flags,
                    VariableFlags.System, true);

                bool undefinedOnly = FlagOps.HasFlags(flags,
                    VariableFlags.Undefined, true);

                bool frameGlobalOnly = FlagOps.HasFlags(frameFlags,
                    VariableFlags.GlobalOnly, true);

                foreach (KeyValuePair<string, IVariable> pair in variables)
                {
                    IVariable variable = pair.Value;

                    if (!undefinedOnly && EntityOps.IsUndefined(variable))
                        continue;

                    string varName = pair.Key;

                    if ((pattern != null) && !StringOps.Match(
                            this, StringOps.DefaultMatchMode, varName,
                            pattern, false))
                    {
                        continue;
                    }

                    ///////////////////////////////////////////////////////////

                    if (globalOnly)
                    {
                        //
                        // BUGFIX: *COMPAT* Tcl. Apparently, links to undefined
                        //         variables do show up in the list of returned
                        //         globals (upvar-8.10).
                        //
                        // BUGFIX: Actually, that is a Tcl bug, not a feature;
                        //         therefore, we will mask undefined variables
                        //         from being returned by this command.
                        //
                        if (IsGlobalCallFrame(CallFrameOps.FollowNext(
                                variable.Frame)))
                        {
                            list.Add(varName);
                        }
                    }
                    else if ((!linksOnly || EntityOps.IsLink(variable)) &&
                        (!systemOnly || EntityOps.IsSystem(variable)) &&
                        (!undefinedOnly || EntityOps.IsUndefined(variable)))
                    {
                        //
                        // NOTE: Add the local variable or variable link name
                        //       to the resulting list.
                        //
                        if ((@namespace != null) &&
                            !IsGlobalNamespace(@namespace))
                        {
                            list.Add(NamespaceOps.MakeName(qualifiers,
                                varName, qualified, qualified || absolute));
                        }
                        else
                        {
                            list.Add(frameGlobalOnly ?
                                NamespaceOps.MakeAbsoluteName(varName) :
                                varName);
                        }
                    }
                }

                return list;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariable(
            ICallFrame frame,
            string varName,
            string varIndex, /* NOT USED */
            ref VariableFlags variableFlags,
            ref IVariable variable,
            ref Result error
            ) /* USED BY CORE RESOLVER ONLY */
        {
            /* CheckDisposed(); */

            //
            // NOTE: Reset the "NotFound" flag because we have not actually
            //       searched for the variable yet.
            //
            variableFlags &= ~VariableFlags.NotFound;

            //
            // NOTE: Make sure the supplied variable name is valid.
            //
            if (varName == null)
            {
                error = "invalid variable name";
                return ReturnCode.Error;
            }

            lock (syncRoot) /* TRANSACTIONAL */
            {
                //
                // NOTE: Get the applicable call frame based on the provided
                //       variable name and flags.
                //
                ICallFrame variableFrame = frame;

                if (GetVariableFrameViaResolvers(
                        LookupFlags.Default, ref variableFrame,
                        ref varName, ref variableFlags,
                        ref error) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }

                if (variableFrame == null)
                {
                    error = "invalid call frame from resolver";
                    return ReturnCode.Error;
                }

                VariableDictionary variables = variableFrame.Variables;

                if (variables == null)
                {
                    error = "call frame does not support variables";
                    return ReturnCode.Error;
                }

                if (variables.Count == 0)
                {
                    //
                    // NOTE: The variable cannot exist in the call frame
                    //       (i.e. there are no variables in the call
                    //       frame), set the "NotFound" flag.
                    //
                    variableFlags |= VariableFlags.NotFound;

                    error = "no variables in call frame";
                    return ReturnCode.Error;
                }

                //
                // NOTE: Try to get the variable in the desired call frame.
                //
                IVariable localVariable = null;

                if (variables.TryGetValue(varName, out localVariable))
                {
                    //
                    // NOTE: Now, see if they require that this be an
                    //       undefined variable (or not).
                    //
                    bool wantDefined = FlagOps.HasFlags(
                        variableFlags, VariableFlags.Defined, true);

                    bool wantUndefined = FlagOps.HasFlags(
                        variableFlags, VariableFlags.Undefined, true);

                    bool isUndefined = EntityOps.IsUndefined(localVariable);

                    if ((!wantDefined && !wantUndefined) ||
                        (wantDefined && !isUndefined) ||
                        (wantUndefined && isUndefined))
                    {
                        //
                        // NOTE: Do they want to allow virtual variables
                        //       to be returned?  If not, raise an error
                        //       now.
                        //
                        bool wantVirtual = !FlagOps.HasFlags(
                            variableFlags, VariableFlags.NonVirtual, true);

                        bool isVirtual = EntityOps.IsVirtual(localVariable);

                        if (wantVirtual || !isVirtual)
                        {
                            //
                            // NOTE: Do they want us to verify that the
                            //       variable does NOT contain a link
                            //       index (i.e. is it an upvar link to
                            //       an array element)?
                            //
                            bool noLinkIndex = FlagOps.HasFlags(
                                variableFlags, VariableFlags.NoLinkIndex, true);

                            bool hasLinkIndex = (localVariable != null) &&
                                (localVariable.LinkIndex != null);

                            if (!noLinkIndex || !hasLinkIndex)
                            {
                                //
                                // NOTE: Now, see if they require that this
                                //       be an array variable (or not).
                                //
                                bool wantArray = !FlagOps.HasFlags(variableFlags,
                                        VariableFlags.NoGetArray, true) &&
                                    FlagOps.HasFlags(variableFlags,
                                        VariableFlags.Array, true);

                                bool wantNoArray = !FlagOps.HasFlags(variableFlags,
                                        VariableFlags.NoGetArray, true) &&
                                    FlagOps.HasFlags(variableFlags,
                                        VariableFlags.NoArray, true);

                                bool isArray = EntityOps.IsArray2(localVariable);

                                if ((!wantArray && !wantNoArray) ||
                                    (wantArray && isArray) ||
                                    (wantNoArray && !isArray))
                                {
                                    variable = localVariable;

                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't get {0}: variable {1} array",
                                        FormatOps.ErrorVariableName(varName, null),
                                        isArray ? "is" : "isn't");
                                }
                            }
                            else
                            {
                                //
                                // NOTE: The variable has a link index (to an array
                                //       element) and according to the caller, it
                                //       should not.
                                //
                                variableFlags |= VariableFlags.HasLinkIndex;

                                error = String.Format(
                                    "can't get {0}: variable is array element link",
                                    FormatOps.ErrorVariableName(varName, null));
                            }
                        }
                        else
                        {
                            //
                            // NOTE: The variable is virtual and according to the
                            //       caller, it should not be.
                            //
                            variableFlags |= VariableFlags.WasVirtual;

                            error = String.Format(
                                "can't get {0}: variable is virtual",
                                FormatOps.ErrorVariableName(varName, null));
                        }
                    }
                    else
                    {
                        //
                        // BUGFIX: If the variable is undefined, we must set
                        //         the "NotFound" flag because an undefined
                        //         variable should be treated just like one
                        //         that is physically missing from the call
                        //         frame.
                        //
                        if (isUndefined)
                            variableFlags |= VariableFlags.NotFound;

                        //
                        // HACK: This is on the "hot path" for WaitVariable on
                        //       variables that do not yet exist; therefore, do
                        //       not use String.Format here.
                        //
                        // BUGBUG: Just how slow is String.Format and why?
                        //
                        // error = String.Format(
                        //     "can't get {0}: variable {1} defined",
                        //     FormatOps.ErrorVariableName(varName, null),
                        //     isUndefined ? "isn't" : "is");
                        //
                        error = isUndefined ?
                            "variable isn't defined" : "variable is defined";
                    }
                }
                else
                {
                    //
                    // NOTE: The variable does not exist in the call frame,
                    //       set the "NotFound" flag.
                    //
                    variableFlags |= VariableFlags.NotFound;

                    //
                    // HACK: This is on the "hot path" for WaitVariable on
                    //       variables that do not yet exist; therefore, do
                    //       not use String.Format here.
                    //
                    // BUGBUG: Just how slow is String.Format and why?
                    //
                    // error = String.Format(
                    //     "variable {0} not found in call frame \"{1}\"",
                    //     FormatOps.ErrorVariableName(varName, null),
                    //     variableFrame);
                    //
                    error = "variable not found in call frame";
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DoesVariableExist(
            VariableFlags flags,
            string name,
            ref IVariable variable
            )
        {
            bool badRequest = false;
            Result error = null;

            return DoesVariableExist(
                flags, null, name, ref variable, ref badRequest, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DoesVariableExist(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            ref bool badRequest,
            ref Result error
            )
        {
            IVariable variable = null;

            return DoesVariableExist(
                flags, frame, name, ref variable, ref badRequest, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DoesVariableExist(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            ref IVariable variable,
            ref bool badRequest,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                string varName = null;
                string varIndex = null;

                if (ScriptOps.SplitVariableName(
                        this, flags, name, ref varName,
                        ref varIndex, ref error) == ReturnCode.Ok)
                {
                    variable = null;

                    if (GetVariableViaResolversWithSplit(
                            frame, varName, ref flags, ref variable,
                            ref error) == ReturnCode.Ok)
                    {
                        //
                        // NOTE: For linked variables, we may be linking to an array
                        //       element.
                        //
                        string linkIndex = null;

                        if (EntityOps.IsLink(variable))
                        {
                            //
                            // NOTE: Get the array element index of the link, if any.
                            //
                            linkIndex = variable.LinkIndex;

                            //
                            // NOTE: Follow the linked variable.
                            //
                            variable = EntityOps.FollowLinks(variable, flags);
                        }

                        //
                        // NOTE: If they specified the NoElement flag, then make sure
                        //       the linked variable does not refer to an array element.
                        //
                        if ((linkIndex == null) ||
                            !FlagOps.HasFlags(flags, VariableFlags.NoElement, true))
                        {
                            badRequest = false; // var name searched OK and found OK.

                            //
                            // BUGFIX: Null and undefined variables do not "exist".
                            //
                            if ((variable != null) &&
                                !EntityOps.IsUndefined(variable))
                            {
                                //
                                // NOTE: Are they requesting an array, directly or
                                //       indirectly (i.e. indirectly if the specified
                                //       variable name or variable link contains an
                                //       element index and they did not specify the
                                //       NoElement flag)?
                                //
                                if (FlagOps.HasFlags(flags, VariableFlags.Array, true) ||
                                    (varIndex != null) || (linkIndex != null))
                                {
                                    //
                                    // NOTE: Is the variable an array?
                                    //
                                    if (EntityOps.IsArray2(variable) &&
                                        ((varIndex == null) || (linkIndex == null)))
                                    {
                                        if ((varIndex != null) || (linkIndex != null))
                                        {
                                            //
                                            // NOTE: If there was no element index specified,
                                            //       use the one from the variable link.
                                            //
                                            if (varIndex == null)
                                                varIndex = linkIndex;

                                            //
                                            // HACK: Handle the global "env" array specially.
                                            //       We must do this because our global "env"
                                            //       array has no backing storage (unlike Tcl's)
                                            //       and we do not have a trace operation for
                                            //       "exists".
                                            //
                                            ElementDictionary arrayValue = variable.ArrayValue;

                                            if ((IsEnvironmentVariable(variable) &&
                                                    CommonOps.Environment.DoesVariableExist(varIndex)) ||
                                                ((arrayValue != null) && arrayValue.ContainsKey(varIndex)))
                                            {
                                                return ReturnCode.Ok;
                                            }
                                            else if ((IsTestsVariable(variable) &&
                                                    DoesTestsVariableExist(varIndex)) ||
                                                ((arrayValue != null) && arrayValue.ContainsKey(varIndex)))
                                            {
                                                return ReturnCode.Ok;
                                            }
                                            else if ((IsSystemArrayVariable(variable) &&
                                                    MarshalOps.DoesArrayElementExist(
                                                        binder, cultureInfo, variable, varIndex)) ||
                                                ((arrayValue != null) && arrayValue.ContainsKey(varIndex)))
                                            {
                                                return ReturnCode.Ok;
                                            }
                                            else
                                            {
#if DATA
                                                DatabaseVariable databaseVariable = null;

                                                if ((IsDatabaseVariable(variable, ref databaseVariable) &&
                                                        databaseVariable.DoesExist(this, varIndex)) ||
                                                    ((arrayValue != null) && arrayValue.ContainsKey(varIndex)))
                                                {
                                                    return ReturnCode.Ok;
                                                }
                                                else
#endif
                                                {
                                                    error = String.Format(
                                                        "can't verify {0}: no such element in array",
                                                        FormatOps.ErrorVariableName(
                                                            variable, linkIndex, varName, varIndex));
                                                }
                                            }
                                        }
                                        else
                                        {
                                            //
                                            // NOTE: The variable is an array and we did not want to
                                            //       validate any actual element.
                                            //
                                            return ReturnCode.Ok;
                                        }
                                    }
                                    else
                                    {
                                        error = String.Format(
                                            "can't verify {0}: variable isn't array",
                                            FormatOps.ErrorVariableName(
                                                variable, linkIndex, varName, varIndex));
                                    }
                                }
                                else if (FlagOps.HasFlags(flags, VariableFlags.NoArray, true))
                                {
                                    if (EntityOps.IsArray2(variable))
                                    {
                                        //
                                        // NOTE: They requested verification of a scalar variable and
                                        //       the variable is actually an array, this is an error.
                                        //
                                        error = String.Format(
                                            "can't verify {0}: variable is array",
                                            FormatOps.ErrorVariableName(
                                                variable, linkIndex, varName, varIndex));
                                    }
                                    else
                                    {
                                        if (varIndex != null)
                                        {
                                            //
                                            // NOTE: This is somewhat confusing.  They requested
                                            //       verification of a scalar variable; however,
                                            //       they supplied an array element index for a
                                            //       non-array variable?
                                            //
                                            error = String.Format(
                                                "can't verify {0}: variable isn't array",
                                                FormatOps.ErrorVariableName(
                                                    variable, linkIndex, varName, varIndex));
                                        }
                                        else
                                        {
                                            //
                                            // NOTE: They requested verification of a scalar variable
                                            //       and [correctly] did not supply an element index,
                                            //       everything is ok.
                                            //
                                            return ReturnCode.Ok;
                                        }
                                    }
                                }
                                else
                                {
                                    //
                                    // NOTE: No special flags were set and they did not specify an
                                    //       element index.
                                    //
                                    return ReturnCode.Ok;
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't verify {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, varName, varIndex));
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Bad request, they wanted to validate that the
                            //       variable does not refer to an array element
                            //       and the linked variable does.  Indicate this
                            //       special condition to the caller.
                            //
                            badRequest = true; // var name NOT searched OK.

                            //
                            // NOTE: Provide an informative error message.
                            //
                            error = "name refers to an element in an array";
                        }
                    }
                    else
                    {
                        //
                        // NOTE: If we did not actually search for the variable
                        //       (due to the internal calls to parse the variable
                        //       name failing, etc), we do not want to pretend that
                        //       the variable was simply not found.
                        //
                        if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                            badRequest = false; // var name searched OK and NOT found.
                        else
                            badRequest = true; // var name NOT searched OK.
                    }
                }
                else
                {
                    //
                    // NOTE: Bad variable name could not be parsed.
                    //       Indicate this special condition to the
                    //       caller.
                    //
                    badRequest = true; // var name NOT searched OK.
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasNoPostProcess()
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.NoPostProcess, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PostProcessVariableValue(
            VariableFlags flags,
            string name,
            string index,
            IVariable variable,
            object oldValue,
            ref Result value,
            ref Result error
            )
        {
            //
            // NOTE: Do we need to post-process this variable value at all
            //       prior to returning it?
            //
            if (EntityOps.IsSubstitute(variable) ||
                EntityOps.IsEvaluate(variable))
            {
                Result result = null;

                //
                // NOTE: Do we need to post-process the variable value by
                //       processing substitutions contained within it?
                //
                if (EntityOps.IsSubstitute(variable))
                {
                    if (SubstituteString(
                            StringOps.GetStringFromObject(oldValue),
                            ref result) != ReturnCode.Ok)
                    {
                        error = result;
                        return ReturnCode.Error;
                    }

                    oldValue = result;
                }

                //
                // NOTE: Do we need to post-process the variable value by
                //       evaluating it as a script?
                //
                if (EntityOps.IsEvaluate(variable))
                {
                    if (EvaluateScript(
                            StringOps.GetStringFromObject(oldValue),
                            ref result) != ReturnCode.Ok) /* EXEMPT */
                    {
                        error = result;
                        return ReturnCode.Error;
                    }

                    oldValue = result;
                }
            }

            //
            // NOTE: If post-processing was skipped or we were
            //       successful, signal success and return.
            //
            if (!FlagOps.HasFlags(flags, VariableFlags.SkipToString, true))
            {
                value = StringOps.GetStringFromObject(oldValue);
            }
            else
            {
                value = Result.FromObject(
                    oldValue, false, false, FlagOps.HasFlags(
                    flags, VariableFlags.FallbackToString, true));
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Currently, for use by the [array] command and the
        //       FireArraySetTraces method only.
        //
        internal ReturnCode FireTraces(
            BreakpointType breakpointType,
            VariableFlags flags,
            ICallFrame frame,
            string varName,
            string varIndex,
            object newValue,
            ElementDictionary oldValues,
            ElementDictionary newValues,
            IVariable variable,
            ref Result result
            )
        {
            if (!FlagOps.HasFlags(flags, VariableFlags.NonTrace, false) &&
                !HasNoTraces() && EntityOps.HasTraces(variable) &&
                !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
            {
                object oldValue = EntityOps.GetOldValue(
                    flags, variable, varIndex,
                    ScriptOps.GetDefaultValue(breakpointType));

                ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                    this, null, breakpointType, frame, variable, varName,
                    varIndex, flags, oldValue, newValue, oldValues, newValues,
                    null, NeedNewTraceInfo(flags), false,
                    !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

                return ScriptOps.FireTraces(
                    variable, breakpointType, this, traceInfo,
                    ref result);
            }
            else
            {
                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode FireArraySetTraces( // NOTE: For use by [array] command only.
            BreakpointType breakpointType,
            VariableFlags flags,
            ICallFrame frame,
            string varName,
            string varIndex,
            object newValue,
            ElementDictionary oldValues,
            ElementDictionary newValues,
            IVariable variable,
            ref Result result
            )
        {
            ElementDictionary effectiveNewValues = new ElementDictionary(
                variableEvent, oldValues);

            foreach (KeyValuePair<string, object> pair in newValues)
                effectiveNewValues[pair.Key] = pair.Value;

            return FireTraces(
                breakpointType, flags, frame, varName, varIndex, newValue,
                oldValues, effectiveNewValues, variable, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetIntegerVariableValue( /* NOTE: For [incr] use only. */
            VariableFlags flags,
            string name,
            ref long value,
            ref Result error
            )
        {
            ReturnCode code;
            Result result = null;

            code = GetVariableValue(
                flags | VariableFlags.SkipToString, name, ref result,
                ref error);

            if (code != ReturnCode.Ok)
                return code;

            if (result != null)
            {
                if (result.Value is int)
                {
                    value = (int)result.Value;
                    return ReturnCode.Ok;
                }

                if (result.Value is long)
                {
                    value = (long)result.Value;
                    return ReturnCode.Ok;
                }
            }

            code = Value.GetWideInteger2(result, ValueFlags.AnyWideInteger,
                cultureInfo, ref value, ref error);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetIntegerVariableValue( /* NOTE: For [incr] use only. */
            VariableFlags flags,
            string name,
            long value,
            ref Result error
            )
        {
            int intValue = ConversionOps.ToInt(value);

            if (value == intValue)
            {
                IVariable variable = null;

                return SetVariableValue2(
                    flags, null, name, null, intValue, null, ref variable,
                    ref error);
            }
            else
            {
                IVariable variable = null;

                return SetVariableValue2(
                    flags, null, name, null, value, null, ref variable,
                    ref error);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetListVariableValue( /* NOTE: For [lsearch] use only. */
            VariableFlags flags,
            string name,
            bool copy,
            bool strict,
            bool cache,
            ref StringList value
            )
        {
            IVariable variable = null;
            bool cached = false;
            Result error = null;

            return GetListVariableValue(
                flags, name, copy, strict, cache, ref variable,
                ref value, ref cached, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetListVariableValue( /* NOTE: For [lappend] use only. */
            VariableFlags flags,
            string name,
            bool copy,
            bool strict,
            bool cache,
            ref StringList value,
            ref Result error
            )
        {
            IVariable variable = null;
            bool cached = false;

            return GetListVariableValue(
                flags, name, copy, strict, cache, ref variable,
                ref value, ref cached, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetListVariableValue(
            VariableFlags flags,
            string name,
            bool copy,
            bool strict,
            bool cache,
            ref IVariable variable,
            ref StringList value,
            ref bool cached,
            ref Result error
            )
        {
            ReturnCode code;

            lock (syncRoot) /* TRANSACTIONAL */
            {
                flags |= VariableFlags.SkipToString;

                string varIndex = null;
                Result localValue = null;
                Result localError = null;

                code = GetVariableValue(
                    flags, name, ref varIndex, ref variable, ref localValue,
                    ref localError);

                if (code == ReturnCode.Ok)
                {
                    object oldValue = !EntityOps.IsVirtualOrSystem(variable) ?
                        EntityOps.GetOldValue(flags, variable, varIndex, null) :
                        StringOps.GetStringFromObject(localValue);

                    if (oldValue is StringList)
                    {
                        if (copy)
                            value = new StringList((StringList)oldValue);
                        else
                            value = (StringList)oldValue;

                        cached = true;
                    }
                    else if (!strict)
                    {
                        if (oldValue != null)
                        {
                            code = Parser.SplitList(
                                this, StringOps.GetStringFromObject(oldValue),
                                0, Length.Invalid, cache, ref value, ref error);

                            if (code == ReturnCode.Ok)
                                cached = false;
                        }
                        else
                        {
                            value = new StringList();
                            cached = false;
                        }
                    }
                    else
                    {
                        error = "variable value is not a list";
                        code = ReturnCode.Error;
                    }
                }
                else if (!strict)
                {
                    //
                    // NOTE: The variable does not exist (or the name is
                    //       invalid, etc).  Return an empty list and let
                    //       the caller deal with it.  For [lappend], if
                    //       the name is invalid, the subsequent call to
                    //       SetVariableValue will fail, that's alright.
                    //
                    value = new StringList();
                    cached = false;

                    code = ReturnCode.Ok;
                }
                else
                {
                    error = localError;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue(
            VariableFlags flags,
            string name,
            ref Result value
            )
        {
            IVariable variable = null;
            Result error = null;

            return GetVariableValue2(
                flags, name, null, ref variable, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetVariableValue( /* NOTE: For use by GetListVariableValue only. */
            VariableFlags flags,
            string name,
            ref string varIndex,
            ref IVariable variable,
            ref Result value,
            ref Result error
            )
        {
            string varName = null;

            if (ScriptOps.SplitVariableName(
                    this, flags, name, ref varName,
                    ref varIndex, ref error) == ReturnCode.Ok)
            {
                return GetVariableValue2(
                    flags, varName, varIndex, ref variable,
                    ref value, ref error);
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            ref Result value
            )
        {
            Result error = null;

            return GetVariableValue2(flags, name, index, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            ref Result value,
            ref Result error
            )
        {
            IVariable variable = null;

            return GetVariableValue2(
                flags, name, index, ref variable, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            ref Result value,
            ref Result error
            )
        {
            IVariable variable = null;

            return GetVariableValue2(
                flags, frame, name, index, ref variable, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            ref IVariable variable,
            ref Result value,
            ref Result error
            )
        {
            return GetVariableValue2(
                flags, null, name, index, ref variable, ref value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetVariableValue2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            ref IVariable variable,
            ref Result value,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                bool haveVariable = (variable != null);

                if ((haveVariable ||
                    (GetVariableViaResolversWithSplit(frame, name, index, ref flags,
                        ref variable, ref error) == ReturnCode.Ok)) &&
                    !EntityOps.IsUndefined(variable, "read", name, index, ref error))
                {
                    //
                    // COMPAT: Tcl, if the index was specified, make sure the name
                    //         itself does not contain an array element reference.
                    //
                    if (haveVariable || (index == null))
                    {
                        VariableFlags splitFlags = flags;
                        string splitIndex = null;

                        if (index != null)
                            splitFlags |= VariableFlags.NoElement;

                        if (ScriptOps.SplitVariableName(
                                this, splitFlags, name, ref name,
                                ref splitIndex, ref error) == ReturnCode.Ok)
                        {
                            if ((index == null) && (splitIndex != null))
                                index = splitIndex;
                        }
                        else
                        {
                            return ReturnCode.Error;
                        }
                    }

                    //
                    // NOTE: Make sure we have a variable.
                    //
                    if (variable == null)
                    {
                        error = String.Format(
                            "can't read {0}: variable is invalid",
                            FormatOps.ErrorVariableName(name, index));

                        return ReturnCode.Error;
                    }

                    //
                    // NOTE: For linked variables, we may be linking to an array
                    //       element.
                    //
                    string linkIndex = null;

                    //
                    // NOTE: Save original call frame for traces.
                    //
                    ICallFrame savedFrame = variable.Frame;

                    //
                    // NOTE: Is the variable really a link to another variable?
                    //
                    if (EntityOps.IsLink(variable))
                    {
                        //
                        // NOTE: Get the array element index of the link, if any.
                        //
                        linkIndex = variable.LinkIndex;

                        //
                        // NOTE: Follow the linked variable.
                        //
                        variable = EntityOps.FollowLinks(variable, flags);
                    }

                    if (!EntityOps.IsUndefined(variable))
                    {
                        if ((index != null) || (linkIndex != null))
                        {
                            if (EntityOps.IsArray2(variable) &&
                                ((index == null) || (linkIndex == null)))
                            {
                                //
                                // NOTE: If there was no element index specified, use
                                //       the one from the variable link.
                                //
                                if (index == null)
                                    index = linkIndex;

                                if (!EntityOps.IsWriteOnly(variable))
                                {
                                    ElementDictionary arrayValue = variable.ArrayValue;

                                    if ((arrayValue != null) && arrayValue.ContainsKey(index))
                                    {
                                        object oldValue = EntityOps.GetOldValue(
                                            flags, variable, index, ScriptOps.GetDefaultValue(
                                                BreakpointType.BeforeVariableGet));

                                        ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                            this, null, BreakpointType.BeforeVariableGet, savedFrame,
                                            variable, name, index, flags, oldValue, null, null, null,
                                            null, NeedNewTraceInfo(flags), false,
                                            !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                            CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                            EntityOps.IsBreakOnGet(variable))
                                        {
                                            //
                                            // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                            //       get access for this variable.
                                            //
                                            Result localResult = null;

                                            if (CheckWatchpoints(
                                                    ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                    traceInfo, ref localResult) != ReturnCode.Ok)
                                            {
                                                error = localResult;
                                                return ReturnCode.Error;
                                            }
                                        }
#endif

                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                            !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                            !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                        {
                                            try
                                            {
                                                if (ScriptOps.FireTraces(
                                                        variable, traceInfo.BreakpointType, this, traceInfo,
                                                        ref value, ref error) != ReturnCode.Ok)
                                                {
                                                    return ReturnCode.Error;
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                error = String.Format(
                                                    "caught exception while firing variable traces: {0}",
                                                    e);

                                                return ReturnCode.Error;
                                            }
                                        }

#if NOTIFY
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                            !EntityOps.IsNoNotify(variable))
                                        {
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.Variable, NotifyFlags.Trace,
                                                new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                this, null, null, null, ref error);
                                        }
#endif

                                        //
                                        // NOTE: If the trace(s) did not cancel the operation, proceed.
                                        //
                                        if (!traceInfo.Cancel)
                                        {
                                            //
                                            // NOTE: Check for post-processing of the variable value.
                                            //
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonPostProcess, false) &&
                                                traceInfo.PostProcess && !HasNoPostProcess())
                                            {
                                                if (PostProcessVariableValue(
                                                        traceInfo.Flags, name, traceInfo.Index, variable,
                                                        traceInfo.OldValue, ref value, ref error) != ReturnCode.Ok)
                                                {
                                                    return ReturnCode.Error;
                                                }
                                            }
                                            else
                                            {
                                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.SkipToString, true))
                                                {
                                                    value = StringOps.GetStringFromObject(traceInfo.OldValue);
                                                }
                                                else
                                                {
                                                    value = Result.FromObject(
                                                        traceInfo.OldValue, false, false, FlagOps.HasFlags(
                                                        traceInfo.Flags, VariableFlags.FallbackToString, true));
                                                }
                                            }
                                        }

                                        return traceInfo.ReturnCode;
                                    }
                                    else
                                    {
                                        ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                            this, null, BreakpointType.BeforeVariableGet, savedFrame,
                                            variable, name, index, flags, null, null, null, null,
                                            null, NeedNewTraceInfo(flags), false,
                                            !EntityOps.IsNoPostProcess(variable), ReturnCode.Error);

#if DEBUGGER && DEBUGGER_VARIABLE
                                        if (CanHitWatchpoints() &&
                                            EntityOps.IsBreakOnGet(variable))
                                        {
                                            //
                                            // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                            //       get access for this variable.
                                            //
                                            Result localResult = null;

                                            if (CheckWatchpoints(
                                                    ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                    traceInfo, ref localResult) != ReturnCode.Ok)
                                            {
                                                error = localResult;
                                                return ReturnCode.Error;
                                            }
                                        }
#endif

                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                            !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                            !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                        {
                                            try
                                            {
                                                if (ScriptOps.FireTraces(
                                                        variable, traceInfo.BreakpointType, this, traceInfo,
                                                        ref value, ref error) != ReturnCode.Ok)
                                                {
                                                    return ReturnCode.Error;
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                error = String.Format(
                                                    "caught exception while firing variable traces: {0}",
                                                    e);

                                                return ReturnCode.Error;
                                            }
                                        }

#if NOTIFY
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                            !EntityOps.IsNoNotify(variable))
                                        {
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.Variable, NotifyFlags.Trace,
                                                new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                this, null, null, null, ref error);
                                        }
#endif

                                        //
                                        // NOTE: If the trace(s) did not cancel the operation, proceed
                                        //       with producing an appropriate error message.  Otherwise,
                                        //       if a trace callback canceled the operation with a
                                        //       successful return code (i.e. not the original error
                                        //       return code) then post-process the variable value (if
                                        //       required) and return.
                                        //
                                        if (traceInfo.Cancel)
                                        {
                                            if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            {
                                                //
                                                // NOTE: Check for post-processing of the variable value.
                                                //
                                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonPostProcess, false) &&
                                                    traceInfo.PostProcess && !HasNoPostProcess())
                                                {
                                                    if (PostProcessVariableValue(
                                                            traceInfo.Flags, name, traceInfo.Index, variable,
                                                            traceInfo.OldValue, ref value, ref error) != ReturnCode.Ok)
                                                    {
                                                        return ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.SkipToString, true))
                                                    {
                                                        value = StringOps.GetStringFromObject(traceInfo.OldValue);
                                                    }
                                                    else
                                                    {
                                                        value = Result.FromObject(
                                                            traceInfo.OldValue, false, false, FlagOps.HasFlags(
                                                            traceInfo.Flags, VariableFlags.FallbackToString, true));
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            error = String.Format(
                                                "can't read {0}: no such element in array",
                                                FormatOps.ErrorVariableName(
                                                    variable, linkIndex, name, traceInfo.Index));
                                        }

                                        return traceInfo.ReturnCode;
                                    }
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't read {0}: variable is write-only",
                                        FormatOps.ErrorVariableName(
                                            variable, linkIndex, name, index));
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't read {0}: variable isn't array",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, index));
                            }
                        }
                        else
                        {
                            if (!EntityOps.IsArray2(variable))
                            {
                                if (!EntityOps.IsWriteOnly(variable))
                                {
                                    object oldValue = (variable.Value != null) ?
                                        variable.Value : ScriptOps.GetDefaultValue(
                                            BreakpointType.BeforeVariableGet);

                                    ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                        this, null, BreakpointType.BeforeVariableGet, savedFrame,
                                        variable, name, index, flags, oldValue, null, null,
                                        null, null, NeedNewTraceInfo(flags), false,
                                        !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                        CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                        EntityOps.IsBreakOnGet(variable))
                                    {
                                        //
                                        // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                        //       get access for this variable.
                                        //
                                        Result localResult = null;

                                        if (CheckWatchpoints(
                                                ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                traceInfo, ref localResult) != ReturnCode.Ok)
                                        {
                                            error = localResult;
                                            return ReturnCode.Error;
                                        }
                                    }
#endif

                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                        !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                        !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                    {
                                        try
                                        {
                                            if (ScriptOps.FireTraces(
                                                    variable, traceInfo.BreakpointType, this, traceInfo,
                                                    ref value, ref error) != ReturnCode.Ok)
                                            {
                                                return ReturnCode.Error;
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            error = String.Format(
                                                "caught exception while firing variable traces: {0}",
                                                e);

                                            return ReturnCode.Error;
                                        }
                                    }

#if NOTIFY
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                        !EntityOps.IsNoNotify(variable))
                                    {
                                        /* IGNORED */
                                        CheckNotifications(
                                            NotifyType.Variable, NotifyFlags.Trace,
                                            new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                            this, null, null, null, ref error);
                                    }
#endif

                                    //
                                    // NOTE: If the trace(s) did not cancel the operation, proceed.
                                    //
                                    if (!traceInfo.Cancel)
                                    {
                                        //
                                        // NOTE: Check for post-processing of the variable value.
                                        //
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonPostProcess, false) &&
                                            traceInfo.PostProcess && !HasNoPostProcess())
                                        {
                                            if (PostProcessVariableValue(
                                                    traceInfo.Flags, name, traceInfo.Index, variable,
                                                    traceInfo.OldValue, ref value, ref error) != ReturnCode.Ok)
                                            {
                                                return ReturnCode.Error;
                                            }
                                        }
                                        else
                                        {
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.SkipToString, true))
                                            {
                                                value = StringOps.GetStringFromObject(traceInfo.OldValue);
                                            }
                                            else
                                            {
                                                value = Result.FromObject(
                                                    traceInfo.OldValue, false, false, FlagOps.HasFlags(
                                                    traceInfo.Flags, VariableFlags.FallbackToString, true));
                                            }
                                        }
                                    }

                                    return traceInfo.ReturnCode;
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't read {0}: variable is write-only",
                                        FormatOps.ErrorVariableName(name, null));
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't read {0}: variable is array",
                                    FormatOps.ErrorVariableName(name, null));
                            }
                        }
                    }
                    else
                    {
                        if (!EntityOps.IsWriteOnly(variable))
                        {
                            ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                this, null, BreakpointType.BeforeVariableGet, savedFrame,
                                variable, name, index, flags, null, null, null,
                                null, null, NeedNewTraceInfo(flags), false,
                                !EntityOps.IsNoPostProcess(variable), ReturnCode.Error);

#if DEBUGGER && DEBUGGER_VARIABLE
                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                EntityOps.IsBreakOnGet(variable))
                            {
                                //
                                // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                //       get access for this variable.
                                //
                                Result localResult = null;

                                if (CheckWatchpoints(
                                        ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                        traceInfo, ref localResult) != ReturnCode.Ok)
                                {
                                    error = localResult;
                                    return ReturnCode.Error;
                                }
                            }
#endif

                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                            {
                                try
                                {
                                    if (ScriptOps.FireTraces(
                                            variable, traceInfo.BreakpointType, this, traceInfo,
                                            ref value, ref error) != ReturnCode.Ok)
                                    {
                                        return ReturnCode.Error;
                                    }
                                }
                                catch (Exception e)
                                {
                                    error = String.Format(
                                        "caught exception while firing variable traces: {0}",
                                        e);

                                    return ReturnCode.Error;
                                }
                            }

#if NOTIFY
                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                !EntityOps.IsNoNotify(variable))
                            {
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Variable, NotifyFlags.Trace,
                                    new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                    this, null, null, null, ref error);
                            }
#endif

                            //
                            // NOTE: If the trace(s) did not cancel the operation, proceed
                            //       with producing an appropriate error message.  Otherwise,
                            //       if a trace callback canceled the operation with a
                            //       successful return code (i.e. not the original error
                            //       return code) then post-process the variable value (if
                            //       required) and return.
                            //
                            if (traceInfo.Cancel)
                            {
                                if (traceInfo.ReturnCode == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Check for post-processing of the variable value.
                                    //
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonPostProcess, false) &&
                                        traceInfo.PostProcess && !HasNoPostProcess())
                                    {
                                        if (PostProcessVariableValue(
                                                traceInfo.Flags, name, traceInfo.Index, variable,
                                                traceInfo.OldValue, ref value, ref error) != ReturnCode.Ok)
                                        {
                                            return ReturnCode.Error;
                                        }
                                    }
                                    else
                                    {
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.SkipToString, true))
                                        {
                                            value = StringOps.GetStringFromObject(traceInfo.OldValue);
                                        }
                                        else
                                        {
                                            value = Result.FromObject(
                                                traceInfo.OldValue, false, false, FlagOps.HasFlags(
                                                traceInfo.Flags, VariableFlags.FallbackToString, true));
                                        }
                                    }
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't read {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, traceInfo.Index));
                            }

                            return traceInfo.ReturnCode;
                        }
                        else
                        {
                            error = String.Format(
                                "can't read {0}: variable is write-only",
                                FormatOps.ErrorVariableName(name, null));
                        }
                    }
                }
                else if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                {
                    error = String.Format(
                        "can't read {0}: no such variable",
                        FormatOps.ErrorVariableName(
                            variable, null, name, index));
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddLibraryVariable(
            VariableFlags flags,
            string name,
            TraceList traces,
            bool strict,
            ref Result error
            )
        {
            flags |= VariableFlags.Library;
            return AddVariable(flags, name, traces, strict, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddVariable2(
            VariableFlags flags,
            string name,
            TraceList traces,
            bool strict,
            ref IVariable variable,
            ref Result error
            )
        {
            return AddVariable2(flags, null, name, traces, strict, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddVariable2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            TraceList traces,
            bool strict,
            ref IVariable variable,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!readOnly || FlagOps.HasFlags(flags, VariableFlags.ReadOnlyMask, false))
                {
                    bool badRequest = false;
                    Result localError = null;

                    if (DoesVariableExist(flags, frame, name, ref badRequest, ref localError) != ReturnCode.Ok)
                    {
                        if (!badRequest)
                        {
                            ICallFrame variableFrame = frame;
                            string newName = name;

                            if (GetVariableFrameViaResolvers(
                                    LookupFlags.Default, ref variableFrame, ref newName,
                                    ref flags, ref error) != ReturnCode.Ok)
                            {
                                return ReturnCode.Error;
                            }

                            if (variableFrame == null)
                            {
                                error = "invalid call frame from resolver";
                                return ReturnCode.Error;
                            }

                            bool isGlobalCallFrame = IsGlobalCallFrame(variableFrame);

                            variable = new Variable(variableFrame, newName,
                                (flags & ~VariableFlags.NonAddMask) |
                                GetNewVariableFlags(isGlobalCallFrame),
                                GetTraces(traces), variableEvent);

                            if (isGlobalCallFrame)
                                EntityOps.SetGlobal(variable, true);
                            else
                                EntityOps.SetLocal(variable, true);

                            ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                this, null, BreakpointType.BeforeVariableAdd, variableFrame,
                                variable, name, null, flags, null, null, null,
                                null, null, NeedNewTraceInfo(flags), false,
                                !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                EntityOps.IsBreakOnSet(variable))
                            {
                                //
                                // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                //       set access for this variable.
                                //
                                Result localResult = null;

                                if (CheckWatchpoints(
                                        ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                        traceInfo, ref localResult) != ReturnCode.Ok)
                                {
                                    error = localResult;
                                    return ReturnCode.Error;
                                }
                            }
#endif

                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                            {
                                try
                                {
                                    if (ScriptOps.FireTraces(
                                            variable, traceInfo.BreakpointType, this, traceInfo,
                                            ref error) != ReturnCode.Ok)
                                    {
                                        return ReturnCode.Error;
                                    }
                                }
                                catch (Exception e)
                                {
                                    error = String.Format(
                                        "caught exception while firing variable traces: {0}",
                                        e);

                                    return ReturnCode.Error;
                                }
                            }

#if NOTIFY
                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                !EntityOps.IsNoNotify(variable))
                            {
                                /* IGNORED */
                                CheckNotifications(
                                    NotifyType.Variable, NotifyFlags.Trace,
                                    new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                    this, null, null, null, ref error);
                            }
#endif

                            //
                            // NOTE: If the trace(s) did not cancel the operation, proceed.
                            //
                            if (!traceInfo.Cancel)
                            {
                                //
                                // NOTE: All arrays (even virtual ones) must have a valid
                                //       dictionary for their elements.
                                //
                                if (EntityOps.IsArray2(variable))
                                {
                                    variable.Value = null;
                                    variable.ArrayValue = new ElementDictionary(variableEvent);
                                }

                                //
                                // BUGFIX: If the variable name exists in the call frame at
                                //         this point it is most likely a zombie (i.e.
                                //         undefined); therefore, replace it if necessary.
                                //
                                VariableDictionary variables = variableFrame.Variables;

                                //
                                // NOTE: Add or replace variable in current call frame.
                                //
                                variables[newName] = variable;

                                //
                                // BUGFIX: Mark the variable as "dirty" AFTER the
                                //         actual modifications have been completed.
                                //
                                EntityOps.SetDirty(variable, true);
                            }

                            return traceInfo.ReturnCode;
                        }
                        else
                        {
                            error = localError;
                        }
                    }
                    else if (strict)
                    {
                        error = String.Format(
                            "can't add {0}: variable already exists",
                            FormatOps.ErrorVariableName(name, null));
                    }
                    else
                    {
                        //
                        // NOTE: Variable already exists (non-strict) mode.
                        //
                        return ReturnCode.Ok;
                    }
                }
                else
                {
                    error = String.Format(
                        "can't add {0}: interpreter is read-only",
                        FormatOps.ErrorVariableName(name, null));
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ResetVariable2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            IVariable variable,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (immutable && !FlagOps.HasFlags(flags, VariableFlags.ImmutableMask, false))
                {
                    error = String.Format(
                        "can't reset {0}: interpreter is immutable",
                        FormatOps.ErrorVariableName(name, index));

                    return ReturnCode.Error;
                }

                if (!readOnly || FlagOps.HasFlags(flags, VariableFlags.ReadOnlyMask, false))
                {
                    //
                    // BUGBUG: This may need revision; we do need some way to remove
                    //         "stale" undefined variables from the call frame even
                    //         though the only way to officially create one is via the
                    //         global or upvar commands and those get cleaned up
                    //         automatically upon procedure exit.
                    //
                    bool haveVariable = (variable != null);
                    Result localError = null;

                    if ((haveVariable ||
                        (GetVariableViaResolversWithSplit(frame, name, index, ref flags,
                            ref variable, ref localError) == ReturnCode.Ok)) &&
                        !EntityOps.IsUndefined(variable, "reset", name, index,
                            ref localError))
                    {
                        //
                        // COMPAT: Tcl, if the index was specified, make sure the name
                        //         itself does not contain an array element reference.
                        //
                        if (haveVariable || (index == null))
                        {
                            VariableFlags splitFlags = flags;
                            string splitIndex = null;

                            if (index != null)
                                splitFlags |= VariableFlags.NoElement;

                            if (ScriptOps.SplitVariableName(
                                    this, splitFlags, name, ref name,
                                    ref splitIndex, ref error) == ReturnCode.Ok)
                            {
                                if ((index == null) && (splitIndex != null))
                                    index = splitIndex;
                            }
                            else
                            {
                                return ReturnCode.Error;
                            }
                        }

                        //
                        // NOTE: Make sure we have a variable.
                        //
                        if (variable == null)
                        {
                            error = String.Format(
                                "can't reset {0}: variable is invalid",
                                FormatOps.ErrorVariableName(name, index));

                            return ReturnCode.Error;
                        }

                        //
                        // NOTE: For linked variables, we may be linking to an array
                        //       element.
                        //
                        string linkIndex = null;

                        //
                        // NOTE: Save original call frame for traces.
                        //
                        ICallFrame savedFrame = variable.Frame;

                        //
                        // NOTE: Is the variable really a link to another variable?
                        //
                        if (EntityOps.IsLink(variable))
                        {
                            //
                            // NOTE: Get the array element index of the link, if any.
                            //
                            linkIndex = variable.LinkIndex;

                            //
                            // NOTE: Follow the linked variable.
                            //
                            variable = EntityOps.FollowLinks(variable, flags);
                        }

                        if ((index != null) || (linkIndex != null))
                        {
                            if (EntityOps.IsArray2(variable) &&
                                    ((index == null) || (linkIndex == null)))
                            {
                                //
                                // NOTE: If there was no element index specified, use
                                //       the one from the variable link.
                                //
                                if (index == null)
                                    index = linkIndex;

                                if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                                {
                                    ElementDictionary arrayValue = variable.ArrayValue;

                                    if ((arrayValue != null) && arrayValue.ContainsKey(index))
                                    {
                                        object oldValue = EntityOps.GetOldValue(
                                            flags, variable, index, ScriptOps.GetDefaultValue(
                                                BreakpointType.BeforeVariableSet));

                                        object newValue = EntityOps.GetNewValue(
                                            flags, variable.Name, index, oldValue, null);

                                        ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                            this, null, BreakpointType.BeforeVariableReset, savedFrame,
                                            variable, name, index, flags, oldValue, newValue, null,
                                            null, null, NeedNewTraceInfo(flags), false,
                                            !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                            CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                            EntityOps.IsBreakOnSet(variable))
                                        {
                                            //
                                            // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                            //       set access for this variable.
                                            //
                                            Result localResult = null;

                                            if (CheckWatchpoints(
                                                    ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                    traceInfo, ref localResult) != ReturnCode.Ok)
                                            {
                                                error = localResult;
                                                return ReturnCode.Error;
                                            }
                                        }
#endif

                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                            !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                            !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                        {
                                            try
                                            {
                                                if (ScriptOps.FireTraces(
                                                        variable, traceInfo.BreakpointType, this, traceInfo,
                                                        ref error) != ReturnCode.Ok)
                                                {
                                                    return ReturnCode.Error;
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                error = String.Format(
                                                    "caught exception while firing variable traces: {0}",
                                                    e);

                                                return ReturnCode.Error;
                                            }
                                        }

#if NOTIFY
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                            !EntityOps.IsNoNotify(variable))
                                        {
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.Variable, NotifyFlags.Trace,
                                                new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                this, null, null, null, ref error);
                                        }
#endif

                                        //
                                        // NOTE: If the trace(s) did not cancel the operation, proceed.
                                        //
                                        if (!traceInfo.Cancel)
                                        {
                                            arrayValue = variable.ArrayValue; /* REFRESH */

                                            if (arrayValue != null)
                                            {
                                                arrayValue[index] = traceInfo.NewValue;

                                                //
                                                // BUGFIX: Mark the variable as "dirty" AFTER the
                                                //         actual modifications have been completed.
                                                //
                                                EntityOps.SignalDirty(variable, index);
                                            }
                                            else
                                            {
                                                error = String.Format(
                                                    "can't reset {0}: no longer an array",
                                                    FormatOps.ErrorVariableName(
                                                        variable, linkIndex, name, index));

                                                return ReturnCode.Error;
                                            }
                                        }

                                        return traceInfo.ReturnCode;
                                    }
                                    else
                                    {
                                        ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                            this, null, BreakpointType.BeforeVariableReset, savedFrame,
                                            variable, name, index, flags, null, null, null, null,
                                            null, NeedNewTraceInfo(flags), false,
                                            !EntityOps.IsNoPostProcess(variable), ReturnCode.Error);

#if DEBUGGER && DEBUGGER_VARIABLE
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                            CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                            EntityOps.IsBreakOnSet(variable))
                                        {
                                            //
                                            // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                            //       unset access for this variable.
                                            //
                                            Result localResult = null;

                                            if (CheckWatchpoints(
                                                    ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                    traceInfo, ref localResult) != ReturnCode.Ok)
                                            {
                                                error = localResult;
                                                return ReturnCode.Error;
                                            }
                                        }
#endif

                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                            !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                            !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                        {
                                            try
                                            {
                                                if (ScriptOps.FireTraces(
                                                        variable, traceInfo.BreakpointType, this, traceInfo,
                                                        ref error) != ReturnCode.Ok)
                                                {
                                                    return ReturnCode.Error;
                                                }
                                            }
                                            catch (Exception e)
                                            {
                                                error = String.Format(
                                                    "caught exception while firing variable traces: {0}",
                                                    e);

                                                return ReturnCode.Error;
                                            }
                                        }

#if NOTIFY
                                        if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                            !EntityOps.IsNoNotify(variable))
                                        {
                                            /* IGNORED */
                                            CheckNotifications(
                                                NotifyType.Variable, NotifyFlags.Trace,
                                                new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                this, null, null, null, ref error);
                                        }
#endif

                                        //
                                        // NOTE: If the trace(s) did not cancel the operation, proceed.
                                        //
                                        if (!traceInfo.Cancel)
                                        {
                                            error = String.Format(
                                                "can't reset {0}: no such element in array",
                                                FormatOps.ErrorVariableName(
                                                    variable, linkIndex, name, index));
                                        }

                                        return traceInfo.ReturnCode;
                                    }
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't reset {0}: variable is read-only",
                                        FormatOps.ErrorVariableName(
                                            variable, linkIndex, name, index));
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't reset {0}: variable isn't array",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, index));
                            }
                        }
                        else
                        {
                            if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                            {
                                object oldValue = EntityOps.GetOldValue(
                                    flags, variable, index, ScriptOps.GetDefaultValue(
                                        BreakpointType.BeforeVariableSet));

                                object newValue = EntityOps.GetNewValue(
                                    flags, variable.Name, index, oldValue, null);

                                ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                    this, null, BreakpointType.BeforeVariableReset, savedFrame,
                                    variable, name, index, flags, oldValue, newValue, null,
                                    null, null, NeedNewTraceInfo(flags), false,
                                    !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                    CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                    EntityOps.IsBreakOnSet(variable))
                                {
                                    //
                                    // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                    //       set access for this variable.
                                    //
                                    Result localResult = null;

                                    if (CheckWatchpoints(
                                            ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                            traceInfo, ref localResult) != ReturnCode.Ok)
                                    {
                                        error = localResult;
                                        return ReturnCode.Error;
                                    }
                                }
#endif

                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                    !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                    !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                {
                                    try
                                    {
                                        if (ScriptOps.FireTraces(
                                                variable, traceInfo.BreakpointType, this, traceInfo,
                                                ref error) != ReturnCode.Ok)
                                        {
                                            return ReturnCode.Error;
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        error = String.Format(
                                            "caught exception while firing variable traces: {0}",
                                            e);

                                        return ReturnCode.Error;
                                    }
                                }

#if NOTIFY
                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                    !EntityOps.IsNoNotify(variable))
                                {
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Variable, NotifyFlags.Trace,
                                        new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                        this, null, null, null, ref error);
                                }
#endif

                                //
                                // NOTE: If the trace(s) did not cancel the operation, proceed.
                                //
                                if (!traceInfo.Cancel)
                                {
                                    //
                                    // NOTE: Did the trace(s) change the variable into an array?
                                    //
                                    if (EntityOps.IsArray2(variable))
                                    {
                                        //
                                        // NOTE: Allocate space for the array name/values now.
                                        //
                                        variable.Value = null;
                                        variable.ArrayValue = new ElementDictionary(variableEvent);
                                    }
                                    //
                                    // NOTE: If the trace(s) changed the variable to be a link, we do
                                    //       not bother doing anything else to it (i.e. we assume it
                                    //       points where they want it to point).
                                    //
                                    else if (!EntityOps.IsLink(variable))
                                    {
                                        //
                                        // NOTE: Set the value to the output of the trace(s).
                                        //
                                        variable.Value = traceInfo.NewValue;
                                    }

                                    //
                                    // BUGFIX: Mark the variable as "dirty" AFTER the
                                    //         actual modifications have been completed.
                                    //
                                    EntityOps.SignalDirty(variable, null);
                                }

                                return traceInfo.ReturnCode;
                            }
                            else
                            {
                                error = String.Format(
                                    "can't reset {0}: variable is read-only",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, null));
                            }
                        }
                    }
                    else
                    {
                        if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                        {
                            if (FlagOps.HasFlags(flags, VariableFlags.NoComplain, true))
                            {
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = String.Format(
                                    "can't reset {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, null, name, index));
                            }
                        }
                        else
                        {
                            if (FlagOps.HasFlags(flags, VariableFlags.NoComplain, true))
                            {
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                //
                                // NOTE: We did not actually search for the variable,
                                //       inform the caller as to why.
                                //
                                error = localError;
                            }
                        }
                    }
                }
                else
                {
                    error = String.Format(
                        "can't reset {0}: interpreter is read-only",
                        FormatOps.ErrorVariableName(name, index));
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetVariableLink2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            MemberInfo memberInfo,
            object @object,
            ref IVariable variable,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot) /* TRANSACTIONAL */
            {
                IAnyPair<MemberInfo, object> pair =
                    new AnyPair<MemberInfo, object>(memberInfo, @object);

                if (SetVariableValue2(
                        flags, frame, name, index, pair, linkedVariableTraceList,
                        ref variable, ref error) == ReturnCode.Ok)
                {
                    if (HasLinkedVariableTraceCallback(variable))
                    {
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = String.Format(
                            "can't link {0}: could not set variable trace",
                            FormatOps.ErrorVariableName(
                                variable, null, name, index));
                    }
                }

                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetVariableSystemArray2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            Array array,
            ref IVariable variable,
            ref Result error
            )
        {
            // CheckDisposed();

            lock (syncRoot) /* TRANSACTIONAL */
            {
                //
                // NOTE: This code assumes the systemArrayTraceList field
                //       cannot be null.
                //
                TraceList traces = systemArrayTraceList;

                if (GetVariableViaResolversWithSplit(
                        frame, name, null, ref flags,
                        ref variable, ref error) == ReturnCode.Ok)
                {
                    if ((variable.AddTraces(traces) == traces.Count) &&
                        HasSystemArrayTraceCallback(variable))
                    {
                        variable.SetupValue(array, false, true, true, true);
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        error = String.Format(
                            "can't link {0}: could not set variable array",
                            FormatOps.ErrorVariableName(
                                variable, null, name, null));
                    }

                    return ReturnCode.Error;
                }
                else
                {
                    if (SetVariableValue2(
                            flags, frame, name, null, array, traces,
                            ref variable, ref error) == ReturnCode.Ok)
                    {
                        if (HasSystemArrayTraceCallback(variable))
                        {
                            variable.SetupValue(null, false, true, true, true);
                            return ReturnCode.Ok;
                        }
                        else
                        {
                            error = String.Format(
                                "can't link {0}: could not set variable array",
                                FormatOps.ErrorVariableName(
                                    variable, null, name, null));
                        }
                    }

                    return ReturnCode.Error;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue(
            VariableFlags flags,
            string name,
            string value
            )
        {
            Result error = null;

            return SetLibraryVariableValue(flags, name, value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue(
            VariableFlags flags,
            string name,
            string value,
            TraceList traces
            )
        {
            Result error = null;

            return SetLibraryVariableValue(flags, name, value, traces, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetLibraryVariableValue(
            VariableFlags flags,
            string name,
            string value,
            ref Result error
            )
        {
            return SetLibraryVariableValue(flags, name, value, (TraceList)null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue(
            VariableFlags flags,
            string name,
            string value,
            TraceList traces,
            ref Result error
            )
        {
            return SetLibraryVariableValue2(flags, name, null, value, traces, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value
            )
        {
            Result error = null;

            return SetLibraryVariableValue2(flags, name, index, value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value,
            ref Result error
            )
        {
            return SetLibraryVariableValue2(flags, name, index, value, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetLibraryVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value,
            TraceList traces,
            ref Result error
            )
        {
            flags |= VariableFlags.Library;
            return SetVariableValue2(flags, name, index, value, traces, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue(
            VariableFlags flags,
            string name,
            string value,
            TraceList traces
            )
        {
            Result error = null;

            return SetVariableValue(
                flags, name, value, traces, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetListVariableValue(
            VariableFlags flags,
            string name,
            StringList value,
            TraceList traces,
            ref Result error
            )
        {
            IVariable variable = null;

            return SetVariableValue2(
                flags, null, name, null, value, traces, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue(
            VariableFlags flags,
            string name,
            string value,
            TraceList traces,
            ref IVariable variable,
            ref Result error
            )
        {
            return SetVariableValue2(
                flags, name, null, value, traces, ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue(
            VariableFlags flags,
            string name,
            string value,
            ref Result error
            )
        {
            return SetVariableValue2(flags, name, null, value, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value,
            ref Result error
            )
        {
            return SetVariableValue2(flags, name, index, value, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value,
            TraceList traces,
            ref Result error
            )
        {
            IVariable variable = null;

            return SetVariableValue2(
                flags, name, index, value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            string value,
            TraceList traces,
            ref Result error
            )
        {
            IVariable variable = null;

            return SetVariableValue2(
                flags, frame, name, index, value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetVariableValue2(
            VariableFlags flags,
            string name,
            string index,
            string value,
            TraceList traces,
            ref IVariable variable,
            ref Result error
            )
        {
            return SetVariableValue2(
                flags, null, name, index, value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetVariableValue2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            string value,
            TraceList traces,
            ref IVariable variable,
            ref Result error
            )
        {
            return SetVariableValue2(
                flags, frame, name, index, (object)value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue2( /* NOTE: FOR [append]/[set] USE ONLY. */
            VariableFlags flags,
            string name,
            object value,
            TraceList traces,
            ref Result error
            )
        {
            IVariable variable = null;

            return SetVariableValue2(
                flags, null, name, null, (object)value, traces,
                ref variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode SetVariableValue2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            object value,
            TraceList traces,
            ref IVariable variable,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!readOnly || FlagOps.HasFlags(flags, VariableFlags.ReadOnlyMask, false))
                {
                    bool haveVariable = (variable != null);
                    Result localError = null;

                    if (haveVariable ||
                        (GetVariableViaResolversWithSplit(frame, name, index, ref flags,
                            ref variable, ref localError) == ReturnCode.Ok))
                    {
                        //
                        // COMPAT: Tcl, if the index was specified, make sure the name
                        //         itself does not contain an array element reference.
                        //
                        if (haveVariable || (index == null))
                        {
                            VariableFlags splitFlags = flags;
                            string splitIndex = null;

                            if (index != null)
                                splitFlags |= VariableFlags.NoElement;

                            if (ScriptOps.SplitVariableName(
                                    this, splitFlags, name, ref name,
                                    ref splitIndex, ref error) == ReturnCode.Ok)
                            {
                                if ((index == null) && (splitIndex != null))
                                    index = splitIndex;
                            }
                            else
                            {
                                return ReturnCode.Error;
                            }
                        }

                        //
                        // NOTE: Make sure we have a variable.
                        //
                        if (variable == null)
                        {
                            error = String.Format(
                                "can't set {0}: variable is invalid",
                                FormatOps.ErrorVariableName(name, index));

                            return ReturnCode.Error;
                        }

                        //
                        // NOTE: For linked variables, we may be linking to an array
                        //       element.
                        //
                        string linkIndex = null;

                        //
                        // NOTE: Save original call frame for traces.
                        //
                        ICallFrame savedFrame = variable.Frame;

                        //
                        // NOTE: Is the variable really a link to another variable?
                        //
                        // BUGFIX: Also, does the variable at the end of the link exist
                        //         in a defined call frame?
                        //
                        if (EntityOps.HasValidLink(variable, false))
                        {
                            //
                            // NOTE: Get the array element index of the link, if any.
                            //
                            linkIndex = variable.LinkIndex;

                            //
                            // NOTE: Follow the linked variable.
                            //
                            variable = EntityOps.FollowLinks(variable, flags);
                        }

                        //
                        // NOTE: Either a direct index or a link index is required.
                        //
                        if ((index != null) || (linkIndex != null))
                        {
                            //
                            // BUGFIX: (PART 1) If the variable was previously undefined, we
                            //         cannot validate it as an array variable.
                            //
                            // BUGFIX: If the variable is a link at this point the call frame
                            //         for the variable at the link destination is invalid;
                            //         therefore, allow the variable to be re-used as an array.
                            //
                            if ((EntityOps.IsUndefined(variable) || EntityOps.IsLink(variable) ||
                                    EntityOps.IsArray2(variable)) &&
                                ((index == null) || (linkIndex == null)))
                            {
                                //
                                // NOTE: If there was no element index specified, use
                                //       the one from the variable link.
                                //
                                if (index == null)
                                    index = linkIndex;

                                if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                                {
                                    object oldValue = EntityOps.GetOldValue(
                                        flags, variable, index, ScriptOps.GetDefaultValue(
                                            BreakpointType.BeforeVariableSet));

                                    object newValue = EntityOps.GetNewValue(
                                        flags, variable.Name, index, oldValue, value);

                                    ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                        this, null, BreakpointType.BeforeVariableSet, savedFrame,
                                        variable, name, index, flags, oldValue, newValue, null,
                                        null, null, NeedNewTraceInfo(flags), false,
                                        !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                        CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                        EntityOps.IsBreakOnSet(variable))
                                    {
                                        //
                                        // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                        //       set access for this variable.
                                        //
                                        Result localResult = null;

                                        if (CheckWatchpoints(
                                                ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                traceInfo, ref localResult) != ReturnCode.Ok)
                                        {
                                            error = localResult;
                                            return ReturnCode.Error;
                                        }
                                    }
#endif

                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                        !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                        !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                    {
                                        try
                                        {
                                            if (ScriptOps.FireTraces(
                                                    variable, traceInfo.BreakpointType, this, traceInfo,
                                                    ref error) != ReturnCode.Ok)
                                            {
                                                return ReturnCode.Error;
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            error = String.Format(
                                                "caught exception while firing variable traces: {0}",
                                                e);

                                            return ReturnCode.Error;
                                        }
                                    }

#if NOTIFY
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                        !EntityOps.IsNoNotify(variable))
                                    {
                                        /* IGNORED */
                                        CheckNotifications(
                                            NotifyType.Variable, NotifyFlags.Trace,
                                            new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                            this, null, null, null, ref error);
                                    }
#endif

                                    //
                                    // NOTE: If the trace(s) did not cancel the operation, proceed.
                                    //
                                    if (!traceInfo.Cancel)
                                    {
                                        if (traceInfo.Index != null)
                                        {
                                            //
                                            // NOTE: If the interpreter is in 'immutable' mode, prevent
                                            //       array elements from being changed (i.e. they may
                                            //       only be added).
                                            //
                                            if (immutable &&
                                                !EntityOps.IsUndefined(variable) &&
                                                !EntityOps.IsMutable(variable) &&
                                                !FlagOps.HasFlags(traceInfo.Flags,
                                                    VariableFlags.ImmutableMask, false))
                                            {
                                                ElementDictionary arrayValue2 = variable.ArrayValue;

                                                if ((arrayValue2 != null) &&
                                                    arrayValue2.ContainsKey(traceInfo.Index))
                                                {
                                                    error = String.Format(
                                                        "can't set {0}: interpreter is immutable",
                                                        FormatOps.ErrorVariableName(
                                                            variable, linkIndex, name, traceInfo.Index));

                                                    return ReturnCode.Error;
                                                }
                                            }

                                            //
                                            // BUGFIX: The variable may have been a link to a variable
                                            //         in an undefined call frame.
                                            //
                                            bool wasUndefined = false;

                                            if (ClearVariableFlagsOrLink(
                                                    frame, variable, traceInfo, traces, ref wasUndefined,
                                                    ref localError) != ReturnCode.Ok)
                                            {
                                                error = String.Format(
                                                    "can't set {0}: {1}",
                                                    FormatOps.ErrorVariableName(name, null),
                                                    localError);

                                                return ReturnCode.Error;
                                            }

                                            //
                                            // BUGFIX: (PART 2) We need to tag the variable as an array and
                                            //         create the underlying dictionary now if the variable
                                            //         was previously undefined.  Also, make sure the array
                                            //         value dictionary is created (or recreated) before
                                            //         continuing.
                                            //
                                            EntityOps.SetArray(variable, true);
                                            ElementDictionary arrayValue = variable.ArrayValue;

                                            if (wasUndefined || (arrayValue == null))
                                            {
                                                variable.Value = null;

                                                variable.ArrayValue = arrayValue =
                                                    new ElementDictionary(variableEvent);
                                            }

                                            arrayValue[traceInfo.Index] = traceInfo.NewValue;

                                            //
                                            // BUGFIX: Mark the variable as "dirty" AFTER the
                                            //         actual modifications have been completed.
                                            //
                                            EntityOps.SignalDirty(variable, traceInfo.Index);
                                        }
                                        else
                                        {
                                            error = String.Format(
                                                "can't set {0}: variable is array",
                                                FormatOps.ErrorVariableName(name, null));

                                            return ReturnCode.Error;
                                        }
                                    }

                                    return traceInfo.ReturnCode;
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't set {0}: variable is read-only",
                                        FormatOps.ErrorVariableName(
                                            variable, linkIndex, name, index));
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't set {0}: variable isn't array",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, index));
                            }
                        }
                        else
                        {
                            //
                            // BUGFIX: (PART 3) If the variable was previously undefined,
                            //         we cannot validate it as a scalar variable.
                            //
                            if (EntityOps.IsUndefined(variable) || !EntityOps.IsArray2(variable))
                            {
                                if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                                {
                                    object oldValue = (variable.Value != null) ?
                                        variable.Value : ScriptOps.GetDefaultValue(
                                            BreakpointType.BeforeVariableSet);

                                    object newValue = EntityOps.GetNewValue(
                                        flags, variable.Name, index, oldValue, value);

                                    ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                        this, null, BreakpointType.BeforeVariableSet, savedFrame,
                                        variable, name, index, flags, oldValue, newValue, null,
                                        null, null, NeedNewTraceInfo(flags), false,
                                        !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                        CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                        EntityOps.IsBreakOnSet(variable))
                                    {
                                        //
                                        // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                        //       set access for this variable.
                                        //
                                        Result localResult = null;

                                        if (CheckWatchpoints(
                                                ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                traceInfo, ref localResult) != ReturnCode.Ok)
                                        {
                                            error = localResult;
                                            return ReturnCode.Error;
                                        }
                                    }
#endif

                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                        !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                        !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                    {
                                        try
                                        {
                                            if (ScriptOps.FireTraces(
                                                    variable, traceInfo.BreakpointType, this, traceInfo,
                                                    ref error) != ReturnCode.Ok)
                                            {
                                                return ReturnCode.Error;
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            error = String.Format(
                                                "caught exception while firing variable traces: {0}",
                                                e);

                                            return ReturnCode.Error;
                                        }
                                    }

#if NOTIFY
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                        !EntityOps.IsNoNotify(variable))
                                    {
                                        /* IGNORED */
                                        CheckNotifications(
                                            NotifyType.Variable, NotifyFlags.Trace,
                                            new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                            this, null, null, null, ref error);
                                    }
#endif

                                    //
                                    // NOTE: If the trace(s) did not cancel the operation, proceed.
                                    //
                                    if (!traceInfo.Cancel)
                                    {
                                        if (immutable &&
                                            !EntityOps.IsUndefined(variable) &&
                                            !EntityOps.IsMutable(variable) &&
                                            !FlagOps.HasFlags(traceInfo.Flags,
                                                VariableFlags.ImmutableMask, false))
                                        {
                                            error = String.Format(
                                                "can't set {0}: interpreter is immutable",
                                                FormatOps.ErrorVariableName(name, null));

                                            return ReturnCode.Error;
                                        }

                                        //
                                        // BUGFIX: The variable may have been a link to a variable
                                        //         in an undefined call frame.
                                        //
                                        bool wasUndefined = false;

                                        if (ClearVariableFlagsOrLink(
                                                frame, variable, traceInfo, traces, ref wasUndefined,
                                                ref localError) != ReturnCode.Ok)
                                        {
                                            error = String.Format(
                                                "can't set {0}: {1}",
                                                FormatOps.ErrorVariableName(name, null),
                                                localError);

                                            return ReturnCode.Error;
                                        }

                                        //
                                        // BUGFIX: (PART 4) We need to tag the variable as a scalar and
                                        //         remove the underlying dictionary now if the variable
                                        //         was previously undefined or if array value dictionary
                                        //         is actually present.
                                        //
                                        EntityOps.SetArray(variable, false);
                                        ElementDictionary arrayValue = variable.ArrayValue;

                                        if (wasUndefined || (arrayValue != null))
                                            variable.ArrayValue = arrayValue = null;

                                        variable.Value = traceInfo.NewValue;

                                        //
                                        // BUGFIX: Mark the variable as "dirty" AFTER the
                                        //         actual modifications have been completed.
                                        //
                                        EntityOps.SignalDirty(variable, null);
                                    }

                                    return traceInfo.ReturnCode;
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't set {0}: variable is read-only",
                                        FormatOps.ErrorVariableName(name, null));
                                }
                            }
                            else
                            {
                                error = String.Format(
                                    "can't set {0}: variable is array",
                                    FormatOps.ErrorVariableName(name, null));
                            }
                        }
                    }
                    else
                    {
                        if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                        {
                            //
                            // COMPAT: Tcl, if the index was specified, make sure the name
                            //         itself does not contain an array element reference.
                            //
                            if (haveVariable || (index == null))
                            {
                                VariableFlags splitFlags = flags;
                                string splitIndex = null;

                                if (index != null)
                                    splitFlags |= VariableFlags.NoElement;

                                if (ScriptOps.SplitVariableName(
                                        this, splitFlags, name, ref name,
                                        ref splitIndex, ref error) == ReturnCode.Ok)
                                {
                                    if ((index == null) && (splitIndex != null))
                                        index = splitIndex;
                                }
                                else
                                {
                                    return ReturnCode.Error;
                                }
                            }

                            //
                            // NOTE: Make sure we are allowed to add new variables (i.e.
                            //       and not just change existing ones).
                            //
                            if (!FlagOps.HasFlags(flags, VariableFlags.NoCreate, true))
                            {
                                ICallFrame variableFrame = frame;
                                string newName = name;

                                if (GetVariableFrameViaResolvers(
                                        LookupFlags.Default, ref variableFrame, ref newName,
                                        ref flags, ref error) != ReturnCode.Ok)
                                {
                                    return ReturnCode.Error;
                                }

                                if (variableFrame == null)
                                {
                                    error = "invalid call frame from resolver";
                                    return ReturnCode.Error;
                                }

                                bool isGlobalCallFrame = IsGlobalCallFrame(variableFrame);

                                variable = new Variable(variableFrame, newName,
                                    (flags & ~VariableFlags.NonSetMask | VariableFlags.Undefined) |
                                    GetNewVariableFlags(isGlobalCallFrame), GetTraces(traces),
                                    variableEvent);

                                if (isGlobalCallFrame)
                                    EntityOps.SetGlobal(variable, true);
                                else
                                    EntityOps.SetLocal(variable, true);

                                object newValue = EntityOps.GetNewValue(
                                    flags, variable.Name, index, null, value);

                                ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                    this, null, BreakpointType.BeforeVariableSet, variableFrame,
                                    variable, name, index, flags, null, newValue, null,
                                    null, null, NeedNewTraceInfo(flags), false,
                                    !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                if (CanHitWatchpoints() &&
                                    EntityOps.IsBreakOnSet(variable))
                                {
                                    //
                                    // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                    //       set access for this variable.
                                    //
                                    Result localResult = null;

                                    if (CheckWatchpoints(
                                            ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                            traceInfo, ref localResult) != ReturnCode.Ok)
                                    {
                                        error = localResult;
                                        return ReturnCode.Error;
                                    }
                                }
#endif

                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                    !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                    !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                {
                                    try
                                    {
                                        if (ScriptOps.FireTraces(
                                                variable, traceInfo.BreakpointType, this, traceInfo,
                                                ref error) != ReturnCode.Ok)
                                        {
                                            return ReturnCode.Error;
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        error = String.Format(
                                            "caught exception while firing variable traces: {0}",
                                            e);

                                        return ReturnCode.Error;
                                    }
                                }

#if NOTIFY
                                if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                    !EntityOps.IsNoNotify(variable))
                                {
                                    /* IGNORED */
                                    CheckNotifications(
                                        NotifyType.Variable, NotifyFlags.Trace,
                                        new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                        this, null, null, null, ref error);
                                }
#endif

                                //
                                // NOTE: If the trace(s) did not cancel the operation, proceed.
                                //
                                if (!traceInfo.Cancel)
                                {
                                    if ((traceInfo.Index != null) ||
                                        EntityOps.IsArray2(variable))
                                    {
                                        EntityOps.SetArray(variable, true);

                                        ElementDictionary arrayValue =
                                            new ElementDictionary(variableEvent);

                                        variable.Value = null;
                                        variable.ArrayValue = arrayValue;

                                        if (traceInfo.Index != null)
                                            arrayValue.Add(traceInfo.Index, traceInfo.NewValue);
                                    }
                                    else
                                    {
                                        variable.Value = traceInfo.NewValue;
                                    }

                                    VariableDictionary variables = variableFrame.Variables;

                                    variables.Add(newName, variable);

                                    //
                                    // BUGFIX: Mark the variable as "dirty" AFTER the
                                    //         actual modifications have been completed.
                                    //
                                    EntityOps.SetUndefined(variable, false);
                                    EntityOps.SignalDirty(variable, traceInfo.Index);
                                }

                                return traceInfo.ReturnCode;
                            }
                            else
                            {
                                error = String.Format(
                                    "can't set {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, null, name, index));
                            }
                        }
                        else
                        {
                            //
                            // NOTE: We did not actually search for the variable,
                            //       inform the caller as to why.
                            //
                            error = localError;
                        }
                    }
                }
                else
                {
                    error = String.Format(
                        "can't set {0}: interpreter is read-only",
                        FormatOps.ErrorVariableName(name, index));
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool HasZeroString(
            VariableFlags variableFlags
            )
        {
#if !MONO && NATIVE && WINDOWS
            return FlagOps.HasFlags(
                variableFlags, VariableFlags.ZeroString, true);
#else
            return false;
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode UnsetLibraryVariable(
            VariableFlags flags,
            string name,
            ref Result error
            )
        {
            flags |= VariableFlags.Library;
            return UnsetVariable2(flags, name, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode UnsetVariable2(
            VariableFlags flags,
            string name,
            string index,
            ref Result error
            )
        {
            return UnsetVariable2(flags, name, index, null, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode UnsetVariable2(
            VariableFlags flags,
            string name,
            string index,
            IVariable variable,
            ref Result error
            )
        {
            return UnsetVariable2(flags, null, name, index, variable, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode UnsetVariable2(
            VariableFlags flags,
            ICallFrame frame,
            string name,
            string index,
            IVariable variable,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (immutable && !FlagOps.HasFlags(flags, VariableFlags.ImmutableMask, false))
                {
                    error = String.Format(
                        "can't unset {0}: interpreter is immutable",
                        FormatOps.ErrorVariableName(name, index));

                    return ReturnCode.Error;
                }

                if (!readOnly || FlagOps.HasFlags(flags, VariableFlags.ReadOnlyMask, false))
                {
                    //
                    // BUGBUG: This may need revision; we do need some way to remove
                    //         "stale" undefined variables from the call frame even
                    //         though the only way to officially create one is via the
                    //         global or upvar commands and those get cleaned up
                    //         automatically upon procedure exit.
                    //
                    bool haveVariable = (variable != null);
                    Result localError = null;

                    if ((haveVariable ||
                        (GetVariableViaResolversWithSplit(frame, name, index, ref flags,
                            ref variable, ref localError) == ReturnCode.Ok)) &&
                        !EntityOps.IsUndefined(variable, "unset", name, index,
                            ref localError))
                    {
                        //
                        // COMPAT: Tcl, if the index was specified, make sure the name
                        //         itself does not contain an array element reference.
                        //
                        if (haveVariable || (index == null))
                        {
                            VariableFlags splitFlags = flags;
                            string splitIndex = null;

                            if (index != null)
                                splitFlags |= VariableFlags.NoElement;

                            if (ScriptOps.SplitVariableName(
                                    this, splitFlags, name, ref name,
                                    ref splitIndex, ref error) == ReturnCode.Ok)
                            {
                                if ((index == null) && (splitIndex != null))
                                    index = splitIndex;
                            }
                            else
                            {
                                return ReturnCode.Error;
                            }
                        }

                        //
                        // NOTE: Make sure we have a variable.
                        //
                        if (variable == null)
                        {
                            error = String.Format(
                                "can't unset {0}: variable is invalid",
                                FormatOps.ErrorVariableName(name, index));

                            return ReturnCode.Error;
                        }

                        //
                        // NOTE: For linked variables, we may be linking to an array
                        //       element.
                        //
                        string linkIndex = null;

                        //
                        // NOTE: Save original call frame for traces.
                        //
                        ICallFrame savedFrame = variable.Frame;

                        //
                        // NOTE: For linked variables, save a reference to the original
                        //       variable link itself.
                        //
                        IVariable savedVariable = null;

                        //
                        // NOTE: Is the variable really a link to another variable?
                        //
                        // BUGFIX: Also, does the variable at the end of the link exist
                        //         in a defined call frame?
                        //
                        if (EntityOps.HasValidLink(variable, false))
                        {
                            //
                            // NOTE: Get the array element index of the link, if any.
                            //
                            linkIndex = variable.LinkIndex;

                            //
                            // NOTE: Save the link itself because we may need to mark it
                            //       as undefined (below).
                            //
                            savedVariable = variable; // TEST: Test this.

                            //
                            // NOTE: Follow the linked variable.
                            //
                            variable = EntityOps.FollowLinks(variable, flags);
                        }

                        if (!EntityOps.IsUndefined(variable))
                        {
                            if ((index != null) || (linkIndex != null))
                            {
                                if (EntityOps.IsArray2(variable) &&
                                        ((index == null) || (linkIndex == null)))
                                {
                                    //
                                    // NOTE: If there was no element index specified, use
                                    //       the one from the variable link.
                                    //
                                    if (index == null)
                                        index = linkIndex;

                                    if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                                    {
                                        ElementDictionary arrayValue = variable.ArrayValue;

                                        if ((arrayValue != null) && arrayValue.ContainsKey(index))
                                        {
                                            object oldValue = EntityOps.GetOldValue(
                                                flags, variable, index, ScriptOps.GetDefaultValue(
                                                    BreakpointType.BeforeVariableUnset));

                                            ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                                this, null, BreakpointType.BeforeVariableUnset, savedFrame,
                                                variable, name, index, flags, oldValue, null, null,
                                                null, null, NeedNewTraceInfo(flags), false,
                                                !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                                CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                                EntityOps.IsBreakOnUnset(variable))
                                            {
                                                //
                                                // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                                //       unset access for this variable.
                                                //
                                                Result localResult = null;

                                                if (CheckWatchpoints(
                                                        ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                        traceInfo, ref localResult) != ReturnCode.Ok)
                                                {
                                                    error = localResult;
                                                    return ReturnCode.Error;
                                                }
                                            }
#endif

                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                                !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                                !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                            {
                                                try
                                                {
                                                    if (ScriptOps.FireTraces(
                                                            variable, traceInfo.BreakpointType, this, traceInfo,
                                                            ref error) != ReturnCode.Ok)
                                                    {
                                                        return ReturnCode.Error;
                                                    }
                                                }
                                                catch (Exception e)
                                                {
                                                    error = String.Format(
                                                        "caught exception while firing variable traces: {0}",
                                                        e);

                                                    return ReturnCode.Error;
                                                }
                                            }

#if NOTIFY
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                                !EntityOps.IsNoNotify(variable))
                                            {
                                                /* IGNORED */
                                                CheckNotifications(
                                                    NotifyType.Variable, NotifyFlags.Trace,
                                                    new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                    this, null, null, null, ref error);
                                            }
#endif

                                            bool reset = FlagOps.HasFlags(
                                                traceInfo.Flags, VariableFlags.ResetValue, true);

                                            bool zero = HasZeroString() && HasZeroString(traceInfo.Flags);

                                            //
                                            // NOTE: If the trace(s) did not cancel the operation, proceed.
                                            //
                                            if (!traceInfo.Cancel)
                                            {
                                                if (traceInfo.Index != null)
                                                {
                                                    arrayValue = variable.ArrayValue; /* REFRESH */

                                                    if (arrayValue != null)
                                                    {
                                                        if (reset)
                                                        {
                                                            /* IGNORED */
                                                            arrayValue.ResetValue(
                                                                this, traceInfo.Index, zero);
                                                        }
                                                        else
                                                        {
                                                            /* IGNORED */
                                                            arrayValue.Remove(traceInfo.Index);
                                                        }

                                                        //
                                                        // HACK: Even though the element itself has been
                                                        //       removed, we need to make sure any pending
                                                        //       waits for the array element are properly
                                                        //       signaled.
                                                        //
                                                        // BUGFIX: Mark the variable as "dirty" AFTER the
                                                        //         actual modifications have been completed.
                                                        //
                                                        EntityOps.SignalDirty(variable, traceInfo.Index);
                                                    }
                                                    else
                                                    {
                                                        error = String.Format(
                                                            "can't unset {0}: no longer an array",
                                                            FormatOps.ErrorVariableName(
                                                                variable, linkIndex, name, index));

                                                        return ReturnCode.Error;
                                                    }
                                                }
                                                else
                                                {
                                                    if ((savedVariable != null) &&
                                                        !Object.ReferenceEquals(savedVariable, variable))
                                                    {
                                                        //
                                                        // NOTE: Links to dead variable(s) should be dead too.
                                                        //
                                                        if (reset && (savedVariable is Variable))
                                                            ((Variable)savedVariable).ResetValue(this, zero);

                                                        EntityOps.SetUndefined(savedVariable, true); // TEST: Test this.
                                                    }

                                                    //
                                                    // NOTE: The variable is now dead.
                                                    //
                                                    if (reset && (variable is Variable))
                                                        ((Variable)variable).ResetValue(this, zero);

                                                    EntityOps.SetUndefined(variable, true);

                                                    //
                                                    // NOTE: Remove any pending array searches that may exist for this
                                                    //       variable.
                                                    //
                                                    CleanupArraySearches(variable);

                                                    //
                                                    // NOTE: Check for the variable purge flag.  If the purge flag is set,
                                                    //       we remove all undefined variables from the current call frame.
                                                    //
                                                    if (FlagOps.HasFlags(traceInfo.Flags, VariableFlags.Purge, true))
                                                    {
                                                        //
                                                        // NOTE: Purge all undefined variables in the call frame for the
                                                        //       variable to be unset.  This implies removal of the variable
                                                        //       to be unset because we just set it to be undefined (above).
                                                        //
                                                        /* IGNORED */
                                                        CallFrameOps.Cleanup(CurrentFrame, savedFrame, false);
                                                    }
                                                    else if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NoRemove, true))
                                                    {
                                                        if (savedFrame != null)
                                                        {
                                                            VariableDictionary variables = savedFrame.Variables;

                                                            //
                                                            // NOTE: Remove the entire array if there is one; otherwise,
                                                            //       just remove this scalar variable.
                                                            //
                                                            if (variables != null)
                                                                variables.Remove(name);
                                                        }
                                                    }

                                                    //
                                                    // HACK: Even though the variable itself has been
                                                    //       removed, we need to make sure any pending
                                                    //       waits for the array elements are properly
                                                    //       signaled.
                                                    //
                                                    // BUGFIX: Mark the variable as "dirty" AFTER the
                                                    //         actual modifications have been completed.
                                                    //
                                                    EntityOps.SignalDirty(variable, null);
                                                }
                                            }

                                            return traceInfo.ReturnCode;
                                        }
                                        else
                                        {
                                            ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                                this, null, BreakpointType.BeforeVariableUnset, savedFrame,
                                                variable, name, index, flags, null, null, null,
                                                null, null, NeedNewTraceInfo(flags), false,
                                                !EntityOps.IsNoPostProcess(variable), ReturnCode.Error);

#if DEBUGGER && DEBUGGER_VARIABLE
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                                CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                                EntityOps.IsBreakOnUnset(variable))
                                            {
                                                //
                                                // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                                //       unset access for this variable.
                                                //
                                                Result localResult = null;

                                                if (CheckWatchpoints(
                                                        ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                        traceInfo, ref localResult) != ReturnCode.Ok)
                                                {
                                                    error = localResult;
                                                    return ReturnCode.Error;
                                                }
                                            }
#endif

                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                                !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                                !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                            {
                                                try
                                                {
                                                    if (ScriptOps.FireTraces(
                                                            variable, traceInfo.BreakpointType, this, traceInfo,
                                                            ref error) != ReturnCode.Ok)
                                                    {
                                                        return ReturnCode.Error;
                                                    }
                                                }
                                                catch (Exception e)
                                                {
                                                    error = String.Format(
                                                        "caught exception while firing variable traces: {0}",
                                                        e);

                                                    return ReturnCode.Error;
                                                }
                                            }

#if NOTIFY
                                            if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                                !EntityOps.IsNoNotify(variable))
                                            {
                                                /* IGNORED */
                                                CheckNotifications(
                                                    NotifyType.Variable, NotifyFlags.Trace,
                                                    new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                                    this, null, null, null, ref error);
                                            }
#endif

                                            //
                                            // NOTE: If the trace(s) did not cancel the operation, proceed.
                                            //
                                            if (!traceInfo.Cancel)
                                            {
                                                //
                                                // BUGFIX: When the variable traces, if any, do not cancel
                                                //         the operation entirely, honor the NoComplain flag.
                                                //
                                                if (FlagOps.HasFlags(
                                                        traceInfo.Flags, VariableFlags.NoComplain, true))
                                                {
                                                    return ReturnCode.Ok;
                                                }

                                                error = String.Format(
                                                    "can't unset {0}: no such element in array",
                                                    FormatOps.ErrorVariableName(
                                                        variable, linkIndex, name, index));
                                            }

                                            return traceInfo.ReturnCode;
                                        }
                                    }
                                    else
                                    {
                                        error = String.Format(
                                            "can't unset {0}: variable is read-only",
                                            FormatOps.ErrorVariableName(
                                                variable, linkIndex, name, index));
                                    }
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't unset {0}: variable isn't array",
                                        FormatOps.ErrorVariableName(
                                            variable, linkIndex, name, index));
                                }
                            }
                            else
                            {
                                if (!EntityOps.IsReadOnly(variable) && !EntityOps.IsInvariant(variable))
                                {
                                    ICallFrame variableFrame = frame;
                                    string newName = name;

                                    if (GetVariableFrameViaResolvers(
                                            LookupFlags.Default, ref variableFrame, ref newName,
                                            ref flags, ref error) != ReturnCode.Ok)
                                    {
                                        return ReturnCode.Error;
                                    }

                                    if (variableFrame == null)
                                    {
                                        error = String.Format(
                                            "can't unset {0}: invalid call frame from resolver",
                                            FormatOps.ErrorVariableName(name, null));

                                        return ReturnCode.Error;
                                    }

                                    VariableDictionary variables = variableFrame.Variables;

                                    if (variables == null)
                                    {
                                        error = String.Format(
                                            "can't unset {0}: call frame does not support variables",
                                            FormatOps.ErrorVariableName(name, null));

                                        return ReturnCode.Error;
                                    }

                                    object oldValue = EntityOps.GetOldValue(
                                        flags, variable, index, ScriptOps.GetDefaultValue(
                                            BreakpointType.BeforeVariableUnset));

                                    ITraceInfo traceInfo = ScriptOps.NewTraceInfo(
                                        this, null, BreakpointType.BeforeVariableUnset, savedFrame,
                                        variable, name, index, flags, oldValue, null, null,
                                        null, null, NeedNewTraceInfo(flags), false,
                                        !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok);

#if DEBUGGER && DEBUGGER_VARIABLE
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonWatchpoint, false) &&
                                        CanHitWatchpoints() && !EntityOps.IsNoWatchpoint(variable) &&
                                        EntityOps.IsBreakOnUnset(variable))
                                    {
                                        //
                                        // NOTE: Debugger support, call Debugger.Trace if we are breaking on
                                        //       unset access for this variable.
                                        //
                                        Result localResult = null;

                                        if (CheckWatchpoints(
                                                ReturnCode.Ok, traceInfo.BreakpointType, name, null,
                                                traceInfo, ref localResult) != ReturnCode.Ok)
                                        {
                                            error = localResult;
                                            return ReturnCode.Error;
                                        }
                                    }
#endif

                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonTrace, false) &&
                                        !HasNoTraces() && EntityOps.HasTraces(variable) &&
                                        !EntityOps.IsNoTrace(variable) && (TraceLevels == 0))
                                    {
                                        try
                                        {
                                            if (ScriptOps.FireTraces(
                                                    variable, traceInfo.BreakpointType, this, traceInfo,
                                                    ref error) != ReturnCode.Ok)
                                            {
                                                return ReturnCode.Error;
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            error = String.Format(
                                                "caught exception while firing variable traces: {0}",
                                                e);

                                            return ReturnCode.Error;
                                        }
                                    }

#if NOTIFY
                                    if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NonNotify, false) &&
                                        !EntityOps.IsNoNotify(variable))
                                    {
                                        /* IGNORED */
                                        CheckNotifications(
                                            NotifyType.Variable, NotifyFlags.Trace,
                                            new ObjectPair(traceInfo.BreakpointType, traceInfo),
                                            this, null, null, null, ref error);
                                    }
#endif

                                    bool reset = FlagOps.HasFlags(
                                        traceInfo.Flags, VariableFlags.ResetValue, true);

                                    bool zero = HasZeroString() && HasZeroString(traceInfo.Flags);

                                    //
                                    // NOTE: If the trace(s) did not cancel the operation, proceed.
                                    //
                                    if (!traceInfo.Cancel)
                                    {
                                        if ((savedVariable != null) &&
                                            !Object.ReferenceEquals(savedVariable, variable))
                                        {
                                            //
                                            // NOTE: Links to dead variable(s) should be dead too.
                                            //
                                            if (reset && (savedVariable is Variable))
                                                ((Variable)savedVariable).ResetValue(this, zero);

                                            EntityOps.SetUndefined(savedVariable, true); // TEST: Test this.
                                        }

                                        //
                                        // NOTE: The variable is now dead.
                                        //
                                        if (reset && (variable is Variable))
                                            ((Variable)variable).ResetValue(this, zero);

                                        EntityOps.SetUndefined(variable, true);

                                        //
                                        // NOTE: Remove any pending array searches that may exist for this
                                        //       variable.
                                        //
                                        CleanupArraySearches(variable);

                                        //
                                        // NOTE: Check for the variable purge flag.  If the purge flag is set,
                                        //       we remove all undefined variables from the current call frame.
                                        //
                                        if (FlagOps.HasFlags(traceInfo.Flags, VariableFlags.Purge, true))
                                        {
                                            //
                                            // NOTE: Purge all undefined variables in the call frame for the
                                            //       variable to be unset.  This implies removal of the variable
                                            //       to be unset because we just set it to be undefined (above).
                                            //
                                            /* IGNORED */
                                            CallFrameOps.Cleanup(CurrentFrame, variableFrame, false);
                                        }
                                        else if (!FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NoRemove, true))
                                        {
                                            //
                                            // NOTE: Remove the entire array if there is one; otherwise,
                                            //       just remove this scalar variable.
                                            //
                                            variables.Remove(newName);
                                        }

                                        //
                                        // HACK: Even though the variable itself has been
                                        //       removed, we need to make sure any pending
                                        //       waits for the array elements are properly
                                        //       signaled.
                                        //
                                        // BUGFIX: Mark the variable as "dirty" AFTER the
                                        //         actual modifications have been completed.
                                        //
                                        EntityOps.SignalDirty(variable, null);
                                    }

                                    return traceInfo.ReturnCode;
                                }
                                else
                                {
                                    error = String.Format(
                                        "can't unset {0}: variable is read-only",
                                        FormatOps.ErrorVariableName(name, null));
                                }
                            }
                        }
                        else
                        {
                            //
                            // BUGBUG: This may need revision; we do need some way to remove
                            //         "stale" undefined variables from the call frame even
                            //         though the only way to officially create one is via the
                            //         global or upvar commands and those get cleaned up
                            //         automatically upon procedure exit.
                            //
                            if (FlagOps.HasFlags(flags, VariableFlags.NoComplain, true))
                            {
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = String.Format(
                                    "can't unset {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, linkIndex, name, index));
                            }
                        }
                    }
                    else
                    {
                        if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                        {
                            if (FlagOps.HasFlags(flags, VariableFlags.NoComplain, true))
                            {
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                error = String.Format(
                                    "can't unset {0}: no such variable",
                                    FormatOps.ErrorVariableName(
                                        variable, null, name, index));
                            }
                        }
                        else
                        {
                            if (FlagOps.HasFlags(flags, VariableFlags.NoComplain, true))
                            {
                                return ReturnCode.Ok;
                            }
                            else
                            {
                                //
                                // NOTE: We did not actually search for the variable,
                                //       inform the caller as to why.
                                //
                                error = localError;
                            }
                        }
                    }
                }
                else
                {
                    error = String.Format(
                        "can't unset {0}: interpreter is read-only",
                        FormatOps.ErrorVariableName(name, index));
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode MakeVariableFast( /* NOTE: For script library only. */
            string name,
            bool fast
            )
        {
            Result error = null;

            return MakeVariableFast(name, fast, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode ClearVariableNameWait(
            Interpreter interpreter, /* in */
            string name,             /* in */
            VariableFlags flags      /* in */
            )
        {
            Result error = null;

            return ClearVariableNameWait(interpreter, name, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode ClearVariableNameWait(
            Interpreter interpreter, /* in */
            string name,             /* in */
            VariableFlags flags,     /* in */
            ref Result error         /* out */
            ) /* THREAD-SAFE */
        {
            if (interpreter != null)
            {
                if (name != null)
                {
                    //
                    // BUGFIX: If the interpreter is disposed, skip clearing the variable
                    //         wait flags because the variable belongs to the interpreter,
                    //         which is now invalid.
                    //
                    lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
                    {
                        if (!IsDeletedOrDisposed(interpreter))
                        {
                            string varName = null;
                            string varIndex = null;
                            IVariable variable = null;

                            //
                            // NOTE: Attempt to search for the variable in the current
                            //       variable call frame.
                            //
                            if (interpreter.GetVariableViaResolversWithSplit(null,
                                    name, null, ref varName, ref varIndex, ref flags,
                                    ref variable, ref error) == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Is the variable really a link to another
                                //       variable?
                                //
                                if (FlagOps.HasFlags(flags,
                                        VariableFlags.WaitFollowLink, true) &&
                                    EntityOps.IsLink(variable))
                                {
                                    //
                                    // NOTE: Follow the linked variable.
                                    //
                                    variable = EntityOps.FollowLinks(variable, flags);
                                }

                                //
                                // NOTE: Was the variable name actually a reference to
                                //       an array element?  Tcl allows this; therefore,
                                //       we must as well.
                                //
                                if (FlagOps.HasFlags(flags,
                                        VariableFlags.WasElement, true) &&
                                    EntityOps.IsArray(variable) && (varIndex != null))
                                {
                                    //
                                    // NOTE: Clear the array element wakeup
                                    //       flag now.
                                    //
                                    /* IGNORED */
                                    EntityOps.SetElementWait(
                                        variable, varIndex, false, true);
                                }
                                else
                                {
                                    //
                                    // NOTE: Clear the variable wakeup flag
                                    //       now.
                                    //
                                    /* IGNORED */
                                    EntityOps.SetWait(variable, false);
                                }

                                return ReturnCode.Ok;
                            }
                        }
                        else
                        {
                            error = "attempt to call eval in disposed interpreter";
                        }
                    }
                }
                else
                {
                    error = "invalid variable name";
                }
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode IsVariableNameDirty(
            Interpreter interpreter, /* in */
            string name,             /* in */
            VariableFlags flags,     /* in */
            ref bool once,           /* in, out */
            ref bool exists,         /* in, out */
            ref bool dirty,          /* out */
            ref Result error         /* out */
            ) /* THREAD-SAFE */
        {
          if (interpreter != null)
            {
                //
                // NOTE: *WARNING* Empty variable names are allowed, please do not
                //       change these to "!String.IsNullOrEmpty".
                //
                if (name != null)
                {
                    lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
                    {
                        //
                        // BUGFIX: Avoid disposal race condition.
                        //
                        if (!IsDeletedOrDisposed(interpreter))
                        {
                            string varName = null;
                            string varIndex = null;
                            IVariable variable = null;
                            Result localError = null;

                            //
                            // NOTE: Attempt to search for the variable in the current
                            //       variable call frame.
                            //
                            if (interpreter.GetVariableViaResolversWithSplit(null,
                                    name, null, ref varName, ref varIndex, ref flags,
                                    ref variable, ref localError) == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Is the variable really a link to another
                                //       variable?
                                //
                                if (FlagOps.HasFlags(flags,
                                        VariableFlags.WaitFollowLink, true) &&
                                    EntityOps.IsLink(variable))
                                {
                                    //
                                    // NOTE: Follow the linked variable.
                                    //
                                    variable = EntityOps.FollowLinks(variable, flags);
                                }

                                //
                                // NOTE: Was the variable name actually a reference to
                                //       an array element?  Tcl allows this; therefore,
                                //       we must as well.
                                //
                                if (FlagOps.HasFlags(flags,
                                        VariableFlags.WasElement, true) &&
                                    EntityOps.IsArray(variable) && (varIndex != null))
                                {
                                    //
                                    // NOTE: Have we seen this array element already?
                                    //
                                    if (once)
                                    {
                                        //
                                        // NOTE: Check if the dirty flag is set on
                                        //       the array element involved.
                                        //
                                        dirty = EntityOps.IsDirty(variable, varIndex);
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Initially, this array element does exist.
                                        //
                                        exists = true;

                                        //
                                        // NOTE: Flag the array element as needing to wakeup
                                        //       from its wait now.
                                        //
                                        /* IGNORED */
                                        EntityOps.SetElementWait(variable, varIndex, true, true);

                                        //
                                        // NOTE: Flag this array element as non-dirty now.
                                        //
                                        /* IGNORED */
                                        EntityOps.SetElementDirty(variable, varIndex, false, true);

                                        //
                                        // NOTE: We have now seen this variable at least
                                        //       once.
                                        //
                                        once = true;
                                    }
                                }
                                else
                                {
                                    //
                                    // NOTE: Have we seen this variable already?
                                    //
                                    if (once)
                                    {
                                        //
                                        // NOTE: If the dirty flag is set, the variable
                                        //       is considered to be dirty.
                                        //
                                        dirty = EntityOps.IsDirty(variable);
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Initially, this variable does exist.
                                        //
                                        exists = true;

                                        //
                                        // NOTE: Flag the variable as needing to wakeup
                                        //       from its wait now.
                                        //
                                        /* IGNORED */
                                        EntityOps.SetWait(variable, true);

                                        //
                                        // NOTE: Flag this variable as non-dirty now.
                                        //
                                        /* IGNORED */
                                        EntityOps.SetDirty(variable, false);

                                        //
                                        // NOTE: We have now seen this variable at least
                                        //       once.
                                        //
                                        once = true;
                                    }
                                }

                                //
                                // NOTE: If the variable is dirty and tracing is enabled,
                                //       display debugging information before returning.
                                //
                                if (dirty && FlagOps.HasFlags(
                                        flags, VariableFlags.WaitTrace, true))
                                {
                                    TraceOps.DebugTrace(String.Format(
                                        "{0}: IsVariableNameDirty: variable resolved, code = Ok, " +
                                        "interpreter = {1}, name = {2}, varName = {3}, varIndex = {4}, " +
                                        "flags = {5}, once = {6}, exists = {7}, dirty = {8}, error = {9}{10}",
                                        GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                                        FormatOps.WrapOrNull(name), FormatOps.WrapOrNull(varName),
                                        FormatOps.WrapOrNull(varIndex), FormatOps.WrapOrNull(flags),
                                        once, exists, dirty, FormatOps.WrapOrNull(true, true, error),
                                        Environment.NewLine), typeof(Interpreter).Name);
                                }

                                return ReturnCode.Ok;
                            }
                            else
                            {
                                //
                                // NOTE: Did we actually search for the variable?
                                //
                                if (FlagOps.HasFlags(flags, VariableFlags.NotFound, true))
                                {
                                    //
                                    // NOTE: Have we seen this variable already?
                                    //
                                    if (once)
                                    {
                                        //
                                        // NOTE: If the variable existed previously and
                                        //       it does not exist now then it is dirty.
                                        //
                                        if (exists)
                                            dirty = true;
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Initially, this variable does not exist.
                                        //
                                        exists = false;

                                        //
                                        // NOTE: We have now seen this variable at least
                                        //       once.
                                        //
                                        once = true;
                                    }

                                    //
                                    // BUGFIX: If we previously waited on another
                                    //         variable that happened to exist, the
                                    //         variable event for the interpreter may
                                    //         already be in a signaled state and we
                                    //         do not want that; therefore, reset it
                                    //         now.
                                    //
                                    /* IGNORED */
                                    ThreadOps.ResetEvent(interpreter.PrivateVariableEvent);

                                    //
                                    // NOTE: If the variable is dirty and tracing is enabled,
                                    //       display debugging information before returning.
                                    //
                                    if (dirty && FlagOps.HasFlags(
                                            flags, VariableFlags.WaitTrace, true))
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: IsVariableNameDirty: variable unresolved, code = Ok, " +
                                            "interpreter = {1}, name = {2}, , varName = {3}, varIndex = {4}, " +
                                            "flags = {5}, once = {6}, exists = {7}, dirty = {8}, error = {9}{10}",
                                            GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                                            FormatOps.WrapOrNull(name), FormatOps.WrapOrNull(varName),
                                            FormatOps.WrapOrNull(varIndex), FormatOps.WrapOrNull(flags),
                                            once, exists, dirty, FormatOps.WrapOrNull(true, true, error),
                                            Environment.NewLine), typeof(Interpreter).Name);
                                    }

                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    //
                                    // NOTE: We could not search for the variable, let the
                                    //       caller know why.
                                    //
                                    error = localError;
                                }
                            }
                        }
                        else
                        {
                            error = "attempt to call eval in disposed interpreter";
                        }
                    }
                }
                else
                {
                    error = "invalid variable name";
                }
            }
            else
            {
                error = "invalid interpreter";
            }

            //
            // NOTE: If the variable is dirty and tracing is enabled,
            //       display debugging information before returning.
            //
            if (dirty && FlagOps.HasFlags(
                    flags, VariableFlags.WaitTrace, true))
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: IsVariableNameDirty: code = Error, interpreter = {1}, name = {2}, " +
                    "flags = {3}, once = {4}, exists = {5}, dirty = {6}, error = {7}{8}",
                    GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                    FormatOps.WrapOrNull(name), FormatOps.WrapOrNull(flags),
                    once, exists, dirty, FormatOps.WrapOrNull(true, true, error),
                    Environment.NewLine), typeof(Interpreter).Name);
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool ShouldWaitVariable()
        {
            //
            // BUGFIX: Prevent possible future deadlock caused by holding the
            //         interpreter lock while calling the Enabled and
            //         EventCount properties method, which may at some point
            //         acquire and hold the event manager lock.
            //
            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            if (EventOps.ManagerIsOk(eventManager))
            {
                bool enabled = eventManager.Enabled;

                return enabled && ((eventManager.TotalEventCount > 0) ||
#if NETWORK
                    (serverSockets > 0)
#else
                    false /* NOTE: No network support. */
#endif
                    );
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private EventWaitHandle[] GetEventWaitHandles(
            EventWaitHandle @event,
            bool reset
            )
        {
            EventWaitHandle variableEvent;

            lock (syncRoot)
            {
                variableEvent = this.variableEvent;
            }

            IEventManager eventManager;

            lock (syncRoot)
            {
                eventManager = this.eventManager;
            }

            EventWaitHandle emptyEvent = null;
            EventWaitHandle enqueueEvent = null;
            EventWaitHandle[] userEvents = null;

            if (EventOps.ManagerIsOk(eventManager))
            {
                emptyEvent = eventManager.EmptyEvent;
                enqueueEvent = eventManager.EnqueueEvent;
                userEvents = eventManager.UserEvents;
            }

            int length = ConversionOps.ToInt(variableEvent != null) +
                ConversionOps.ToInt(emptyEvent != null) +
                ConversionOps.ToInt(enqueueEvent != null) +
                ConversionOps.ToInt(@event != null) +
                ((userEvents != null) ? userEvents.Length : 0);

            EventWaitHandle[] events;

            if (length > 0)
            {
                events = new EventWaitHandle[length];

                int startIndex = 0;

                if ((length > startIndex) && (variableEvent != null))
                    events[startIndex++] = variableEvent;

                if ((length > startIndex) && (emptyEvent != null))
                    events[startIndex++] = emptyEvent;

                if ((length > startIndex) && (enqueueEvent != null))
                    events[startIndex++] = enqueueEvent;

                //
                // NOTE: *HOOK* Allow the immediate caller to inject an event
                //       into the array to wait for.
                //
                if ((length > startIndex) && (@event != null))
                    events[startIndex++] = @event;

                //
                // NOTE: *HOOK* Allow external applications and/or users to
                //       cleanly interact with the core event loop.
                //
                if (length > startIndex)
                    for (int index = startIndex; index < length; index++)
                        events[index] = userEvents[index - startIndex];

                if (reset)
                {
                    //
                    // NOTE: Minimally, we need to reset the master variable
                    //       event to make sure we do not [always] return
                    //       immediately from the wait call inside the loop.
                    //
                    for (int index = 0; index < length; index++)
                        ThreadOps.ResetEvent(events[index]);
                }

                return events;
            }

            return null;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Variable Management (Multiple)
        public ReturnCode GetVariableValues(
            VariableFlags flags,
            StringSortedList variables,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            if (variables != null)
            {
                StringList keys = new StringList(variables.Keys);

                foreach (string name in keys)
                {
                    ReturnCode code;
                    Result value = null;

                    code = GetVariableValue(flags, name, ref value, ref error);

                    //
                    // NOTE: Non-strict mode allows us to unconditionally query a
                    //       group of variables without worrying that some of them
                    //       may not actually exist.
                    //
                    if (code == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Success, replace contained value with
                        //       queried value.
                        //
                        variables[name] = value;
                    }
                    else if (strict)
                    {
                        //
                        // NOTE: Failure, return error code to caller.
                        //
                        return code;
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid variable list";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode SetVariableValues(
            VariableFlags flags,
            TraceList traces,
            StringSortedList variables,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            if (variables != null)
            {
                foreach (KeyValuePair<string, string> pair in variables)
                {
                    ReturnCode code;

                    code = SetVariableValue(flags, pair.Key, pair.Value, traces, ref error);

                    //
                    // NOTE: Non-strict mode allows us to unconditionally set a
                    //       group of variables without worrying that some of them
                    //       may actually be read-only, etc.
                    //
                    if (strict && (code != ReturnCode.Ok))
                    {
                        //
                        // NOTE: Failure, return error code to caller.
                        //
                        return code;
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid variable list";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode UnsetVariables(
            VariableFlags flags,
            StringSortedList variables,
            bool strict,
            ref Result error
            )
        {
            CheckDisposed();

            if (variables != null)
            {
                foreach (string name in variables.Keys)
                {
                    ReturnCode code;

                    code = UnsetVariable(flags, name, ref error);

                    //
                    // NOTE: Non-strict mode allows us to unconditionally unset a
                    //       group of variables without worrying that some of them
                    //       may not actually exist.
                    //
                    if (strict && (code != ReturnCode.Ok))
                    {
                        //
                        // NOTE: Failure, return error code to caller.
                        //
                        return code;
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid variable list";
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Creation, Pre-Setup, Setup, & Initialization
        #region Creation
        internal CreateFlags FilterCreateFlags(
            bool debug,
            bool safe,
            bool standard
            )
        {
            CreateFlags result = CreateFlags.None;

#if DEBUGGER
            if (debug)
                result |= (createFlags & CreateFlags.DebuggerUse);
#endif

            if (safe)
                result |= (createFlags & CreateFlags.SafeAndHideUnsafe);

            if (standard)
                result |= (createFlags & CreateFlags.StandardAndHideNonStandard);

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && NATIVE_UTILITY
        internal static bool IsVerbose(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return false;

            return FlagOps.HasFlags(
                interpreter.CreateFlagsNoLock, CreateFlags.Verbose, true);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static CreateFlags GetStartupCreateFlags( /* throw */
            IEnumerable<string> args,
            CreateFlags createFlags,
            OptionOriginFlags originFlags,
            bool console,
            bool verbose
            )
        {
            StringList argv = (args != null) ? new StringList(args) : null;

            TraceOps.DebugTrace(String.Format(
                "{0}: GetStartupCreateFlags: entered, argv = {1}, createFlags = {2}, " +
                "originFlags = {3}, console = {4}, verbose = {5}{6}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(true, true, argv),
                FormatOps.WrapOrNull(createFlags), FormatOps.WrapOrNull(originFlags),
                console, verbose, Environment.NewLine), typeof(Interpreter).Name);

            if (verbose)
            {
// #if CONSOLE
//                 if (console)
//                     Console.WriteLine(_Constants.Prompt.Verbose);
// #endif

                createFlags |= CreateFlags.Verbose;
            }

            if (FlagOps.HasFlags(originFlags, OptionOriginFlags.Environment, true))
            {
                //
                // NOTE: Check for the debug environment variable.
                //       If it is set (to anything) then set the
                //       debug flag for the interpreter right now.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.Debug, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.Debug);
#endif

                    createFlags |= CreateFlags.Debug;
                }

                //
                // NOTE: Check for the "safe" environment variable.
                //       If it is set (to anything) then enable the
                //       appropriate "safe mode" flags for the
                //       interpreter.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.Safe, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.Safe); /* throw */
#endif

                    createFlags |= CreateFlags.SafeAndHideUnsafe;
                }

                //
                // NOTE: Check for the "standard" environment variable.
                //       If it is set (to anything) then enable the
                //       appropriate "standard mode" flags for the
                //       interpreter.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.Standard, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.Standard); /* throw */
#endif

                    createFlags |= CreateFlags.StandardAndHideNonStandard;
                }

                //
                // NOTE: Check for the use-attach environment variable.
                //       If it is set (to anything) then make sure the
                //       console will be attached if necessary.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.UseAttach, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.UseAttach); /* throw */
#endif

                    createFlags |= CreateFlags.UseAttach;
                }

                //
                // NOTE: Check for the no-color environment variable.
                //       If it is set (to anything) then make sure the
                //       console output will not be in color.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoColor, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoColor); /* throw */
#endif

                    createFlags |= CreateFlags.NoColor;
                }

                //
                // NOTE: Check for the no-title environment variable.
                //       If it is set (to anything) then skip setting the
                //       console title.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoTitle, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoTitle); /* throw */
#endif

                    createFlags |= CreateFlags.NoTitle;
                }

                //
                // NOTE: Check for the no-icon environment variable.
                //       If it is set (to anything) then skip setting the
                //       console icon.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoIcon, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoIcon); /* throw */
#endif

                    createFlags |= CreateFlags.NoIcon;
                }

                //
                // NOTE: Check for the no-profile environment variable.
                //       If it is set (to anything) then skip loading the
                //       host profile.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoProfile, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoProfile); /* throw */
#endif

                    createFlags |= CreateFlags.NoProfile;
                }

                //
                // NOTE: Check for the no-cancel environment variable.
                //       If it is set (to anything) then skip setting up the
                //       console script cancellation keypress, etc.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoCancel, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoCancel); /* throw */
#endif

                    createFlags |= CreateFlags.NoCancel;
                }

                //
                // NOTE: Check for the no-initialize environment variable.
                //       If it is set (to anything) then skip initialization
                //       of the interpreter.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoInitialize, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoInitialize);
#endif

                    createFlags &= ~CreateFlags.Initialize;
                }

                //
                // NOTE: Check for the no-throw-on-disposed environment variable.
                //       If it is set (to anything) then we will not throw exceptions
                //       when a disposed object is accessed.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoThrowOnDisposed, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoThrowOnDisposed);
#endif

                    createFlags &= ~CreateFlags.ThrowOnDisposed;
                }

                //
                // NOTE: Check for the no-utility environment variable.
                //       If it is set (to anything) then the native utility
                //       library will not be loaded.
                //
                if (GlobalState.GetEnvironmentVariable(
                        EnvVars.NoUtility, true, false, verbose) != null)
                {
#if CONSOLE
                    if (console && verbose)
                        Console.WriteLine(_Constants.Prompt.NoUtility); /* throw */
#endif

                    createFlags |= CreateFlags.NoUtility;
                }

                //
                // NOTE: Does the caller want to allow the CreateFlags to be
                //       overridden directly via the environment?
                //
                if (FlagOps.HasFlags(originFlags, OptionOriginFlags.Override, true))
                {
                    //
                    // NOTE: Check for the CreateFlags environment variable.
                    //       If it is set (and valid) then we will use it to
                    //       modify the creation flags for the interpreter.
                    //
                    string value = GlobalState.GetEnvironmentVariable(
                        EnvVars.CreateFlags, true, false, verbose);

                    if (!String.IsNullOrEmpty(value))
                    {
#if CONSOLE
                        if (console && verbose)
                            Console.WriteLine(String.Format(
                                _Constants.Prompt.CreateFlags, value));
#endif

                        object enumValue = null;
                        Result enumError = null;

                        enumValue = EnumOps.TryParseFlagsEnum(
                            null, typeof(CreateFlags), createFlags.ToString(),
                            value, null, true, true, ref enumError);

                        if (enumValue is CreateFlags)
                            createFlags = (CreateFlags)enumValue;
                        else
                            DebugOps.Complain(ReturnCode.Error, enumError);
                    }
                }
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: GetStartupCreateFlags: exited, argv = {1}, createFlags = {2}, " +
                "originFlags = {3}, console = {4}, verbose = {5}{6}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(true, true, argv),
                FormatOps.WrapOrNull(createFlags), FormatOps.WrapOrNull(originFlags),
                console, verbose, Environment.NewLine), typeof(Interpreter).Name);

            return createFlags;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // BUGBUG: This method is currently a no-op if the SHELL compile-time option is not defined.
        //
        public static ReturnCode GetStartupLibraryPath(
            IEnumerable<string> args,
            CreateFlags createFlags,
            OptionOriginFlags originFlags,
            bool console,
            bool verbose,
            ref string libraryPath,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Ok;
            StringList argv = (args != null) ? new StringList(args) : null;

            TraceOps.DebugTrace(String.Format(
                "{0}: GetStartupLibraryPath: entered, argv = {1}, createFlags = {2}, " +
                "originFlags = {3}, console = {4}, verbose = {5}, libraryPath = {6}, " +
                "code = {7}, error = {8}{9}", GlobalState.GetCurrentThreadId(),
                FormatOps.WrapOrNull(true, true, argv), FormatOps.WrapOrNull(createFlags),
                FormatOps.WrapOrNull(originFlags), console, verbose, FormatOps.WrapOrNull(
                libraryPath), code, FormatOps.WrapOrNull(true, true, error),
                Environment.NewLine), typeof(Interpreter).Name);

#if SHELL
            if (argv != null)
            {
                //
                // NOTE: Scan all the command line arguments, searching for the
                //       ones we are interested in (i.e. mainly those that must
                //       be processed prior to interpreter creation).
                //
                for (int index = 0; index < argv.Count; index++)
                {
                    //
                    // NOTE: Grab the current command line argument.
                    //
                    string arg = argv[index];

                    //
                    // NOTE: This is the number of switch chars in front of the
                    //       current argument.
                    //
                    int count = 0;

                    //
                    // NOTE: Trims any leading switch chars from the current
                    //       command line argument and sets the count to the
                    //       number of switch chars actually removed.
                    //
                    arg = StringOps.TrimSwitchChars(arg, ref count);

                    //
                    // NOTE: Check for the "library" command line option.  This
                    //       option is special because it must be done prior to
                    //       the interpreter being created in order for it to
                    //       take full effect.
                    //
                    if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Library))
                    {
                        //
                        // NOTE: There must be a path value after the option.
                        //
                        if ((index + 1) >= argv.Count)
                        {
                            error = String.Format(
                                "wrong # args: should be \"-{0} <directory>\"",
                                CommandLineOption.Library);

                            code = ReturnCode.Error;
                            break;
                        }

                        string localLibraryPath = argv[index + 1];

                        if (String.IsNullOrEmpty(localLibraryPath))
                            localLibraryPath = null;

                        libraryPath = localLibraryPath;
                        break;
                    }
                }
            }
#endif

            TraceOps.DebugTrace(String.Format(
                "{0}: GetStartupLibraryPath: exited, argv = {1}, createFlags = {2}, " +
                "originFlags = {3}, console = {4}, verbose = {5}, libraryPath = {6}, " +
                "code = {7}, error = {8}{9}", GlobalState.GetCurrentThreadId(),
                FormatOps.WrapOrNull(true, true, argv), FormatOps.WrapOrNull(createFlags),
                FormatOps.WrapOrNull(originFlags), console, verbose, FormatOps.WrapOrNull(
                libraryPath), code, FormatOps.WrapOrNull(true, true, error),
                Environment.NewLine), typeof(Interpreter).Name);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode ProcessStartupOptions(
            Interpreter interpreter,
            IEnumerable<string> args,
            CreateFlags createFlags,
            OptionOriginFlags originFlags,
            bool console,
            bool verbose,
            ref Result error
            )
        {
            bool initialize = false;

            return ProcessStartupOptions(interpreter, args, createFlags, originFlags,
                console, verbose, ref initialize, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode ProcessStartupOptions(
            Interpreter interpreter,
            IEnumerable<string> args,
            CreateFlags createFlags,
            OptionOriginFlags originFlags,
            bool console,
            bool verbose,
            ref bool initialize,
            ref Result error
            )
        {
            bool loop = false;

            return ProcessStartupOptions(interpreter, args, createFlags, originFlags,
                console, verbose, ref initialize, ref loop, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode ProcessStartupOptions(
            Interpreter interpreter,
            IEnumerable<string> args,
            CreateFlags createFlags,
            OptionOriginFlags originFlags,
            bool console,
            bool verbose,
            ref bool initialize,
            ref bool loop,
            ref Result error
            )
        {
            StringList argv = (args != null) ? new StringList(args) : null;

            TraceOps.DebugTrace(String.Format(
                "{0}: ProcessStartupOptions: entered, interpreter = {1}, argv = {2}, " +
                "createFlags = {3}, originFlags = {4}, console = {5}, " +
                "verbose = {6}, initialize = {7}, loop = {8}, error = {9}{10}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                FormatOps.WrapOrNull(true, true, argv), FormatOps.WrapOrNull(createFlags),
                FormatOps.WrapOrNull(originFlags), console, verbose, initialize, loop,
                FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                typeof(Interpreter).Name);

            try
            {
                if (interpreter != null)
                {
                    if (FlagOps.HasFlags(originFlags, OptionOriginFlags.Environment, true))
                    {
                        //
                        // NOTE: Check for the no-trace environment variable.  If it
                        //       is set (to anything) then we clear all the trace
                        //       listeners.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.NoTrace, true, false, verbose) != null) /* GLOBAL */
                        {
                            //
                            // NOTE: Attempt to clear the trace listeners now.
                            //
                            DebugOps.ClearTraceListeners( /* GLOBAL */
                                interpreter.Debug, console, verbose);
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the trace environment variable.
                        //       If it is set (to anything) then we add the console
                        //       trace listener so that we can see debugging output.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.Trace, true, false, verbose) != null) /* GLOBAL */
                        {
                            //
                            // NOTE: Attempt to setup the trace listeners in verbose
                            //       mode.  This may fail; however, the success and/or
                            //       failure messages will be displayed on the console
                            //       from inside the method.
                            //
                            DebugOps.SetupTraceListeners( /* GLOBAL */
                                true, interpreter.Debug, console, verbose);
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        string value;

                        ///////////////////////////////////////////////////////////////////////////////

                        #region Notification-Only [Global] Environment Variables
#if CONSOLE
                        if (console && verbose)
                        {
                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.DefaultQuiet, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.DefaultQuiet);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.Quiet, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.Quiet);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.DefaultTraceStack, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.DefaultTraceStack);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            value = GlobalState.GetEnvironmentVariable(
                                EnvVars.UtilityPath, true, false, verbose);

                            if (value != null)
                                Console.WriteLine(_Constants.Prompt.UtilityPath, value);

                            ///////////////////////////////////////////////////////////////////////////

                            value = GlobalState.GetEnvironmentVariable(
                                EnvVars.VendorPath, true, false, verbose);

                            if (value != null)
                                Console.WriteLine(_Constants.Prompt.VendorPath, value);

                            ///////////////////////////////////////////////////////////////////////////

                            value = GlobalState.GetEnvironmentVariable(
                                EnvVars.EllipsisLimit, true, false, verbose);

                            if (value != null)
                                Console.WriteLine(_Constants.Prompt.EllipsisLimit, value);

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.NoVerbose, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.NoVerbose);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.NoTrusted, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.NoTrusted);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.NoVerified, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.NoVerified);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.Throw, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.Throw);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.NeverGC, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.NeverGC);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.NeverWaitForGC, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.NeverWaitForGC);
                            }

                            ///////////////////////////////////////////////////////////////////////////

                            if (GlobalState.GetEnvironmentVariable(
                                    EnvVars.AlwaysWaitForGC, true, false, verbose) != null)
                            {
                                Console.WriteLine(_Constants.Prompt.AlwaysWaitForGC);
                            }
                        }
#endif
                        #endregion

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the trace-to-host environment variable.
                        //       If it is set (to anything) then set the trace-to-host
                        //       flag for the interpreter right now.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.TraceToHost, true, false, verbose) != null)
                        {
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(_Constants.Prompt.TraceToHost);
#endif

                            interpreter.InterpreterFlags |= InterpreterFlags.TraceToHost;
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the interactive environment variable.
                        //       If it is set (to anything) then set the
                        //       interactive flag for the interpreter right now.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.Interactive, true, false, verbose) != null)
                        {
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(_Constants.Prompt.Interactive);
#endif

                            interpreter.Interactive = true;
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the single-step environment variable.
                        //       If it is set (to anything) then set the single
                        //       step flag for the interpreter right now.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.Step, true, false, verbose) != null)
                        {
#if DEBUGGER
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(_Constants.Prompt.SingleStep);
#endif

                            interpreter.SingleStep = true;
#else
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(_Constants.Prompt.NoDebugger);
#endif
#endif
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the no-initialize environment variable.
                        //       If it is set (to anything) then skip initialization
                        //       of the interpreter.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.NoInitialize, true, false, verbose) != null)
                        {
#if CONSOLE
                            //
                            // NOTE: Do not bother notifying the user that the script
                            //       library initialization of the interpreter will
                            //       be skipped if it is likely that they have already
                            //       been notified (i.e. if the "Initialize" flag has
                            //       already been disabled via GetStartupCreateFlags).
                            //
                            if (console && verbose &&
                                FlagOps.HasFlags(createFlags, CreateFlags.Initialize, true))
                            {
                                Console.WriteLine(_Constants.Prompt.NoInitialize);
                            }
#endif

                            initialize = false;
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the no-loop environment variable.
                        //       If it is set (to anything) then skip entering
                        //       the interactive loop.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.NoLoop, true, false, verbose) != null)
                        {
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(_Constants.Prompt.NoLoop);
#endif

                            loop = false;
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the no-throw-on-disposed environment variable.
                        //       If it is set (to anything) then we will not throw exceptions
                        //       when a disposed object is accessed.
                        //
                        if (GlobalState.GetEnvironmentVariable(
                                EnvVars.NoThrowOnDisposed, true, false, verbose) != null) /* GLOBAL */
                        {
#if CONSOLE
                            if (console && verbose &&
                                FlagOps.HasFlags(createFlags, CreateFlags.ThrowOnDisposed, true))
                            {
                                Console.WriteLine(_Constants.Prompt.NoThrowOnDisposed);
                            }
#endif

                            Engine.SetThrowOnDisposed(null, false, false); /* GLOBAL */
                        }

                        ///////////////////////////////////////////////////////////////////////////////

                        //
                        // NOTE: Check for the InterpreterFlags environment variable.
                        //       If it is set (and valid) then we will use it to
                        //       modify the instance flags for the interpreter.
                        //
                        value = GlobalState.GetEnvironmentVariable(
                            EnvVars.InterpreterFlags, true, false, verbose);

                        if (!String.IsNullOrEmpty(value))
                        {
#if CONSOLE
                            if (console && verbose)
                                Console.WriteLine(String.Format(
                                    _Constants.Prompt.InterpreterFlags, value));
#endif

                            object enumValue = null;
                            Result enumError = null;

                            enumValue = EnumOps.TryParseFlagsEnum(
                                null, typeof(InterpreterFlags),
                                interpreter.InterpreterFlags.ToString(),
                                value, null, true, true, ref enumError);

                            if (enumValue is InterpreterFlags)
                                interpreter.InterpreterFlags = (InterpreterFlags)enumValue;
                            else
                                DebugOps.Complain(interpreter, ReturnCode.Error, enumError);
                        }
                    }

                    TraceOps.DebugTrace(String.Format(
                        "{0}: ProcessStartupOptions: exited, interpreter = {1}, argv = {2}, " +
                        "createFlags = {3}, originFlags = {4}, console = {5}, " +
                        "verbose = {6}, initialize = {7}, loop = {8}, error = {9}{10}",
                        GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                        FormatOps.WrapOrNull(true, true, argv), FormatOps.WrapOrNull(createFlags),
                        FormatOps.WrapOrNull(originFlags), console, verbose, initialize, loop,
                        FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                        typeof(Interpreter).Name);

                    return ReturnCode.Ok;
                }
                else
                {
                    error = "invalid interpreter";
                }
            }
            catch (Exception e)
            {
                error = e;
            }

#if CONSOLE
            if (console)
                Console.WriteLine(ResultOps.Format(ReturnCode.Error, error));
#endif

            TraceOps.DebugTrace(String.Format(
                "{0}: ProcessStartupOptions: exited, interpreter = {1}, argv = {2}, " +
                "createFlags = {3}, originFlags = {4}, console = {5}, " +
                "verbose = {6}, initialize = {7}, loop = {8}, error = {9}{10}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(interpreter),
                FormatOps.WrapOrNull(true, true, argv), FormatOps.WrapOrNull(createFlags),
                FormatOps.WrapOrNull(originFlags), console, verbose, initialize, loop,
                FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                typeof(Interpreter).Name);

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This is the "simplest" possible method that can
        //       be used to create an interpreter.
        //
        public static Interpreter Create( /* Example.Program */
            IEnumerable<string> args,
            ref Result result
            )
        {
            return Create(args, CreateFlags.Default, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            InterpreterSettings interpreterSettings,
            bool strict,
            ref Result result
            )
        {
            if (interpreterSettings != null)
            {
                return Create(
                    interpreterSettings.Args, interpreterSettings.Culture,
                    interpreterSettings.CreateFlags, interpreterSettings.ScriptFlags,
                    interpreterSettings.AppDomain, interpreterSettings.Host,
                    interpreterSettings.Profile, interpreterSettings.ApplicationObject,
                    interpreterSettings.PolicyObject, interpreterSettings.ResolverObject,
                    interpreterSettings.UserObject, interpreterSettings.Policies,
                    interpreterSettings.Traces, interpreterSettings.Text,
                    interpreterSettings.LibraryPath, interpreterSettings.AutoPathList,
                    ref result);
            }

            if (strict)
            {
                result = "invalid interpreter settings";
                return null;
            }

            return Create(ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            IEnumerable<string> args,
            CreateFlags createFlags,
            IHost host,
            ref Result result
            )
        {
            return Create(
                args, null, createFlags, ScriptFlags.Default, null, host, null,
                null, null, null, null, null, null, null, null, null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            IEnumerable<string> args,
            CreateFlags createFlags,
            ref Result result
            )
        {
            return Create(args, createFlags, (TraceList)null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            IEnumerable<string> args,
            CreateFlags createFlags,
            string libraryPath,
            ref Result result
            )
        {
            return Create(args, createFlags, null, libraryPath, null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            ref Result result
            )
        {
            return Create(null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create( /* [test2], Featherlight.Components.Private.CommonOps */
            IEnumerable<string> args,
            CreateFlags createFlags,
            string text,
            string libraryPath,
            StringList autoPathList,
            ref Result result
            )
        {
            return Create(
                args, createFlags, null, null, null, null, null, null, text,
                libraryPath, autoPathList, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static Interpreter Create( /* InterpreterHelper.Create */
            IEnumerable<string> args,
            CreateFlags createFlags,
            ScriptFlags scriptFlags,
            string text,
            string libraryPath,
            StringList autoPathList,
            ref Result result
            )
        {
            return Create(
                args, null, createFlags, scriptFlags, null, null, null, null,
                null, null, null, null, null, text, libraryPath, autoPathList,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create( /* Sample.Class1 */
            IEnumerable<string> args,
            CreateFlags createFlags,
            TraceList traces,
            ref Result result
            )
        {
            return Create(
                args, createFlags, null, null, null, null, null, traces, null,
                null, null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create( /* Eagle._Cmdlets.Script */
            IEnumerable<string> args,
            CreateFlags createFlags,
            object applicationObject,
            object policyObject,
            object resolverObject,
            object userObject,
            ExecuteCallbackDictionary policies,
            TraceList traces,
            string text,
            string libraryPath,
            StringList autoPathList,
            ref Result result
            )
        {
            return Create(
                args, null, createFlags, ScriptFlags.Default, null, null, null,
                applicationObject, policyObject, resolverObject, userObject,
                policies, traces, text, libraryPath, autoPathList, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static Interpreter Create( /* NOTE: INTERNAL DEBUGGER USE ONLY. */
            string culture,
            CreateFlags createFlags,
            AppDomain appDomain,
            ref Result result
            )
        {
            return Create(
                null, culture, createFlags, ScriptFlags.Default, appDomain,
                null, null, null, null, null, null, null, null, null, null,
                null, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter Create(
            IEnumerable<string> args,           // original arguments to the host application, where applicable.
            string culture,                     // currently, used only for parsing (error messages are same).
            CreateFlags createFlags,            // special creation flags.
            ScriptFlags scriptFlags,            // the default script flags used by the engine.
            AppDomain appDomain,                // pass null to use the current application domain.
            IHost host,                         // pass null to use the default host.
            string profile,                     // the host profile to load (pass null for none).
            object applicationObject,           // this is reserved for use by the application (pass null if not needed).
            object policyObject,                // this is reserved for use by custom policies (pass null if not needed).
            object resolverObject,              // this is reserved for use by custom resolvers (pass null if not needed).
            object userObject,                  // this is reserved for use by the user (pass null if not needed).
            ExecuteCallbackDictionary policies, // "safe" interpreter policies, if any.
            TraceList traces,                   // interpreter wide variable traces, if any.
            string text,                        // the "pre-init" (actually "post-setup") script, if any.
            string libraryPath,                 // location of the script library (i.e. "init" script).
            StringList autoPathList,            // extra dirs to check for packages.
            ref Result result                   // result of script library initialization or error upon failure.
            )
        {
            Interpreter interpreter = null;

            bool measureTime = FlagOps.HasFlags(
                createFlags, CreateFlags.MeasureTime, true);

            double microseconds = 0;
            long startCount = 0;
            long stopCount = 0;

            try
            {
                if (measureTime)
                    ProfileOps.Start(ref startCount, ref microseconds);

                StringList argv = (args != null) ? new StringList(args) : null;

                TraceOps.DebugTrace(String.Format(
                    "{0}: Create: argv = {1}, culture = {2}, createFlags = {3}, " +
                    "scriptFlags = {4}, appDomain = {5}, host = {6}, " +
                    "profile = {7}, applicationObject = {8}, policyObject = {9}, " +
                    "resolverObject = {10}, userObject = {11}, policies = {12}, " +
                    "traces = {13}, text = {14}, libraryPath = {15}, " +
                    "autoPathList = {16}, result = {17}{18}",
                    GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(true, true, argv),
                    FormatOps.WrapOrNull(culture), FormatOps.WrapOrNull(createFlags),
                    FormatOps.WrapOrNull(scriptFlags), FormatOps.WrapOrNull(appDomain),
                    FormatOps.WrapOrNull(host), FormatOps.WrapOrNull(profile),
                    FormatOps.WrapOrNull(applicationObject), FormatOps.WrapOrNull(policyObject),
                    FormatOps.WrapOrNull(resolverObject), FormatOps.WrapOrNull(userObject),
                    FormatOps.WrapOrNull(policies), FormatOps.WrapOrNull(traces),
                    FormatOps.WrapOrNull(text), FormatOps.WrapOrNull(libraryPath),
                    FormatOps.WrapOrNull(true, true, autoPathList),
                    FormatOps.WrapOrNull(true, true, result), Environment.NewLine),
                    typeof(Interpreter).Name);

                //
                // NOTE: Pause for them to attach a debugger, if requested.  For embedders, we
                //       really need the ability to break into the debugger here; otherwise,
                //       being able to easily attach a debugger at a predictable point becomes
                //       a problem.
                //
                if (FlagOps.HasFlags(createFlags, CreateFlags.BreakOnCreate, true) ||
                    ((GlobalState.GetEnvironmentVariable(EnvVars.Break, true, false) != null) &&
                     (Interlocked.Increment(ref breakCount) == 1)))
                {
#if CONSOLE
                    Console.WriteLine(String.Format(
                        _Constants.Prompt.Debugger,
                        RuntimeOps.GetCurrentProcessId()));

                    try
                    {
                        Console.ReadKey(true); /* throw */
                    }
                    catch (InvalidOperationException) // Console.ReadKey
                    {
                        // do nothing.
                    }
#endif

                    DebugOps.Break(); /* throw */
                }

                bool throwOnError = FlagOps.HasFlags(createFlags,
                    CreateFlags.ThrowOnError, true);

                try
                {
                    interpreter = new Interpreter();

                    lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                    {
                        GlobalState.PushActiveInterpreter(interpreter);

                        try
                        {
                            ReturnCode code = interpreter.PreSetup(
                                culture, createFlags, scriptFlags, appDomain,
                                host, profile, applicationObject, policyObject,
                                resolverObject, userObject, new StringDictionary(),
                                text, libraryPath, autoPathList, ref result);

                            //*****************************************************

                            if (code == ReturnCode.Ok)
                            {
                                code = interpreter.Setup(
                                    createFlags, args, policies, traces,
                                    ref result);
                            }

                            //*****************************************************
                            // WARNING: No scripts of any kind may be evaluated
                            //          using the interpreter until after this
                            //          point.
                            //*****************************************************

                            if (code == ReturnCode.Ok)
                            {
#if DEBUGGER
                                //
                                // NOTE: This must be prior to the Initialize()
                                //       call below if we want to be able to debug
                                //       the startup script.
                                //
                                // BUGFIX: Use the same host as we were passed,
                                //         never create a new one here.
                                //
                                if (FlagOps.HasFlags(
                                        createFlags, CreateFlags.Debugger, true))
                                {
                                    interpreter.Debugger = DebuggerOps.Create(
                                        !FlagOps.HasFlags(createFlags,
                                            CreateFlags.NoIsolated, true),
                                        culture, createFlags, interpreter.GetAppDomain(),
                                        interpreter.Host);
                                }
#endif

                                bool initialize = true;

                                if (FlagOps.HasFlags(
                                        createFlags, CreateFlags.Startup, true))
                                {
                                    code = ProcessStartupOptions(
                                        interpreter, args, createFlags,
                                        OptionOriginFlags.All,
                                        !FlagOps.HasFlags(createFlags,
                                            CreateFlags.NoHost, true) &&
                                        !FlagOps.HasFlags(createFlags,
                                            CreateFlags.NoConsole, true),
                                        true, ref initialize, ref result);
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: If script library initialization was
                                    //       requested, do it now.
                                    //
                                    if (initialize &&
                                        FlagOps.HasFlags(createFlags,
                                            CreateFlags.Initialize, true))
                                    {
                                        code = interpreter.PrivateInitialize(
                                            false, false, ref result);
                                    }
                                }
                            }

                            //*****************************************************

                            if (code == ReturnCode.Ok)
                            {
                                GlobalState.AddInterpreter(interpreter);

#if NOTIFY && NOTIFY_GLOBAL
                                if (interpreter.GlobalNotify)
                                    /* IGNORED */
                                    CheckNotifications(
                                        null, false,
                                        NotifyType.Interpreter, NotifyFlags.Added,
                                        new ObjectTriplet(culture, createFlags, host),
                                        interpreter, null, null, null, ref result);
#endif
                            }
                            else
                            {
                                interpreter.Dispose(); /* throw */
                                interpreter = null;
                            }

                            //*****************************************************

                            if ((interpreter == null) && throwOnError)
                            {
                                TraceOps.DebugTrace(String.Format(
                                    "{0}: Create: failure (with throw), " +
                                    "code = {1}, result = {2}{3}",
                                    GlobalState.GetCurrentThreadId(), code,
                                    FormatOps.WrapOrNull(true, true, result),
                                    Environment.NewLine), typeof(Interpreter).Name);

                                //
                                // NOTE: If we get to this point we have failed to
                                //       create and/or initialize the interpreter
                                //       AND they requested that we throw an
                                //       exception in that case.
                                //
                                throw new ScriptException(code, result, null);
                            }
                        }
                        finally
                        {
                            /* IGNORED */
                            GlobalState.PopActiveInterpreter();
                        }
                    }
                }
                catch (Exception e)
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: {1}{2}",
                        GlobalState.GetCurrentThreadId(),
                        e, Environment.NewLine),
                        typeof(Interpreter).Name);

                    if (interpreter != null)
                    {
                        interpreter.Dispose(); /* throw */
                        interpreter = null;
                    }

                    if (throwOnError)
                        throw;
                    else
                        result = e;
                }

                if (interpreter != null)
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: Create: success, interpreter = {1}, result = {2}{3}",
                        GlobalState.GetCurrentThreadId(),
                        FormatOps.WrapOrNull(interpreter),
                        FormatOps.WrapOrNull(true, true, result),
                        Environment.NewLine), typeof(Interpreter).Name);
                }
                else
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: Create: failure (without throw), interpreter = {1}, " +
                        "result = {2}{3}", GlobalState.GetCurrentThreadId(),
                        FormatOps.WrapOrNull(interpreter),
                        FormatOps.WrapOrNull(true, true, result),
                        Environment.NewLine), typeof(Interpreter).Name);
                }
            }
            finally
            {
                if (measureTime)
                {
                    ProfileOps.Stop(
                        startCount, ref stopCount, ref microseconds);

                    TraceOps.DebugTrace(String.Format(
                        "{0}: Create: return, interpreter = {1}, result = {2}, " +
                        "completed in {3}{4}", GlobalState.GetCurrentThreadId(),
                        FormatOps.WrapOrNull(interpreter), FormatOps.WrapOrNull(
                        true, true, result), FormatOps.Performance(microseconds),
                        Environment.NewLine), typeof(Interpreter).Name);

                }
            }

            return interpreter;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Pre-Setup
        private ReturnCode PreSetupCulture(
            string culture,
            bool specific,
            ref Result error
            )
        {
            //
            // NOTE: Empty string is valid here, we use it to select the current
            //       culture.
            //
            if (culture != null)
            {
                try
                {
                    //
                    // NOTE: Attempt to set the culture based on using the parameter
                    //       "culture" as a name (either neutral or specific).  Empty
                    //       string is valid here and selects the invariant culture.
                    //
                    if (specific)
                        cultureInfo = CultureInfo.CreateSpecificCulture(culture);
                    else
                        cultureInfo = CultureInfo.GetCultureInfo(culture);

                    return ReturnCode.Ok;
                }
                catch
                {
                    //
                    // NOTE: Ok, it was not a valid culture name, try to interpret the
                    //       parameter "culture" as an Id integer.
                    //
                    int cultureId = 0;

                    if (Value.GetInteger2(culture, ValueFlags.AnyInteger, null /* no culture yet! */,
                            ref cultureId, ref error) == ReturnCode.Ok)
                    {
                        try
                        {
                            cultureInfo = CultureInfo.GetCultureInfo(cultureId);

                            return ReturnCode.Ok;
                        }
                        catch (Exception e)
                        {
                            //
                            // NOTE: It parsed as a valid integer; however, the culture
                            //       specified by the Id was not found.
                            //
                            error = FormatOps.ErrorWithException(String.Format(
                                CultureInfoError, culture), e);

                            return ReturnCode.Error;
                        }
                    }
                    else
                    {
                        //
                        // NOTE: It did not parse as a valid integer, fail.
                        //
                        error = String.Format(CultureInfoError, culture);

                        return ReturnCode.Error;
                    }
                }
            }
            else
            {
                //
                // NOTE: Getting this property value is documented to never fail.
                //
                cultureInfo = CultureInfo.InvariantCulture;

                return ReturnCode.Ok;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Core class only.
        //
        internal ResourceManager ResourceManager
        {
            get { return resourceManager; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PreSetupResourceManager(ref Result error)
        {
            if (cultureInfo != null)
            {
                string resourceBaseName = GlobalState.GetResourceBaseName();

                if (resourceBaseName != null)
                {
                    try
                    {
                        //
                        // FIXME: PRI 4: Now that this resource management code
                        //        is in place and working properly, we need to
                        //        migrate all the error messages and other
                        //        static strings to be managed resources.  The
                        //        original intention was to do this right from
                        //        the start; however, time constraints prevented
                        //        that vision from becoming a reality.
                        //
                        resourceManager = new ResourceManager(
                            resourceBaseName, GlobalState.GetAssembly());

                        return ReturnCode.Ok;
                    }
                    catch (Exception e)
                    {
                        error = FormatOps.ErrorWithException(String.Format(
                            ResourceManagerError, resourceBaseName), e);
                    }
                }
                else
                {
                    error = InvalidBaseResourceName;
                }
            }
            else
            {
                error = InvalidCultureInfoError;
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PreSetupHost(
            IHost host,
            bool strict,
            ref Result error
            )
        {
            //
            // NOTE: Set the system default values for the "default" foreground
            //       and background colors now.  That way, even if there is no
            //       interpreter host or it decides not to do anything, these
            //       values will still be explicitly initialized.
            //
            defaultForegroundColor = _ConsoleColor.Default;
            defaultBackgroundColor = _ConsoleColor.Default;

            //
            // NOTE: If this IHost call fails, the caller will fail to setup
            //       the interpreter.  This is considered to be legitimate,
            //       even in non-strict mode, because IHost implementations are
            //       free to simply return "Ok" without having to do anything
            //       else (i.e. the default colors have already been set to the
            //       system defaults before this call).  Therefore, an IHost
            //       implementation that returns "Error" here is explicitly
            //       saying "the interpreter setup should fail".  Furthermore,
            //       we attempt to further minimize the risk of failure here
            //       by explicitly requesting the default hard-coded colors
            //       from the host (i.e. both the "foreground" and "background"
            //       boolean arguments are set to "false") because that should
            //       be even less likely to fail (and it _is_ less likely to
            //       fail with the "stock" implementation of this method,
            //       as provided by the _Hosts.Core host).
            //
            return HostOps.GetColors(
                host, ColorName.Default, false, false, strict,
                ref defaultForegroundColor, ref defaultBackgroundColor,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PreSetupNamespaces(
            bool enable,
            bool dispose,
            bool flags
            )
        {
            TraceOps.DebugTrace(String.Format(
                "{0}: PreSetupNamespaces: interpreter = {1}, " +
                "enable = {2}, dispose = {3}, flags = {4}{5}",
                GlobalState.GetCurrentThreadId(),
                FormatOps.WrapOrNull(this), enable, dispose, flags,
                Environment.NewLine), typeof(Interpreter).Name);

            ///////////////////////////////////////////////////////////////////////////////////////////

            //
            // HACK: Make 100% sure that we are not about to overwrite valid
            //       disposable object instances when enabling or disabling
            //       namespace support.
            //
            if (dispose)
                DisposeNamespaces();

            ///////////////////////////////////////////////////////////////////////////////////////////

            lock (syncRoot)
            {
                if (enable)
                {
                    if (globalNamespace == null)
                        globalNamespace = NamespaceOps.CreateGlobal(this);

                    if (pendingNamespaces == null)
                        pendingNamespaces = new Dictionary<string, INamespace>();

                    if (flags)
                        createFlags |= CreateFlags.UseNamespaces;
                }
                else if (flags)
                {
                    createFlags &= ~CreateFlags.UseNamespaces;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PreSetup(
            string culture,
            CreateFlags createFlags,
            ScriptFlags scriptFlags,
            AppDomain appDomain,
            IHost host,
            string profile,
            object applicationObject,
            object policyObject,
            object resolverObject,
            object userObject,
            StringDictionary runtimeOptions,
            string text,
            string libraryPath,
            StringList autoPathList,
            ref Result result
            )
        {
            #region Thread Affinity / AppDomain Identity
            //
            // NOTE: Keep track of the thread that this interpreter was created on.
            //
            this.Thread = Thread.CurrentThread;
            this.ThreadId = GlobalState.GetCurrentThreadId();
            this.VariableEvent = ThreadOps.CreateEvent(false);

            //
            // NOTE: What is the application domain for this interpreter?
            //
            this.appDomain = (appDomain != null) ?
                appDomain : AppDomain.CurrentDomain;
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Host Integration
            //
            // NOTE: Create and/or setup our host environment first because this
            //       will be used to communicate all other initialization failures.
            //
            if (host != null)
            {
                //
                // NOTE: Use the specified hosting environment.
                //
                this.host = host;
            }
            else if (!FlagOps.HasFlags(createFlags, CreateFlags.NoHost, true))
            {
                if (profile == null)
                    profile = GlobalState.GetEnvironmentVariable(
                        EnvVars.Profile, true, false);

                ///////////////////////////////////////////////////////////////////////////////////////

#if CONSOLE
                if (!String.IsNullOrEmpty(profile))
                {
                    Console.WriteLine(String.Format(
                        _Constants.Prompt.Profile, profile));
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (FlagOps.HasFlags(
                        createFlags, CreateFlags.CloseConsole, true))
                {
                    ReturnCode consoleCode;
                    Result consoleError = null;

#if NATIVE && WINDOWS
                    if (PlatformOps.IsWindowsOperatingSystem())
                    {
                        consoleCode = NativeConsole.Close(ref consoleError);
                    }
                    else
                    {
                        consoleError = "not implemented";
                        consoleCode = ReturnCode.Error;
                    }
#else
                    consoleError = "not implemented";
                    consoleCode = ReturnCode.Error;
#endif

                    if (consoleCode != ReturnCode.Ok)
                        DebugOps.Complain(this, consoleCode, consoleError);
                }

                ///////////////////////////////////////////////////////////////////////////////////////

                if (FlagOps.HasFlags(
                        createFlags, CreateFlags.OpenConsole, true))
                {
                    ReturnCode consoleCode;
                    Result consoleError = null;

#if NATIVE && WINDOWS
                    if (PlatformOps.IsWindowsOperatingSystem())
                    {
                        consoleCode = NativeConsole.AttachOrOpen(
                            FlagOps.HasFlags(createFlags,
                            CreateFlags.ForceConsole, true),
                            FlagOps.HasFlags(createFlags,
                            CreateFlags.AttachConsole, true),
                            ref consoleError);
                    }
                    else
                    {
                        consoleError = "not implemented";
                        consoleCode = ReturnCode.Error;
                    }
#else
                    consoleError = "not implemented";
                    consoleCode = ReturnCode.Error;
#endif

                    if (consoleCode != ReturnCode.Ok)
                        DebugOps.Complain(this, consoleCode, consoleError);
                }
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

                //
                // NOTE: *HOOK* Allow the default host to be overridden by
                //       an external application or third-party plugin.
                //
                NewHostCallback callback = NewHostCallback; /* STATIC */

                if (callback != null)
                {
                    this.host = HostOps.NewCustom(
                        callback, this, null, profile, createFlags);
                }
                else
                {
#if CONSOLE
                    //
                    // NOTE: Use the default hosting environment (optimized
                    //       for console apps, like the interactive shell).
                    //
                    if (!FlagOps.HasFlags(
                            createFlags, CreateFlags.NoConsole, true))
                    {
                        this.host = HostOps.NewConsole(
                            this, null, profile, createFlags);
                    }
                    else
#endif
                    {
                        this.host = HostOps.NewDiagnostic(
                            this, null, profile, createFlags);
                    }
                }
            }
            else
            {
                this.host = null;
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Application Integration
            //
            // NOTE: Set the application and user objects now, in case they are necessary
            //       during the later phases of interpreter initialization (e.g. for use
            //       with a custom security policy callback).
            //
            this.applicationObject = applicationObject;
            this.policyObject = policyObject;
            this.resolverObject = resolverObject;
            this.userObject = userObject;
            this.runtimeOptions = runtimeOptions;
            this.throwOnFeatureNotSupported = RuntimeOps.DefaultThrowOnFeatureNotSupported;
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            //
            // NOTE: We must have a culture and resource manager setup before we do anything
            //       further because they are required to get access to our string resources
            //       (error messages, etc).
            //
            if ((PreSetupCulture(culture, false, ref result) == ReturnCode.Ok) &&
                (PreSetupResourceManager(ref result) == ReturnCode.Ok) &&
                (PreSetupHost(this.host, false, ref result) == ReturnCode.Ok))
            {
                #region Public Properties
                this.ReadOnly = false;
                this.ReadyLimit = DefaultReadyLimit;
                this.RecursionLimit = DefaultRecursionLimit;
                this.Timeout = DefaultTimeout;
                this.FinallyTimeout = DefaultFinallyTimeout;
                this.SleepTime = _Public.EventManager.DefaultSleepTime;
                this.ExitCode = ResultOps.SuccessExitCode();
                this.DateTimeFormat = Value.DefaultDateTimeFormat;
                this.DateTimeKind = Value.DefaultDateTimeKind;
                this.Quiet = DebugOps.GetDefaultQuiet(DefaultQuiet);
                this.CommandDecision = PolicyDecision.None;
                this.ScriptDecision = PolicyDecision.None;
                this.FileDecision = PolicyDecision.None;
                this.StreamDecision = PolicyDecision.None;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Script Library Pre-Initialization
                preInitializeText = text;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Script Library Paths
                this.libraryPath = libraryPath;
                this.autoPathList = autoPathList;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Script Library Miscellaneous
                preSetup = false;
                setup = false;
                initialized = false;
                initializedPath = null;
                initializedShell = false;
                initializedShellPath = null;
                trustedPaths = new StringList();
                trustedTypes = new ObjectDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Flags
                this.createFlags = createFlags;
                this.scriptFlags = scriptFlags;

                ///////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
                cacheFlags = CacheFlags.Default;
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

                interpreterFlags = InterpreterFlags.Default;
                readyFlags = ReadyFlags.None;
                engineFlags = EngineFlags.None;
                substitutionFlags = SubstitutionFlags.Default;
                expressionFlags = ExpressionFlags.Default;
                afterEventFlags = EventFlags.After;
                engineEventFlags = EventFlags.Default;
                queueEventFlags = EventFlags.Queue;
                serviceEventFlags = EventFlags.Service;
                updateEventFlags = EventFlags.Wait;
                waitEventFlags = EventFlags.Wait;

                ///////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER || SHELL
                headerFlags = HeaderFlags.Invalid;
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if SHELL && INTERACTIVE_COMMANDS
                interactiveEngineFlags = EngineFlags.None;
                interactiveSubstitutionFlags = SubstitutionFlags.None;
                interactiveEventFlags = EventFlags.None;
                interactiveExpressionFlags = ExpressionFlags.None;
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

                newGlobalVariableFlags = VariableFlags.None;
                newLocalVariableFlags = VariableFlags.None;

                ///////////////////////////////////////////////////////////////////////////////////////

                procedureFlags = ProcedureFlags.None;
                pluginFlags = PluginFlags.None;

                ///////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
                notifyTypes = NotifyType.None;
                notifyFlags = NotifyFlags.None;

                //
                // NOTE: For now, default the "global" notification setting to
                //       enabled.  This can be overridden prior to any "global"
                //       notifications being fired by changing this setting
                //       from the "init" script or by using the NoGlobalNotify
                //       flag.
                //
                notify = !FlagOps.HasFlags(createFlags, CreateFlags.NoGlobalNotify, true);
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Plugin Tokens
                corePluginToken = 0;

#if NOTIFY || NOTIFY_OBJECT
                objectPluginToken = 0;
#endif

#if DEBUG
                testPluginToken = 0;
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Core Entities
                //
                // NOTE: How many discrete operations have been executed?
                //
                operationCount = 0;

                //
                // NOTE: How many commands have been executed?
                //
                commandCount = 0;

                //
                // NOTE: How many readiness checks have been executed?
                //
                readyCount = 0;

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Packages
                packageIndexes = new PackageIndexDictionary();
                packages = new PackageWrapperDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Namespaces
                PreSetupNamespaces(AreNamespacesEnabled(), true, false);
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Core Extensibility
                pluginArguments = new StringDictionary();
                plugins = new PluginWrapperDictionary();
                commands = new CommandWrapperDictionary();
                hiddenCommands = new CommandWrapperDictionary();
                policies = new PolicyWrapperDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Executable Objects
                procedures = new ProcedureWrapperDictionary();
                hiddenProcedures = new ProcedureWrapperDictionary();

                #region Dead Code
#if DEAD_CODE
                lambdas = new LambdaWrapperDictionary();
#endif
                #endregion

                executes = new ExecuteWrapperDictionary();
                hiddenExecutes = new ExecuteWrapperDictionary();
                operators = new OperatorWrapperDictionary();
                functions = new FunctionWrapperDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Event Manager
                //
                // NOTE: Create the event manager now.
                //
                eventManager = new EventManager(this);

                //
                // NOTE: Initialize the count of pending wait calls to zero.
                //
                waitCount = 0;

                //
                // NOTE: How many times have we waited for an event (in WaitVariable)?
                //
                waitSpinCount = 0;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Variable Traces
                traces = new TraceWrapperDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Variable Scopes
                scopes = new CallFrameDictionary();
                #endregion
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region CLR Integration
                binder = new ScriptBinder(this, null, this.Debug);
                objects = new ObjectWrapperDictionary();
                aliases = new AliasWrapperDictionary();
                callbacks = new CallbackDictionary();

                ///////////////////////////////////////////////////////////////////////////////////////

                objectTypes = new StringDictionary();

                objectNamespaces = new StringDictionary(
                    (IDictionary<string, string>)Value.DefaultObjectNamespaces); /* COPY */

                objectInterfaces = new TypePairDictionary<string, long>();

                objectAliasNamespaces = new StringDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Interpreters
                masterInterpreter = null;
                slaveName = null;

#if APPDOMAINS && ISOLATED_INTERPRETERS
                slaveAppDomainName = null;
#endif

                slaveInterpreters = new InterpreterDictionary();
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Other Entities
#if DATA
                connections = new DbConnectionDictionary();
                transactions = new DbTransactionDictionary();
#endif

#if CALLBACK_QUEUE
                callbackQueue = new CallbackQueue();
#endif

#if APPDOMAINS
                appDomains = new AppDomainDictionary();
#endif

#if LIST_CACHE
                stringListCache = new StringListDictionary(true);
#endif

#if PARSE_CACHE
                parseStateCache = new ParseStateDictionary();

                #region Dead Code
#if DEAD_CODE
                expressionStateCache = new ExpressionStateDictionary();
#endif
                #endregion
#endif

#if EXECUTE_CACHE
                executeCache = new ExecuteCache();
                hiddenExecuteCache = new ExecuteCache();
#endif

#if TYPE_CACHE
                typeCache = new TypeDictionary();
#endif

#if COM_TYPE_CACHE
                comTypeListCache = new IntPtrTypeListDictionary();
#endif

#if NATIVE && TCL
                lock (tclSyncRoot) // NOTE: Pedantic.
                {
                    tclInterps = new IntPtrDictionary();

#if TCL_THREADS
                    tclThreads = new TclThreadDictionary();
#endif

                    tclBridges = new TclBridgeDictionary();
                }
#endif

#if NATIVE && LIBRARY
                modules = new ModuleWrapperDictionary();
                delegates = new DelegateWrapperDictionary();
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Random Number Generators
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoRandom, true))
                {
                    random = new Random();
                    randomNumberGenerator = RNGCryptoServiceProvider.Create();
                }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Object Identifiers
#if RANDOMIZE_ID
                //
                // NOTE: If possible, randomize the starting Id for objects.
                //
                nextId = (random != null) ? Math.Abs(random.Next()) : 0;
#else
                nextId = 0;
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Script Error Handling
                unknown = TclVars.Unknown;
                backgroundError = TclVars.BackgroundError;
                packageUnknown = TclVars.PackageUnknown;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Channels & Encodings
                channels = new ChannelDictionary();

                //
                // NOTE: Initialize the "well-known" encodings.
                //
                encodings = new EncodingDictionary(new _Comparers.Custom(
                    StringOps.SystemNoCaseStringComparisonType));

                encodings.Add(Channel.NullEncodingName, null);
                encodings.Add(Channel.BinaryEncodingName, Channel.BinaryEncoding);
                encodings.Add(Channel.DefaultEncodingName, Channel.DefaultEncoding);
                encodings.Add(Channel.SystemDefaultEncodingName, Encoding.Default);
                encodings.Add(IdentityEncoding.webName, IdentityEncoding.Identity);
                encodings.Add(OneByteEncoding.webName, OneByteEncoding.OneByte);
                encodings.Add(TwoByteEncoding.webName, TwoByteEncoding.TwoByte);
                encodings.Add(TclEncoding.webName, TclEncoding.Tcl);
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Static Lock Held
                lock (staticSyncRoot)
                {
#if NATIVE && WINDOWS
                    #region Native Stack Checking
                    RuntimeOps.InitializeStackChecking();
                    #endregion
#endif

                    ///////////////////////////////////////////////////////////////////////////////////

#if THREADING
                    ContextManager.Initialize();
#endif

                    ///////////////////////////////////////////////////////////////////////////////////

#if NATIVE && TCL
                    #region Transfer Global Tcl/Tk Integration Data
                    //
                    // NOTE: If this thread (i.e. the primary thread for this
                    //       interpreter) is the same as the thread for the
                    //       dead Tcl objects in the global cache, transfer
                    //       them to us now.
                    //
                    if (!FlagOps.HasFlags(createFlags, CreateFlags.NoTclTransfer, true))
                    {
                        lock (tclSyncRoot)
                        {
                            if (IsPrimaryThread(deadTclThreadId))
                            {
                                ResultList errors = null;

                                ///////////////////////////////////////////////////////////////////////

                                if (deadTclThreadId != 0)
                                    deadTclThreadId = 0;

                                ///////////////////////////////////////////////////////////////////////

                                if (deadTclApi != null)
                                {
                                    tclApi = deadTclApi;
                                    deadTclApi = null;

                                    if (errors == null)
                                        errors = new ResultList();

                                    errors.Add("recovered dead Tcl API object");
                                }

                                ///////////////////////////////////////////////////////////////////////

                                if (deadTclInterps != null)
                                {
                                    if (tclInterps != null)
                                        tclInterps.Add(deadTclInterps);

                                    if (errors == null)
                                        errors = new ResultList();

                                    errors.Add(String.Format(
                                        "recovered {0} dead Tcl interpreters: {1}",
                                        deadTclInterps.Count, deadTclInterps));

                                    deadTclInterps.Clear();
                                    deadTclInterps = null;
                                }

                                ///////////////////////////////////////////////////////////////////////

#if TCL_THREADS
                                if (deadTclThreads != null)
                                {
                                    if (tclThreads != null)
                                        tclThreads.Add(deadTclThreads);

                                    errors.Add(String.Format(
                                        "recovered {0} dead Tcl threads: {1}",
                                        deadTclThreads.Count, deadTclThreads));

                                    deadTclThreads.Clear();
                                    deadTclThreads = null;
                                }
#endif

                                ///////////////////////////////////////////////////////////////////////

                                if (deadTclBridges != null)
                                {
                                    if (tclBridges != null)
                                        tclBridges.Add(deadTclBridges);

                                    errors.Add(String.Format(
                                        "recovered {0} dead Tcl bridges: {1}",
                                        deadTclBridges.Count, deadTclBridges));

                                    deadTclBridges.Clear();
                                    deadTclBridges = null;
                                }

                                ///////////////////////////////////////////////////////////////////////

                                if ((errors != null) && (errors.Count > 0))
                                {
                                    errors.Insert(0, String.Format(
                                        "interpreter \"{0}\" from thread {1}",
                                        this, threadId));

                                    DebugOps.Complain(this, ReturnCode.Error, errors);
                                }
                            }
                        }
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Initialize Global Tcl/Tk Integration Data
                    lock (tclSyncRoot)
                    {
                        if (deadTclInterps == null)
                            deadTclInterps = new IntPtrDictionary();

#if TCL_THREADS
                        if (deadTclThreads == null)
                            deadTclThreads = new TclThreadDictionary();
#endif

                        if (deadTclBridges == null)
                            deadTclBridges = new TclBridgeDictionary();
                    }
                    #endregion
#endif
                }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Context Manager (Threaded Only)
#if THREADING
                //
                // NOTE: This must be done AFTER the static Initialize method
                //       of the ContextManager class has been called (above).
                //
                contextManager = new ContextManager(this);
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Call Stack (Non-Threaded Only)
#if !THREADING
                CallStack = new CallStack(this.RecursionLimit);
                GlobalFrame = NewGlobalCallFrame(CallStack);

                PushGlobalCallFrame(false); // NOTE: This call frame is never popped.
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Command & Variable Resolvers
                //
                // NOTE: For now, just add the core resolver.  This must refer
                //       to the "GlobalFrame" property so that it gets created
                //       now, if necessary.
                //
                resolvers = new List<IResolve>(new IResolve[] {
                    RuntimeOps.NewResolver(this, GlobalFrame, globalNamespace, createFlags)
                });
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Engine Non-Context Members
                Cancel = false;
                Unwind = false;
                Halt = false;

                CancelResult = null;
                HaltResult = null;
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Engine Context Members
#if !THREADING
                Levels = 0;
                ParserLevels = 0;
                ExpressionLevels = 0;
                UnknownLevels = 0;
                TraceLevels = 0;

#if DEBUGGER
                WatchpointLevels = 0;
#endif

#if NOTIFY || NOTIFY_OBJECT
                NotifyLevels = 0;
                NotifyTypes = NotifyType.None;
                NotifyFlags = NotifyFlags.None;
#endif

                PolicyLevels = 0;
                TestLevels = 0;

#if DEBUGGER
                Debugger = null;
#endif

#if PREVIOUS_RESULT
                PreviousResult = null;
#endif

                SharedEngineFlags = EngineFlags.None;

                ParseState = null;

                ReturnCode = ReturnCode.Ok;

                ErrorLine = 0;
                ErrorCode = null;
                ErrorInfo = null;

                ScriptLocation = null;
                ScriptLocations = new StackList<IScriptLocation>();

                PreviousProcessId = 0;

                ArraySearches = new ArraySearchDictionary();

#if HISTORY
                HistoryEngineFilter = null;
                _History = new ClientDataList();
#endif

                Complaint = null;
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Interactive Context Members
#if !THREADING
#if HISTORY
                HistoryLoadData = null;
                HistorySaveData = null;

                HistoryInfoFilter = null;
                HistoryLoadFilter = null;
                HistorySaveFilter = null;

                HistoryFileName = null;
#endif
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Test Context Members
#if !THREADING
                //
                // NOTE: Initialize the test related data.
                //
                TestStatistics = new int[(int)TestInformationType.SizeOf];
                TestConstraints = new StringList();
                TestSkipped = new StringList();
                TestFailures = new StringList();
                TestCounts = new IntDictionary();
                TestMatch = new StringList(); /* TODO: Should this default to all (*)? */
                TestSkip = new StringList();
                TestReturnCodeMessages = TestOps.GetReturnCodeMessages();

#if DEBUGGER
                TestBreakpoints = new StringDictionary();
#endif
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

                preSetup = true;
                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Setup
#if DEBUGGER
        private static ReturnCode SetupDebuggerHost(
            Interpreter interpreter,
            IHost host,
            ref Result error
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    //
                    // NOTE: If this interpreter has no debugger then we
                    //       can simply do nothing.
                    //
                    IDebugger debugger = interpreter.Debugger;

                    if (debugger != null)
                    {
                        //
                        // NOTE: Extract the isolated debugger interpreter
                        //       and check its validity.
                        //
                        Interpreter debugInterpreter = debugger.Interpreter;

                        if (debugInterpreter != null)
                        {
                            try
                            {
                                //
                                // NOTE: If the provided host is valid, clone it
                                //       into the isolated debugger interpreter;
                                //       otherwise, just use the provided null
                                //       value (i.e. if the parent interpreter
                                //       does not have a valid host then the
                                //       isolated debugger interpreter should not
                                //       have one either).
                                //
                                IHost newHost = (host != null) ?
                                    host.Clone(debugInterpreter) : null;

                                //
                                // NOTE: Set the host for the isolated debugger
                                //       interpreter (may be null).
                                //
                                debugInterpreter.Host = newHost;

                                //
                                // NOTE: If we set the host for the isolated
                                //       debugger interpreter to a non-null value,
                                //       create the standard channels for it now;
                                //       otherwise, we are totally done.
                                //
                                if (newHost != null)
                                    return SetupHostChannels(
                                        debugInterpreter, newHost, true, ref error);
                                else
                                    return ReturnCode.Ok;
                            }
                            catch (Exception e)
                            {
                                error = e;
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Ok, the debugger interpreter is not available.
                            //       This is not an error.
                            //
                            return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        //
                        // NOTE: Ok, the debugger is not available.  This is not
                        //       an error.
                        //
                        return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetupTraces(
            TraceList traces,
            IClientData clientData,
            ref Result error
            )
        {
            if (traces != null)
            {
                foreach (ITrace trace in traces)
                {
                    Result localResult = null;

                    if (AddTrace(trace, clientData,
                            ref localResult) != ReturnCode.Ok)
                    {
                        error = localResult;
                        return ReturnCode.Error;
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid traces";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetupPolicies(
            ExecuteCallbackDictionary policies,
            IPlugin plugin,
            IClientData clientData,
            ref Result error
            )
        {
            if (policies != null)
            {
                foreach (KeyValuePair<string, ExecuteCallback> pair in policies)
                {
                    Result localResult = null;

                    if (AddPolicy(pair.Value, plugin, clientData,
                            ref localResult) != ReturnCode.Ok)
                    {
                        error = localResult;
                        return ReturnCode.Error;
                    }
                }

                return ReturnCode.Ok;
            }
            else
            {
                error = "invalid policies";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Assumes the interpreter lock is held.
        //
        internal ReturnCode SetupVariables(
            CreateFlags createFlags,
            IEnumerable<string> args,
            bool strict,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (!FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
            {
                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue(
                        VariableFlags.None, TclVars.VersionName,
                        TclVars.VersionValue, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue(
                        VariableFlags.None, TclVars.PatchLevelName,
                        TclVars.PatchLevelValue, ref result);

                if (code == ReturnCode.Ok)
                    code = SetVariableValue(
                        Engine.ErrorCodeVariableFlags, TclVars.ErrorCode,
                        null, ref result);

                if (code == ReturnCode.Ok)
                    code = SetVariableValue(
                        Engine.ErrorInfoVariableFlags, TclVars.ErrorInfo,
                        null, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue(
                        VariableFlags.None, TclVars.PrecisionName,
                        TclVars.PrecisionValue.ToString(), precisionTraceList,
                        ref result);

                if (code == ReturnCode.Ok)
                {
                    if (!FlagOps.HasFlags(createFlags, CreateFlags.Safe, true))
                    {
                        if (args != null)
                        {
                            StringList arguments = new StringList(args);

                            if (code == ReturnCode.Ok)
                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.ShellArgumentCount,
                                    arguments.Count.ToString(), ref result);

                            if (code == ReturnCode.Ok)
                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.ShellArguments,
                                    arguments.ToString(), ref result);
                        }
                        else if (FlagOps.HasFlags(
                                createFlags, CreateFlags.SetArguments, true))
                        {
                            if (code == ReturnCode.Ok)
                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.ShellArgumentCount,
                                    0.ToString(), ref result);

                            if (code == ReturnCode.Ok)
                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.ShellArguments,
                                    null, ref result);
                        }

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue(
                                VariableFlags.None, TclVars.ShellArgument0,
                                PathOps.GetExecutableName(), ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue(
                                VariableFlags.None, TclVars.RunCommandsFileName,
                                TclVars.RunCommandsFileValue, ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue(
                                VariableFlags.None, TclVars.NonWordCharacters,
                                null, ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue(
                                VariableFlags.None, TclVars.WordCharacters,
                                null, ref result);

                        if ((code == ReturnCode.Ok) && initialized)
                            code = SetLibraryVariableValue(
                                VariableFlags.None, TclVars.AutoPath,
                                GlobalState.GetAutoPathList(this, false).ToString(),
                                autoPathTraceList, ref result);

                        if (code == ReturnCode.Ok)
                            code = AddLibraryVariable(
                                VariableFlags.None, TclVars.AutoSourcePath,
                                null, strict, ref result);

                        if (code == ReturnCode.Ok)
                            code = AddLibraryVariable(VariableFlags.Array,
                                TclVars.Environment, environmentTraceList, strict,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = AddLibraryVariable(VariableFlags.Array,
                                Vars.Tests, testsTraceList, strict, ref result);

                        if (code == ReturnCode.Ok)
                            code = AddLibraryVariable(VariableFlags.Array,
                                Vars.Paths, null, strict, ref result);

                        if (code == ReturnCode.Ok)
                            code = AddLibraryVariable(VariableFlags.Array,
                                TclVars.AutoIndex, null, strict, ref result);
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetupFunctions(
            CreateFlags createFlags,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (!FlagOps.HasFlags(createFlags, CreateFlags.NoFunctions, true))
            {
                IPlugin plugin = GetCorePlugin(ref result);

                if (plugin != null)
                {
                    code = AddFunction(
                        null, "abs", Value.numberTypes, FunctionFlags.None,
                        plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "acos", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "asin", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "atan", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "atan2", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "bool", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "ceil", Value.nonIntegralTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "cos", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "cosh", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "datetime", Value.allTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "decimal", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "double", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "e", null, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "epsilon", null, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "exp", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "flags", Value.stringTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "floor", Value.nonIntegralTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "fmod", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "hypot", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "int", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "list", Value.allTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "log", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "log10", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "log2", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "logx", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "max", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "min", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "pi", null, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "pow", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "rand", null, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "random", null, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "randstr", Value.integerTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "round", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "round2", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "round3", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "sign", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "sin", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "sinh", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "sqrt", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "srand", Value.integerTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "tan", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "tanh", Value.floatTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "timespan", Value.allTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "truncate", Value.nonIntegralTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "typeof", Value.allTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddFunction(
                            null, "wide", Value.numberTypes, FunctionFlags.None,
                            plugin, ClientData.Empty, false, ref result);
                }
                else
                {
                    code = ReturnCode.Error;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode SetupOperators(
            CreateFlags createFlags,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (!FlagOps.HasFlags(createFlags, CreateFlags.NoOperators, true))
            {
                IPlugin plugin = GetCorePlugin(ref result);

                if (plugin != null)
                {
                    if (code == ReturnCode.Ok)
                        //
                        // NOTE: *VERY SPECIAL CASE* This operator is handled directly
                        //       by the expression engine; therefore, we specify the
                        //       default operator here (which does nothing).
                        //
                        code = AddOperator(
                            typeof(_Operators.Core), Operators.Question, Lexeme.Question,
                            null, OperatorFlags.Special | OperatorFlags.Standard, plugin,
                            ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseAnd), Operators.BitwiseAnd,
                            Lexeme.BitwiseAnd, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseEqv), Operators.BitwiseEqv,
                            Lexeme.BitwiseEqv, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseImp), Operators.BitwiseImp,
                            Lexeme.BitwiseImp, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseNot), Operators.BitwiseNot,
                            Lexeme.BitwiseNot, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseOr), Operators.BitwiseOr,
                            Lexeme.BitwiseOr, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.BitwiseXor), Operators.BitwiseXor,
                            Lexeme.BitwiseXor, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Divide), Operators.Divide,
                            Lexeme.Divide, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Equal), Operators.Equal,
                            Lexeme.Equal, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Exponent), Operators.Exponent,
                            Lexeme.Exponent, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.GreaterThan), Operators.GreaterThan,
                            Lexeme.GreaterThan, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.GreaterThanOrEqualTo), Operators.GreaterThanOrEqualTo,
                            Lexeme.GreaterThanOrEqualTo, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LeftRotate), Operators.LeftRotate,
                            Lexeme.LeftRotate, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LeftShift), Operators.LeftShift,
                            Lexeme.LeftShift, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LessThan), Operators.LessThan,
                            Lexeme.LessThan, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LessThanOrEqualTo), Operators.LessThanOrEqualTo,
                            Lexeme.LessThanOrEqualTo, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.ListIn), Operators.ListIn,
                            Lexeme.ListIn, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.ListNotIn), Operators.ListNotIn,
                            Lexeme.ListNotIn, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalAnd), Operators.LogicalAnd,
                            Lexeme.LogicalAnd, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalEqv), Operators.LogicalEqv,
                            Lexeme.LogicalEqv, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalImp), Operators.LogicalImp,
                            Lexeme.LogicalImp, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalNot), Operators.LogicalNot,
                            Lexeme.LogicalNot, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalOr), Operators.LogicalOr,
                            Lexeme.LogicalOr, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.LogicalXor), Operators.LogicalXor,
                            Lexeme.LogicalXor, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Minus), Operators.Minus,
                            Lexeme.Minus, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Modulus), Operators.Modulus,
                            Lexeme.Modulus, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Multiply), Operators.Multiply,
                            Lexeme.Multiply, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.NotEqual), Operators.NotEqual,
                            Lexeme.NotEqual, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.Plus), Operators.Plus,
                            Lexeme.Plus, Value.numberTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.RightRotate), Operators.RightRotate,
                            Lexeme.RightRotate, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.RightShift), Operators.RightShift,
                            Lexeme.RightShift, Value.integralTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.StringEqual), Operators.StringEqual,
                            Lexeme.StringEqual, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);

                    if (code == ReturnCode.Ok)
                        code = AddOperator(
                            typeof(_Operators.StringNotEqual), Operators.StringNotEqual,
                            Lexeme.StringNotEqual, Value.allTypes, OperatorFlags.None,
                            plugin, ClientData.Empty, false, ref result);
                }
                else
                {
                    code = ReturnCode.Error;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode SetupHostChannels(
            Interpreter interpreter,
            IStreamHost streamHost,
            bool replace,
            ref Result error
            )
        {
            if (interpreter != null)
            {
                return interpreter.AddStandardChannels(
                    streamHost, null, ChannelType.All, replace, false, ref error);
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Assumes the interpreter lock is held.
        //
        private ReturnCode Setup(
            CreateFlags createFlags,
            IEnumerable<string> args,
            ExecuteCallbackDictionary policies,
            TraceList traces,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Standard Channels
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoHost, true) &&
                    !FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) &&
                    !FlagOps.HasFlags(createFlags, CreateFlags.NoChannels, true))
                {
                    code = AddStandardChannels(
                        host, null, ChannelType.All, false, false, ref result);
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Core Plugins
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoPlugins, true))
                {
                    IPlugin plugin = null;

                    if ((code == ReturnCode.Ok) &&
                        !FlagOps.HasFlags(createFlags, CreateFlags.NoCorePlugin, true))
                    {
                        if (code == ReturnCode.Ok)
                        {
                            plugin = NewCorePlugin();

                            if (plugin != null)
                            {
                                Result localResult = null;

                                code = RuntimeOps.PrepareStaticPlugin(plugin, ref localResult);

                                if (code == ReturnCode.Ok)
                                    code = AddPlugin(plugin, null, ref corePluginToken, ref localResult);

                                if (code != ReturnCode.Ok)
                                    result = localResult;
                            }
                            else
                            {
                                result = "invalid core plugin";
                                code = ReturnCode.Error;
                            }
                        }
                    }

#if NOTIFY || NOTIFY_OBJECT
                    if ((code == ReturnCode.Ok) &&
                        !FlagOps.HasFlags(createFlags, CreateFlags.NoObjectPlugin, true))
                    {
                        plugin = NewObjectPlugin();

                        if (plugin != null)
                        {
                            Result localResult = null;

                            code = RuntimeOps.PrepareStaticPlugin(plugin, ref localResult);

                            if (code == ReturnCode.Ok)
                                code = AddPlugin(plugin, null, ref objectPluginToken, ref localResult);

                            if (code != ReturnCode.Ok)
                                result = localResult;
                        }
                        else
                        {
                            result = "invalid object plugin";
                            code = ReturnCode.Error;
                        }
                    }
#endif

#if DEBUG
                    if ((code == ReturnCode.Ok) &&
                        !FlagOps.HasFlags(createFlags, CreateFlags.NoTestPlugin, true))
                    {
                        plugin = NewTestPlugin();

                        if (plugin != null)
                        {
                            Result localResult = null;

                            code = RuntimeOps.PrepareStaticPlugin(plugin, ref localResult);

                            if (code == ReturnCode.Ok)
                                code = AddPlugin(plugin, null, ref testPluginToken, ref localResult);

                            if (code != ReturnCode.Ok)
                                result = localResult;
                        }
                        else
                        {
                            result = "invalid test plugin";
                            code = ReturnCode.Error;
                        }
                    }
#endif
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Namespace Support (optional)
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                if (RuntimeOps.AreNamespacesEnabled(createFlags))
                    code = NamespaceOps.Enable(this, true, false, ref result);
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Core command policies (for safe interpreters).
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                IPlugin plugin = GetCorePlugin(ref result);

                if (plugin != null)
                {
                    //
                    // NOTE: For "safe" interpreters, setup the interpreter policies now.  Policies
                    //       provided by the caller are added first followed by the policies needed
                    //       for proper operation of various features (e.g. such as script library
                    //       initialization).
                    //
                    if (policies != null)
                        code = SetupPolicies(policies, null, null, ref result);

                    if ((code == ReturnCode.Ok) &&
                        !FlagOps.HasFlags(createFlags, CreateFlags.NoCorePolicies, true) &&
                        (PolicyOps.Policies != null))
                    {
                        code = SetupPolicies(PolicyOps.Policies, plugin, null, ref result);
                    }
                }
                else
                {
                    code = ReturnCode.Error;
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Pre-defined Trace Lists
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                IPlugin plugin = GetCorePlugin(ref result);

                if (plugin != null)
                {
                    autoPathTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { AutoPathTraceCallback });

                    environmentTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { EnvironmentTraceCallback });

                    linkedVariableTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { LinkedVariableTraceCallback });

                    systemArrayTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { SystemArrayTraceCallback });

                    objectTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.Global, plugin,
                        new TraceCallback[] { ObjectTraceCallback });

                    precisionTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { PrecisionTraceCallback });

                    testsTraceList = new TraceList(
                        ClientData.Empty, TraceFlags.None, plugin,
                        new TraceCallback[] { TestsTraceCallback });

                    //
                    // NOTE: Setup interpreter wide variable traces now.  Traces provided by the
                    //       caller are added first followed by traces needed for proper operation
                    //       of various features (e.g. the core opaque object handle reference
                    //       counting).
                    //
                    if (traces != null)
                        code = SetupTraces(traces, null, ref result);

                    if ((code == ReturnCode.Ok) &&
                        !FlagOps.HasFlags(createFlags, CreateFlags.NoCoreTraces, true) &&
                        (objectTraceList != null))
                    {
                        code = SetupTraces(objectTraceList, null, ref result);
                    }
                }
                else
                {
                    code = ReturnCode.Error;
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Pre-defined Global Variables
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                code = SetupVariables(createFlags, args, true, ref result);

            if (code == ReturnCode.Ok)
                code = SetupPlatform(createFlags, true, ref result);

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Pre-defined Environment Variables
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                code = SetupHome(createFlags, ref result);

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Update script-level interactive status.
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                this.Interactive = false;
                this.InteractiveLoops = 0;
                this.Precision = TclVars.PrecisionValue;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Predefined Objects
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
            {
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoObjects, true))
                {
                    if (code == ReturnCode.Ok)
                    {
                        code = AddObject(Vars.Null, null,
                            ObjectFlags.Locked | ObjectFlags.Safe,
                            ClientData.Empty, 0,
#if NATIVE && TCL
                            null,
#endif
#if DEBUGGER && DEBUGGER_ARGUMENTS
                            null,
#endif
                            null, ref result);
                    }

                    if (!FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                    {
                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue(
                                VariableFlags.Invariant, Vars.Null,
                                Vars.Null, ref result);
                    }
                }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Expression Functions
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                code = SetupFunctions(createFlags, ref result);

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Expression Operators
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                code = SetupOperators(createFlags, ref result);

            ///////////////////////////////////////////////////////////////////////////////////////////
            //
            // Evaluate the "pre-init" script, if any...
            //
            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                code = PrivatePreInitialize(false, ref result);

            ///////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY && NOTIFY_GLOBAL
            if ((code == ReturnCode.Ok) && this.GlobalNotify)
                /* IGNORED */
                CheckNotifications(
                    null, false,
                    NotifyType.Interpreter, NotifyFlags.Setup,
                    new ObjectPair(createFlags, args), this,
                    null, null, null, ref result);
#endif

            ///////////////////////////////////////////////////////////////////////////////////////////

            if (code == ReturnCode.Ok)
                setup = true;

            ///////////////////////////////////////////////////////////////////////////////////////////

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode SetupHome(
            CreateFlags createFlags,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (!FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) &&
                !FlagOps.HasFlags(createFlags, CreateFlags.NoHome, true))
            {
                if (code == ReturnCode.Ok)
                {
                    string home = PathOps.GetHomeDirectory();

                    if (home == null)
                    {
                        //
                        // NOTE: The HOME environment variable was not found.  We need
                        //       to add it.  Start by creating an empty string.
                        //
                        home = String.Empty;

                        //
                        // NOTE: Check for the HOMEDRIVE environment variable and append
                        //       the value, if any, to the HOME value we are going to set.
                        //
                        string homeDrive = GlobalState.GetEnvironmentVariable(
                            EnvVars.HomeDrive, true, false);

                        if (homeDrive != null)
                            home += homeDrive;

                        //
                        // NOTE: Check for the HOMEPATH environment variable and append
                        //       the value, if any, to the HOME value we are going to set.
                        //
                        string homePath = GlobalState.GetEnvironmentVariable(
                            EnvVars.HomePath, true, false);

                        if (homePath != null)
                            home += homePath;

                        //
                        // NOTE: If the newly constructed candidate value for the HOME
                        //       environment variable has a value, set it now.
                        //
                        if (!String.IsNullOrEmpty(home))
                            PathOps.SetHomeDirectory(home);
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Assumes the interpreter lock is held.
        //
        internal ReturnCode SetupPlatform(
            CreateFlags createFlags,
            bool create,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (!FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true) &&
                !FlagOps.HasFlags(createFlags, CreateFlags.NoPlatform, true))
            {
                if (code == ReturnCode.Ok)
                {
                    string byteOrder = BitConverter.IsLittleEndian ?
                        TclVars.Platform.LittleEndianValue :
                        TclVars.Platform.BigEndianValue;

                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.ByteOrder,
                        byteOrder, ref result);
                }

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.CharacterSize,
                        sizeof(char).ToString() + Characters.MinusSign +
                            sizeof(char).ToString(),
                        ref result);

#if DEBUG
                //
                // NOTE: When built with DEBUG, we are always debug-enabled.
                //
                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.Debug,
                        ConversionOps.ToInt(true).ToString(), ref result);
#endif

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.DirectorySeparator,
                        Path.DirectorySeparatorChar.ToString(), ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.Engine,
                        Vars.PackageName, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.PatchLevel,
                        TclVars.PatchLevelValue, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.PathSeparator,
                        Path.PathSeparator.ToString(), ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.PlatformName,
                        PlatformOps.GetPlatformName(), ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.PointerSize,
                        IntPtr.Size.ToString(), ref result);

                if (code == ReturnCode.Ok) /* we are always threads-enabled */
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.Threaded,
                        ConversionOps.ToInt(true).ToString(), ref result);

                if (code == ReturnCode.Ok) /* we are always unicode-enabled */
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.Unicode,
                        ConversionOps.ToInt(true).ToString(), ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.Version,
                        TclVars.VersionValue, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        TclVars.Platform.Name, TclVars.Platform.WordSize,
                        sizeof(int).ToString(), ref result);

                Version version = GlobalState.GetAssemblyVersion();

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        Vars.Platform.Name, Vars.Platform.Version,
                        FormatOps.MajorMinor(version), ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        Vars.Platform.Name, Vars.Platform.PatchLevel,
                        (version != null) ? version.ToString() : null,
                        ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        Vars.Platform.Name, Vars.Platform.Engine,
                        Vars.PackageName, ref result);

                if (code == ReturnCode.Ok)
                    code = SetLibraryVariableValue2(VariableFlags.None,
                        Vars.Platform.Name, Vars.Platform.Configuration,
                        AttributeOps.GetAssemblyConfiguration(
                            GlobalState.GetAssembly()),
                        ref result);

                if (code == ReturnCode.Ok)
                {
                    if (!FlagOps.HasFlags(createFlags, CreateFlags.Safe, true))
                    {
                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.Processors,
                                Environment.ProcessorCount.ToString(),
                                ref result);

#if NATIVE && WINDOWS
                        if (code == ReturnCode.Ok)
                        {
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.ProcessorAffinityMasks,
                                NativeOps.GetProcessorAffinityMasks().ToString(),
                                ref result);
                        }
#endif

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.Host,
                                Environment.MachineName, ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.Machine,
                                PlatformOps.GetProcessorName(), ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.OsName,
                                PlatformOps.GetOperatingSystemName(), ref result);

                        /* REUSED */
                        version = PlatformOps.GetOperatingSystemVersion();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.OsVersion,
                                FormatOps.MajorMinor(version), ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.OsPatchLevel,
                                (version != null) ? version.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.OsServicePack,
                                PlatformOps.GetOperatingSystemServicePack(),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.ProcessBits,
                                PlatformOps.GetProcessBits().ToString(),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                TclVars.Platform.Name, TclVars.Platform.User,
                                PlatformOps.GetUserName(false), ref result);

#if CAS_POLICY
                        if (code == ReturnCode.Ok)
                        {
                            Result permissionSetResult = null;

                            try
                            {
                                Evidence evidence = GlobalState.GetAssemblyEvidence();

                                PermissionSet permissionSet = (evidence != null) ?
                                    SecurityManager.ResolvePolicy(evidence) : null;

                                permissionSetResult = (permissionSet != null) ?
                                    StringOps.NormalizeWhiteSpace(
                                        permissionSet.ToString(), Characters.Space,
                                        true, false) : null;
                            }
                            catch (Exception e)
                            {
                                permissionSetResult = e;
                            }

                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.PermissionSet,
                                permissionSetResult, ref result);
                        }
#endif

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.SourceId,
                                AttributeOps.GetAssemblySourceId(
                                    GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.SourceTimeStamp,
                                AttributeOps.GetAssemblySourceTimeStamp(
                                    GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Administrator,
                                RuntimeOps.IsAdministrator().ToString(),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Culture,
                                FormatOps.CultureName(
                                    GlobalState.GetAssemblyCultureInfo(), false),
                                ref result);

                        /* REUSED */
                        version = CommonOps.Runtime.GetFrameworkVersion();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.FrameworkVersion,
                                (version != null) ? version.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.FrameworkExtraVersion,
                                CommonOps.Runtime.GetFrameworkExtraVersion(),
                                ref result);

                        OperatingSystem operatingSystem = PlatformOps.GetOperatingSystem();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.OsName,
                                (operatingSystem != null) ?
                                    operatingSystem.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Wow64,
                                PlatformOps.GetWin32onWin64().ToString(),
                                ref result);

                        /* REUSED */
                        version = CommonOps.Runtime.GetRuntimeVersion();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.RuntimeVersion,
                                (version != null) ? version.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.ImageRuntimeVersion,
                                AssemblyOps.GetImageRuntimeVersion(
                                    GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Epoch,
                                FormatOps.Iso8601DateTime(TimeOps.UnixEpoch, true),
                                ref result);

                        if (code == ReturnCode.Ok)
                        {
                            Assembly assembly = GlobalState.GetAssembly();

                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.GlobalAssemblyCache,
                                (assembly != null) ?
                                    assembly.GlobalAssemblyCache.ToString() :
                                    false.ToString(),
                                ref result);
                        }

                        StringList options = DefineConstants.OptionList;

                        if (options != null)
                        {
                            options = new StringList(options);
                            options.Sort();
                        }

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.CompileOptions,
                                (options != null) ? options.ToString(false) : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.CSharpOptionsName,
                                Vars.Platform.CSharpOptionsValue, ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.RuntimeOptions,
                                runtimeOptions.ToString(), ref result);

                        if (!FlagOps.HasFlags(createFlags, CreateFlags.NoObjectIds, true))
                        {
                            StringPairList objectIds =
                                AttributeOps.GetObjectIds(GlobalState.GetAssembly(), false);

                            if (code == ReturnCode.Ok)
                                code = SetLibraryVariableValue2(VariableFlags.None,
                                    Vars.Platform.Name, Vars.Platform.ObjectIds,
                                    (objectIds != null) ? objectIds.ToString() : null,
                                    ref result);
                        }

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.MinimumDate,
                                FormatOps.Iso8601DateTime(DateTime.MinValue, true),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.MaximumDate,
                                FormatOps.Iso8601DateTime(DateTime.MaxValue, true),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.TimeStamp,
                                FormatOps.Iso8601DateTime(
                                    AttributeOps.GetAssemblyDateTime(
                                        GlobalState.GetAssembly()), true),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Release,
                                AttributeOps.GetAssemblyRelease(GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Tag,
                                AttributeOps.GetAssemblyTag(GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Text,
                                AttributeOps.GetAssemblyText(GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.TargetFramework,
                                AttributeOps.GetAssemblyTargetFramework(
                                    GlobalState.GetAssembly()),
                                ref result);

#if NATIVE && NATIVE_UTILITY
                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.NativeUtility,
                                NativeUtility.GetVersion(this), ref result);
#endif

                        Uri uri = GlobalState.GetAssemblyUri();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Uri,
                                (uri != null) ? uri.ToString() : null,
                                ref result);

                        uri = GlobalState.GetAssemblyUpdateBaseUri();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.UpdateBaseUri,
                                (uri != null) ? uri.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.PublicKey,
                                AssemblyOps.GetPublicKey(
                                    GlobalState.GetAssemblyName()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.PublicKeyToken,
                                AssemblyOps.GetPublicKeyToken(
                                    GlobalState.GetAssemblyName()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.ModuleVersionId,
                                AssemblyOps.GetModuleVersionId(
                                    GlobalState.GetAssembly()).ToString(),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Certificate,
                                FormatOps.Certificate(
                                    GlobalState.GetAssemblyLocation(), GetCertificate(),
                                    !create || RuntimeOps.ShouldCheckFileTrusted(),
                                    false, false),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.UpdatePathAndQueryName,
                                String.Format(Vars.Platform.UpdatePathAndQueryValue,
                                    GlobalState.GetAssemblyUpdateVersion()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.StrongName,
                                FormatOps.StrongName(
                                    GlobalState.GetAssembly(), GetStrongName(),
                                    !create || RuntimeOps.ShouldCheckStrongNameVerified()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.StrongNameTag,
                                AttributeOps.GetAssemblyStrongNameTag(
                                    GlobalState.GetAssembly()),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.Hash,
                                FormatOps.Hash(GetHash()), ref result);

                        /* REUSED */
                        version = GlobalState.GetEntryAssemblyVersion();

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.ShellVersion,
                                FormatOps.MajorMinor(version),
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.ShellPatchLevel,
                                (version != null) ? version.ToString() : null,
                                ref result);

                        if (code == ReturnCode.Ok)
                            code = SetLibraryVariableValue2(VariableFlags.None,
                                Vars.Platform.Name, Vars.Platform.RuntimeName,
                                CommonOps.Runtime.GetRuntimeName(),
                                ref result);
                    }
                }
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Initialization
        private static ReturnCode EvaluateScript(
            Interpreter interpreter,
            string name,
            bool core,
            ref ScriptFlags flags,
            ref Result result
            )
        {
            string text = null;

            return EvaluateScript(interpreter, name, core, ref flags, ref text, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode EvaluateScript(
            Interpreter interpreter,
            string name,
            bool core,
            ref ScriptFlags flags,
            ref string text,
            ref Result result
            )
        {
            int errorLine = 0;

            ReturnCode code = EvaluateScript(
                interpreter, name, core, ref flags,
                ref text, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(interpreter, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: *WARNING* This method is for use with named (i.e.
        //       predefined) script library and host scripts only.
        //       This method may be radically modified and/or
        //       removed in the future.
        //
        private static ReturnCode EvaluateScript(
            Interpreter interpreter,
            string name,
            bool core,
            ref ScriptFlags flags,
            ref string text,
            ref Result result,
            ref int errorLine
            )
        {
            if (interpreter != null)
            {
                try
                {
                    ProcedureFlags savedProcedureFlags = interpreter.ProcedureFlags;

                    try
                    {
                        //
                        // NOTE: Figure out and then set the effective procedure
                        //       flags needed while evaluating this script.
                        //
                        ProcedureFlags newProcedureFlags = interpreter.ProcedureFlags;
                        bool library = FlagOps.HasFlags(flags, ScriptFlags.Library, true);
                        bool interactive = FlagOps.HasFlags(flags, ScriptFlags.Interactive, true);

                        if (core)
                            newProcedureFlags |= ProcedureFlags.Core;

                        if (library)
                            newProcedureFlags |= ProcedureFlags.Library;

                        if (interactive)
                            newProcedureFlags |= ProcedureFlags.Interactive;

                        interpreter.ProcedureFlags = newProcedureFlags;

                        ///////////////////////////////////////////////////////////////////////////////

                        Result localResult = null;

                        if ((library && (ScriptOps.GetLibrary(
                                interpreter, interpreter.Host, name,
                                ref flags, ref localResult) == ReturnCode.Ok)) ||
                            (!library && (HostOps.GetScript(
                                interpreter, interpreter.Host, name,
                                ref flags, ref localResult) == ReturnCode.Ok)))
                        {
                            text = localResult;

                            if (!String.IsNullOrEmpty(text))
                            {
                                if (FlagOps.HasFlags(flags, ScriptFlags.File, true))
                                {
                                    if (PathOps.IsRemoteUri(text) || File.Exists(text))
                                    {
                                        return interpreter.EvaluateFile(
                                            text, ref result, ref errorLine);
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "the provided \"{0}\" script file \"{1}\" is not " +
                                            "a valid remote uri and does not exist locally",
                                            name, text);
                                    }
                                }
                                else
                                {
                                    return interpreter.EvaluateScript(
                                        text, ref result, ref errorLine);
                                }
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.Required, true))
                            {
                                //
                                // NOTE: The script is required; therefore, this
                                //       is an error.
                                //
                                result = String.Format(
                                    "the provided \"{0}\" script is invalid (required)",
                                    name);
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.Optional, true))
                            {
                                //
                                // NOTE: Script is explicitly optional, this is OK.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.ErrorOnEmpty, true))
                            {
                                //
                                // NOTE: The strict flag is set; therefore, this
                                //       is an error.
                                //
                                result = String.Format(
                                    "the provided \"{0}\" script is invalid (strict)",
                                    name);
                            }
                            else
                            {
                                //
                                // TODO: Script is neither explicitly requierd nor
                                //       optional and the strict flag is not set;
                                //       therefore, just return success.  These
                                //       semantics may need fine-tuning later.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                        else if (FlagOps.HasFlags(flags, ScriptFlags.Required, true) ||
                            FlagOps.HasFlags(flags, ScriptFlags.ErrorOnEmpty, true))
                        {
                            //
                            // NOTE: No suitable script could be located to
                            //       satisfy the request.  Return the inner
                            //       error message verbatim.
                            //
                            result = localResult;
                        }
                        else
                        {
                            //
                            // TODO: Script is neither explicitly requierd nor
                            //       optional and the strict flag is not set;
                            //       therefore, just return success.  These
                            //       semantics may need fine-tuning later.
                            //
                            result = String.Empty;
                            return ReturnCode.Ok;
                        }
                    }
                    finally
                    {
                        //
                        // NOTE: Restore the saved procedure flags.
                        //
                        interpreter.ProcedureFlags = savedProcedureFlags;
                    }
                }
                catch (Exception e)
                {
                    result = e;
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            //
            // NOTE: If we get to this point, we have failed and
            //       we do not have error line information (i.e.
            //       we have not evaluated anything).
            //
            errorLine = 0;

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode EvaluateStartupScript(
            Interpreter interpreter,
            ref ScriptFlags flags,
            ref Result result
            )
        {
            int errorLine = 0;

            ReturnCode code = EvaluateStartupScript(
                interpreter, ref flags, ref result, ref errorLine);

            if (errorLine != 0)
                SetErrorLine(interpreter, errorLine);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode EvaluateStartupScript(
            Interpreter interpreter,
            ref ScriptFlags flags,
            ref Result result,
            ref int errorLine
            )
        {
            if (interpreter != null)
            {
                try
                {
                    ProcedureFlags savedProcedureFlags = interpreter.ProcedureFlags;

                    try
                    {
                        //
                        // NOTE: Figure out and then set the effective procedure
                        //       flags needed while evaluating this script.
                        //
                        ProcedureFlags newProcedureFlags = interpreter.ProcedureFlags;
                        bool library = FlagOps.HasFlags(flags, ScriptFlags.Library, true);
                        bool interactive = FlagOps.HasFlags(flags, ScriptFlags.Interactive, true);

                        if (library)
                            newProcedureFlags |= ProcedureFlags.Library;

                        if (interactive)
                            newProcedureFlags |= ProcedureFlags.Interactive;

                        interpreter.ProcedureFlags = newProcedureFlags;

                        ///////////////////////////////////////////////////////////////////////////////

                        string name = TclVars.RunCommandsFileName;
                        Result localResult = null;
                        ResultList errors = null;

                        if (ScriptOps.GetStartup(
                                interpreter, interpreter.Host, name, ref flags,
                                ref localResult, ref errors) == ReturnCode.Ok)
                        {
                            string text = localResult;

                            if (!String.IsNullOrEmpty(text))
                            {
                                if (FlagOps.HasFlags(flags, ScriptFlags.File, true))
                                {
                                    if (PathOps.IsRemoteUri(text) || File.Exists(text))
                                    {
                                        return interpreter.EvaluateFile(
                                            text, ref result, ref errorLine);
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "the provided \"{0}\" script file \"{1}\" is not " +
                                            "a valid remote uri and does not exist locally",
                                            name, text);
                                    }
                                }
                                else
                                {
                                    return interpreter.EvaluateScript(
                                        text, ref result, ref errorLine);
                                }
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.Required, true))
                            {
                                //
                                // NOTE: The script is required; therefore, this
                                //       is an error.
                                //
                                result = String.Format(
                                    "the provided \"{0}\" script is invalid (required)",
                                    name);
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.Optional, true))
                            {
                                //
                                // NOTE: Script is explicitly optional, this is OK.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                            else if (FlagOps.HasFlags(flags, ScriptFlags.ErrorOnEmpty, true))
                            {
                                //
                                // NOTE: The strict flag is set; therefore, this
                                //       is an error.
                                //
                                result = String.Format(
                                    "the provided \"{0}\" script is invalid (strict)",
                                    name);
                            }
                            else
                            {
                                //
                                // TODO: Script is neither explicitly requierd nor
                                //       optional and the strict flag is not set;
                                //       therefore, just return success.  These
                                //       semantics may need fine-tuning later.
                                //
                                result = String.Empty;
                                return ReturnCode.Ok;
                            }
                        }
                        else if (FlagOps.HasFlags(flags, ScriptFlags.Required, true) ||
                            FlagOps.HasFlags(flags, ScriptFlags.ErrorOnEmpty, true))
                        {
                            //
                            // NOTE: No suitable script could be located to
                            //       satisfy the request.  Return the inner
                            //       error message verbatim.
                            //
                            result = errors;
                        }
                        else
                        {
                            //
                            // TODO: Script is neither explicitly requierd nor
                            //       optional and the strict flag is not set;
                            //       therefore, just return success.  These
                            //       semantics may need fine-tuning later.
                            //
                            result = String.Empty;
                            return ReturnCode.Ok;
                        }
                    }
                    finally
                    {
                        //
                        // NOTE: Restore the saved procedure flags.
                        //
                        interpreter.ProcedureFlags = savedProcedureFlags;
                    }
                }
                catch (Exception e)
                {
                    result = e;
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            //
            // NOTE: If we get to this point, we have failed and
            //       we do not have error line information (i.e.
            //       we have not evaluated anything).
            //
            errorLine = 0;

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ProvideCorePackages(
            ref Result error /* out */
            )
        {
            ReturnCode code;
            Result localResult = null;

            //
            // NOTE: Provide the static Tcl package in the interpreter for the
            //       purpose of source compatibility with package index files.
            //
            code = ProvidePackage(
                TclVars.PackageName, TclVars.PackageVersion, ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            //
            // NOTE: Provide the static Eagle package in the interpreter.
            //
            code = ProvidePackage(
                GlobalState.GetPackageName(), GlobalState.GetAssemblyVersion(),
                ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void AllowInitializeLibrary()
        {
            lock (syncRoot)
            {
                createFlags &= ~CreateFlags.NoLibrary;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateInitializeLibrary(
            ref Result error /* out */
            )
        {
            ReturnCode code;
            ScriptFlags scriptFlags;
            string text = null;
            Result localResult = null;

            scriptFlags = ScriptFlags.CoreLibraryRequiredFile;

            code = EvaluateScript(
                this, FileName.Initialization, true, ref scriptFlags,
                ref text, ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            lock (syncRoot)
            {
                if (FlagOps.HasFlags(scriptFlags, ScriptFlags.File, true))
                {
                    //
                    // BUGFIX: Save the directory where we found the "init"
                    //         script.
                    //
                    initializedPath = PathOps.TranslatePath(
                        PathOps.GetDirectoryName(text),
                        PathTranslationType.Default);
                }
                else
                {
                    //
                    // BUGFIX: No file was used to find the "init" script;
                    //         however, we probably pulled it from the
                    //         assembly resources.
                    //
                    Assembly assembly = GlobalState.GetAssembly();

                    initializedPath = (assembly != null) ?
                        PathOps.TranslatePath(assembly.Location,
                            PathTranslationType.Default) : null;
                }
            }

            scriptFlags = ScriptFlags.ApplicationLibraryOptionalFile;

            code = EvaluateScript(
                this, FileName.Embedding, true, ref scriptFlags,
                ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            scriptFlags = ScriptFlags.VendorLibraryOptionalFile;

            code = EvaluateScript(
                this, FileName.Vendor, true, ref scriptFlags,
                ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateInitialize(
            bool force,      /* in */
            bool debug,      /* in */
            ref Result error /* out */
            )
        {
            ReturnCode code = ReturnCode.Ok;
            bool wasInitialized;
            bool didInitialize = false;

            lock (syncRoot)
            {
                wasInitialized = initialized;
            }

            if (force || !wasInitialized)
            {
                #region Set Debugger Engine Flags (Optional)
#if DEBUGGER
                EngineFlags savedEngineFlags = EngineFlags.None;

                if (debug)
                    savedEngineFlags = BeginDebuggerExecution();

                try
#endif
                #endregion
                {
                    #region Phase 0: Copy Creation Flags
                    CreateFlags localCreateFlags;

                    lock (syncRoot)
                    {
                        localCreateFlags = createFlags;
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 1: Auto-Path Diagnostics (Optional)
                    //
                    // NOTE: Debug all the key paths used to initialize the
                    //       interpreter.  This was created initially to
                    //       debug compliance with our path resolution
                    //       expectations (primarily on Mono).
                    //
                    if (FlagOps.HasFlags(
                            localCreateFlags, CreateFlags.ShowAutoPath, true))
                    {
                        GlobalState.DisplayPaths(this, true);
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 2: Provide System Packages
                    if (code == ReturnCode.Ok)
                    {
                        code = ProvideCorePackages(ref error);
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 3: Initialize Library
                    if (code == ReturnCode.Ok)
                    {
                        if (!FlagOps.HasFlags(
                                localCreateFlags, CreateFlags.NoLibrary, true))
                        {
                            code = PrivateInitializeLibrary(ref error);

                            if (code == ReturnCode.Ok)
                                didInitialize = true;
                        }
                        else
                        {
                            //
                            // HACK: After trying to automatically initialize
                            //       the core library, mask off the creation
                            //       flag that may have been used to prevent
                            //       the actual script file evaluation.
                            //
                            /* NO RESULT */
                            AllowInitializeLibrary();
                        }
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 4: Set Auto-Path & Library Variables
                    if (code == ReturnCode.Ok)
                    {
                        if (!FlagOps.HasFlags(
                                localCreateFlags, CreateFlags.NoVariables, true) &&
                            !FlagOps.HasFlags(
                                localCreateFlags, CreateFlags.Safe, true))
                        {
                            //
                            // NOTE: Trigger the initialization of the package
                            //       "subsystem".  This must be done after the
                            //       library has been initialized; otherwise,
                            //       the pkgIndex scripts will not be able to
                            //       use those facilities.
                            //
                            if (code == ReturnCode.Ok)
                            {
                                TraceList traceList;

                                lock (syncRoot)
                                {
                                    traceList = autoPathTraceList;
                                }

                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.AutoPath,
                                    GlobalState.GetAutoPathList(this,
                                    false).ToString(), traceList, ref error);
                            }

                            //
                            // NOTE: This variable should have been set above.
                            //       It may be null if no physical file was
                            //       used for the "init" script; however, this
                            //       is OK.
                            //
                            if (code == ReturnCode.Ok)
                            {
                                string path;

                                lock (syncRoot)
                                {
                                    path = initializedPath;
                                }

                                code = SetLibraryVariableValue(
                                    VariableFlags.None, TclVars.Library,
                                    path, ref error);
                            }
                        }
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 5: Initialize Debugger Interpreter
#if DEBUGGER
                    //
                    // NOTE: Now, see if we need still need to initialize
                    //       isolated interpreter for our debugger (if we
                    //       have one).
                    //
                    if (code == ReturnCode.Ok)
                    {
                        IDebugger debugger = Debugger; /* PROPERTY */

                        if (debugger != null)
                        {
                            Interpreter debugInterpreter = debugger.Interpreter;

                            if ((debugInterpreter != null) &&
                                !debugInterpreter.PrivateInitialized)
                            {
                                /* RECURSION */
                                code = debugInterpreter.PrivateInitialize(
                                    force, debug, ref error);
                            }
                        }
                    }
#endif
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 6: Set Library Initialized Flag
                    //
                    // NOTE: Has everything succeeded?
                    //
                    if (code == ReturnCode.Ok)
                    {
#if NOTIFY && NOTIFY_GLOBAL
                        string path = null;
#endif

                        lock (syncRoot)
                        {
#if NOTIFY && NOTIFY_GLOBAL
                            path = initializedPath;
#endif

                            if (!initialized)
                                initialized = true;
                        }

#if NOTIFY && NOTIFY_GLOBAL
                        if (this.GlobalNotify)
                            /* IGNORED */
                            CheckNotifications(
                                null, false, NotifyType.Interpreter |
                                NotifyType.Library, NotifyFlags.Initialized,
                                new ObjectList(force, debug, path,
                                    wasInitialized, didInitialize),
                                this, null, null, null, ref error);
#endif
                    }
                    #endregion
                }
                #region Restore Saved Engine Flags
#if DEBUGGER
                finally
                {
                    if (debug)
                        EndDebuggerExecution(savedEngineFlags);
                }
#endif
                #endregion
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: PrivateInitialize: interpreter = {1}, force = {2}, " +
                "debug = {3}, wasInitialized = {4}, didInitialize = {5}, " +
                "code = {6}, error = {7}{8}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(this),
                force, debug, wasInitialized, didInitialize, code,
                FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                typeof(Interpreter).Name);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL
        private void AllowInitializeShellLibrary()
        {
            lock (syncRoot)
            {
                createFlags &= ~CreateFlags.NoShellLibrary;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateInitializeShellLibrary(
            ref Result error /* out */
            )
        {
            ReturnCode code;
            ScriptFlags scriptFlags;
            string text = null;
            Result localResult = null;

            scriptFlags = ScriptFlags.Interactive |
                ScriptFlags.CoreLibraryRequiredFile;

            code = EvaluateScript(
                this, FileName.Shell, true, ref scriptFlags, ref text,
                ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            lock (syncRoot)
            {
                if (FlagOps.HasFlags(scriptFlags, ScriptFlags.File, true))
                {
                    //
                    // NOTE: Save the directory where we found the "shell"
                    //       script.
                    //
                    initializedShellPath = PathOps.TranslatePath(
                        PathOps.GetDirectoryName(text),
                        PathTranslationType.Default);
                }
                else
                {
                    //
                    // NOTE: No file was used to find the "shell" script;
                    //       however, we probably pulled it from the assembly
                    //       resources.
                    //
                    Assembly assembly = GlobalState.GetAssembly();

                    initializedShellPath = (assembly != null) ?
                        PathOps.TranslatePath(assembly.Location,
                            PathTranslationType.Default) : null;
                }
            }

            scriptFlags = ScriptFlags.Interactive |
                ScriptFlags.ApplicationOptionalFile |
                ScriptFlags.UserOptionalFile;

            code = EvaluateStartupScript(
                this, ref scriptFlags, ref localResult);

            if (code != ReturnCode.Ok)
            {
                error = localResult;
                return code;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PrivateInitializeShell(
            bool force,      /* in */
            bool debug,      /* in */
            ref Result error /* out */
            )
        {
            ReturnCode code = ReturnCode.Ok;
            bool wasInitialized;
            bool didInitialize = false;

            lock (syncRoot)
            {
                wasInitialized = initializedShell;
            }

            if (force || !wasInitialized)
            {
                #region Set Debugger Engine Flags (Optional)
#if DEBUGGER
                EngineFlags savedEngineFlags = EngineFlags.None;

                if (debug)
                    savedEngineFlags = BeginDebuggerExecution();

                try
#endif
                #endregion
                {
                    #region Phase 0: Copy Creation Flags
                    CreateFlags localCreateFlags;

                    lock (syncRoot)
                    {
                        localCreateFlags = createFlags;
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 1: Auto-Path Diagnostics (Optional)
                    //
                    // NOTE: Debug all the key paths used to initialize the
                    //       interpreter.  This was created initially to
                    //       debug compliance with our path resolution
                    //       expectations (primarily on Mono).
                    //
                    if (FlagOps.HasFlags(
                            localCreateFlags, CreateFlags.ShowAutoPath, true))
                    {
                        GlobalState.DisplayPaths(this, true);
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 2: Initialize Shell Library
                    if (code == ReturnCode.Ok)
                    {
                        if (!FlagOps.HasFlags(
                                localCreateFlags, CreateFlags.NoShellLibrary, true))
                        {
                            code = PrivateInitializeShellLibrary(ref error);

                            if (code == ReturnCode.Ok)
                                didInitialize = true;
                        }
                        else
                        {
                            //
                            // HACK: After trying to automatically initialize
                            //       the shell library, mask off the creation
                            //       flag that may have been used to prevent
                            //       the actual script file evaluation.
                            //
                            /* NO RESULT */
                            AllowInitializeShellLibrary();
                        }
                    }
                    #endregion

                    ///////////////////////////////////////////////////////////////////////////////////

                    #region Phase 3: Set Shell Initialized Flag
                    if (code == ReturnCode.Ok)
                    {
#if NOTIFY && NOTIFY_GLOBAL
                        string path = null;
#endif

                        lock (syncRoot)
                        {
#if NOTIFY && NOTIFY_GLOBAL
                            path = initializedShellPath;
#endif

                            if (!initializedShell)
                                initializedShell = true;
                        }

#if NOTIFY && NOTIFY_GLOBAL
                        if (this.GlobalNotify)
                            /* IGNORED */
                            CheckNotifications(
                                null, false, NotifyType.Interpreter |
                                NotifyType.Shell, NotifyFlags.Initialized,
                                new ObjectList(force, debug, path,
                                    wasInitialized, didInitialize),
                                this, null, null, null, ref error);
#endif
                    }
                    #endregion
                }
                #region Restore Saved Engine Flags
#if DEBUGGER
                finally
                {
                    if (debug)
                        EndDebuggerExecution(savedEngineFlags);
                }
#endif
                #endregion
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: PrivateInitializeShell: interpreter = {1}, force = {2}, " +
                "debug = {3}, wasInitialized = {4}, didInitialize = {5}, " +
                "code = {6}, error = {7}{8}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(this),
                force, debug, wasInitialized, didInitialize, code,
                FormatOps.WrapOrNull(true, true, error), Environment.NewLine),
                typeof(Interpreter).Name);

            return code;
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Debugger Support
#if DEBUGGER
        private bool CanHitWatchpoints()
        {
            return !Engine.HasNoWatchpoint(engineFlags) && !PrivateIsDebuggerActive();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool CanHitBreakpoints()
        {
            return !Engine.HasNoBreakpoint(engineFlags) && !PrivateIsDebuggerActive();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode TestBreakpointsToString(
            ref Result result
            )
        {
            StringDictionary testBreakpoints = TestBreakpoints;

            if (testBreakpoints == null)
            {
                result = "test breakpoints not available";
                return ReturnCode.Error;
            }

            result = testBreakpoints.ToString(null, false);
            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool HasTestBreakpoint(
            string name
            )
        {
            if (name != null)
            {
                StringDictionary testBreakpoints = TestBreakpoints;

                if (testBreakpoints != null)
                    return testBreakpoints.ContainsKey(name);
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool SetTestBreakpoint(
            string name,
            bool enable,
            ref Result error
            )
        {
            if (name == null)
            {
                error = "invalid test name";
                return false;
            }

            StringDictionary testBreakpoints = TestBreakpoints;

            if (testBreakpoints == null)
            {
                error = "test breakpoints not available";
                return false;
            }

            if (enable == testBreakpoints.ContainsKey(name))
            {
                error = String.Format(
                    "test \"{0}\" breakpoint is already {1}",
                    name, enable ? "set" : "unset");

                return false;
            }

            if (enable)
                testBreakpoints.Add(name, null);
            else
                testBreakpoints.Remove(name);

            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckBreakpoints(
            ReturnCode code,
            BreakpointType breakpointType,
            string breakpointName,
            IToken token,
            ITraceInfo traceInfo,
            IExecute execute,
            IExecuteArgument executeArgument,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            return Engine.CheckBreakpoints(
                code, breakpointType, breakpointName, token, traceInfo, engineFlags,
                substitutionFlags, engineEventFlags, expressionFlags, execute,
                executeArgument, this, clientData, arguments, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER && DEBUGGER_VARIABLE
        private ReturnCode CheckWatchpoints(
            ReturnCode code,
            BreakpointType breakpointType,
            string breakpointName,
            IToken token,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            return Engine.CheckWatchpoints(
                code, breakpointType, breakpointName, token, traceInfo, engineFlags,
                substitutionFlags, engineEventFlags, expressionFlags, this, ref result);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DebuggerBreak(
            IDebugger debugger,
            ReturnCode code,
            BreakpointType breakpointType,
            string breakpointName,
            IToken token,
            ITraceInfo traceInfo,
            HeaderFlags headerFlags,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            return _Private.DebuggerOps.Breakpoint(
                debugger, this, code, breakpointType, breakpointName, token,
                traceInfo, engineFlags, substitutionFlags, engineEventFlags,
                expressionFlags, headerFlags, clientData, arguments, ref result);
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Shell & Interactive Loop Support
        #region Shell Support
        #region Shell Thread Support
#if SHELL
        private static void ShellThreadStart(
            object obj
            )
        {
            try
            {
                IEnumerable<string> args = obj as IEnumerable<string>;

                TraceOps.DebugTrace(String.Format(
                    "{0}: ShellThreadStart: entered, args = {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    FormatOps.WrapArgumentsOrNull(true, true, args),
                    Environment.NewLine), typeof(Interpreter).Name);

                ExitCode exitCode = ShellMain(args);

                TraceOps.DebugTrace(String.Format(
                    "{0}: ShellThreadStart: exited, args = {1}, " +
                    "exitCode = {2}{3}",
                    GlobalState.GetCurrentThreadId(),
                    FormatOps.WrapArgumentsOrNull(true, true, args),
                    exitCode, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Thread ShellThreadMain(
            IEnumerable<string> args,
            bool start
            ) /* ENTRY-POINT, THREAD-SAFE, RE-ENTRANT */
        {
            try
            {
                Thread shellMainThread = Engine.CreateThread(
                    ShellThreadStart, 0, true, false);

                if (shellMainThread != null)
                {
                    shellMainThread.Name = "shellMainThread";

                    if (start)
                        shellMainThread.Start(args);

                    return shellMainThread;
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }

            return null;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Shell Script Evaluation Support
#if SHELL
        private void RefreshShellCallbacks(
            bool hadArgumentCallback,
            bool hadEvaluateScriptCallback,
            bool hadEvaluateFileCallback,
            bool hadEvaluateEncodedFileCallback,
            bool hadInteractiveLoopCallback,
            ref ArgumentCallback argumentCallback,
            ref EvaluateScriptCallback evaluateScriptCallback,
            ref EvaluateFileCallback evaluateFileCallback,
            ref EvaluateEncodedFileCallback evaluateEncodedFileCallback,
            ref InteractiveLoopCallback interactiveLoopCallback)
        {
            lock (syncRoot) /* TRANSACTIONAL */
            {
                if (!hadArgumentCallback)
                    argumentCallback = this.ArgumentCallback;

                if (!hadEvaluateScriptCallback)
                    evaluateScriptCallback = this.EvaluateScriptCallback;

                if (!hadEvaluateFileCallback)
                    evaluateFileCallback = this.EvaluateFileCallback;

                if (!hadEvaluateEncodedFileCallback)
                    evaluateEncodedFileCallback = this.EvaluateEncodedFileCallback;

#if DEBUGGER
                if (!hadInteractiveLoopCallback)
                    interactiveLoopCallback = this.InteractiveLoopCallback;
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ShellEvaluateScript(
            EvaluateScriptCallback evaluateScriptCallback,
            string text,
            ref Result result,
            ref int errorLine
            )
        {
            try
            {
                return (evaluateScriptCallback != null) ?
                    evaluateScriptCallback(this, text, ref result, ref errorLine) :
                    EvaluateScript(text, ref result, ref errorLine);
            }
            catch (Exception e)
            {
                result = e;
                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ShellEvaluateFile(
            EvaluateFileCallback evaluateFileCallback,
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            try
            {
                return (evaluateFileCallback != null) ?
                    evaluateFileCallback(this, fileName, ref result, ref errorLine) :
                    EvaluateFile(fileName, ref result, ref errorLine);
            }
            catch (Exception e)
            {
                result = e;
                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ShellEvaluateFile(
            EvaluateEncodedFileCallback evaluateEncodedFileCallback,
            Encoding encoding,
            string fileName,
            ref Result result,
            ref int errorLine
            )
        {
            try
            {
                return (evaluateEncodedFileCallback != null) ?
                    evaluateEncodedFileCallback(this, encoding, fileName, ref result, ref errorLine) :
                    EvaluateFile(encoding, fileName, ref result, ref errorLine);
            }
            catch (Exception e)
            {
                result = e;
                return ReturnCode.Error;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Shell Core Support
#if SHELL
        private static int GetShellErrorLine(
            Interpreter interpreter,
            int errorLine
            )
        {
            if (errorLine != 0)
                return errorLine;

            return GetErrorLine(interpreter);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This method is [also] specifically for use by alternative shells
        //       (i.e. ones that have no console, etc).  This method assumes that
        //       the interpreter has already been created with the desired options
        //       and that the interpreter host has been set to something with
        //       suitable functionality (i.e. minimally, something that fully
        //       implements the IInteractiveHost interface).
        //
        public static ExitCode ShellMainCore(
            Interpreter interpreter,
            ArgumentCallback argumentCallback,
            EvaluateScriptCallback evaluateScriptCallback,
            EvaluateFileCallback evaluateFileCallback,
            EvaluateEncodedFileCallback evaluateEncodedFileCallback,
            InteractiveLoopCallback interactiveLoopCallback,
            IClientData clientData,
            IEnumerable<string> args,
            bool initialize,
            bool loop,
            ref Result result
            ) /* ENTRY-POINT, THREAD-SAFE, RE-ENTRANT */
        {
            IList<string> argv = (args != null) ? new StringList(args) : null;

            TraceOps.DebugTrace(String.Format(
                "{0}: ShellMainCore: entered, interpreter = {1}, " +
                "argumentCallback = {2}, evaluateScriptCallback = {3}, " +
                "evaluateFileCallback = {4}, evaluateEncodedFileCallback = {5}, " +
                "interactiveLoopCallback = {6}, clientData = {7}, argv = {8}, "+
                "initialize = {9}, loop = {10}, result = {11}{12}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    (interpreter != null) ? (object)interpreter.IdNoThrow : null),
                FormatOps.WrapOrNull(FormatOps.DelegateName(argumentCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateScriptCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateFileCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateEncodedFileCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(interactiveLoopCallback)),
                FormatOps.WrapOrNull(clientData), FormatOps.WrapOrNull(true, true, argv),
                initialize, loop, FormatOps.WrapOrNull(true, true, result),
                Environment.NewLine), typeof(Interpreter).Name);

            ExitCode exitCode;
            bool dispose = false;

            if (interpreter != null)
            {
                //
                // NOTE: Keep track of whether our direct caller provided
                //       each of the available shell callbacks.
                //
                bool hadArgumentCallback = (argumentCallback != null);
                bool hadEvaluateScriptCallback = (evaluateScriptCallback != null);
                bool hadEvaluateFileCallback = (evaluateFileCallback != null);
                bool hadEvaluateEncodedFileCallback = (evaluateEncodedFileCallback != null);
                bool hadInteractiveLoopCallback = (interactiveLoopCallback != null);

                //
                // NOTE: Initially, grab each of the shell callbacks from the
                //       interpreter itself if they were not provided by our
                //       direct caller.
                //
                /* NO RESULT */
                interpreter.RefreshShellCallbacks(
                    hadArgumentCallback, hadEvaluateScriptCallback,
                    hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                    hadInteractiveLoopCallback, ref argumentCallback,
                    ref evaluateScriptCallback, ref evaluateFileCallback,
                    ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                //
                // NOTE: Get the file name that started the current process.
                //
                string executableFileName = PathOps.GetExecutableName();

                //
                // NOTE: Get the file name where additional command line
                //       arguments may be found.
                //
                string argvFileName = ShellOps.GetArgumentsFileName(
                    executableFileName);

                //
                // NOTE: Determine if the arguments file, if any, should really
                //       be used.
                //
                bool useArgvFileName = ShellOps.ShouldUseArgumentsFileName(
                    argv);

                //
                // NOTE: We need the return code all over the place in this
                //       method.
                //
                ReturnCode code;

                //
                // NOTE: Fetch the interpreter host now for result reporting
                //       purposes.
                //
                IInteractiveHost interactiveHost = interpreter.Host;

                //
                // NOTE: During shell argument processing, should we
                //       attempt to be as quiet as possible?
                //
                bool quiet = interpreter.ShouldBeQuiet();

                //
                // NOTE: In debug mode, show the command line arguments just
                //       as we received them.
                //
                if (interpreter.Debug)
                {
                    HostOps.WriteLineOrConsole(interactiveHost,
                        String.Format("The executable file name is: {0}",
                            executableFileName));

                    HostOps.WriteLineOrConsole(interactiveHost,
                        String.Format("The arguments file name is: {0}",
                            argvFileName));

                    HostOps.WriteLineOrConsole(interactiveHost,
                        String.Format("Use arguments file name is: {0}",
                            useArgvFileName));

                    HostOps.WriteLineOrConsole(interactiveHost,
                        String.Format("The original command line arguments are: {0}",
                            RuntimeOps.BuildCommandLine(argv, true)));
                }

                //
                // NOTE: If this is non-zero, the interpreter initialization
                //       will be forced (i.e. it will be performed even if it
                //       has already been done).
                //
                bool forceInitialize = false;

                //
                // NOTE: If this value is non-zero after a file is evaluated,
                //       we enter the interactive loop instead of exiting the
                //       process.
                //
                bool noExit = false;

                //
                // NOTE: Command line usage information variables.
                //
                bool showOptions = false;
                bool showEnvironment = false;

                //
                // NOTE: This is the encoding to use for reading a script
                //       file.  It can be set using the "-encoding"
                //       command-line option.
                //
                Encoding encoding = null;

                //
                // NOTE: If the optional file containing additional command
                //       line arguments exits, attempt to read and process it
                //       now; otherwise, do nothing.
                //
                if (useArgvFileName && File.Exists(argvFileName))
                {
                    //
                    // NOTE: Get the stream reader for the file containing
                    //       the arguments to process.
                    //
                    TextReader textReader = ShellOps.GetTextReaderForFile(
                        encoding, argvFileName, false, ref result);

                    if (textReader != null)
                    {
                        //
                        // NOTE: Attempt to read additional command line
                        //       arguments from the file.
                        //
                        code = ShellOps.ReadArgumentsFromFile(
                            interpreter, textReader, /* POP */ 0,
                            true, ref argv, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: In debug mode, show the modified command
                            //       line arguments.
                            //
                            if (interpreter.Debug)
                                HostOps.WriteLineOrConsole(interactiveHost,
                                    String.Format("The modified command line arguments are: {0}",
                                        RuntimeOps.BuildCommandLine(argv, true)));
                        }
                        else
                        {
                            exitCode = ResultOps.ReturnCodeToExitCode(
                                code, true);

                            goto done;
                        }
                    }
                    else
                    {
                        exitCode = ResultOps.FailureExitCode();
                        goto done;
                    }
                }

            retry: // NOTE: Used to continue processing arguments.
                int argc = (argv != null) ? argv.Count : 0;

                //
                // NOTE: Re-fetch interpreter host in case it has changed
                //       out from under us during argument processing.
                //
                interactiveHost = interpreter.Host;

                if (argc > 0)
                {
                    //
                    // NOTE: Grab the first argument in the array.  The
                    //       array is modified as we process the arguments;
                    //       however, we are guaranteed to have at least
                    //       one by the containing if statement.
                    //
                    string arg = argv[0];

                    //
                    // NOTE: Save the original, unmodified argument for
                    //       later error reporting.
                    //
                    string savedArg = arg;

                option:
                    //
                    // NOTE: This is the number of switch chars in front
                    //       of the current argument.
                    //
                    int count = 0;

                    //
                    // NOTE: This trims any leading switch chars from the
                    //       current argument and sets the count to the
                    //       number of switch chars actually removed.
                    //
                    arg = StringOps.TrimSwitchChars(arg, ref count);

                    if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.AnyInitialize))
                    {
                        if (argc >= 2)
                        {
                            int errorLine = 0;

                            code = interpreter.ShellEvaluateScript(
                                evaluateScriptCallback, argv[1], ref result,
                                ref errorLine);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: The shell callbacks may have been changed via
                                //       the evaluated script; therefore, refresh the
                                //       ones which were not directly supplied by the
                                //       caller.
                                //
                                /* NO RESULT */
                                interpreter.RefreshShellCallbacks(
                                    hadArgumentCallback, hadEvaluateScriptCallback,
                                    hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                                    hadInteractiveLoopCallback, ref argumentCallback,
                                    ref evaluateScriptCallback, ref evaluateFileCallback,
                                    ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                                //
                                // NOTE: Ok, remove the first two arguments and
                                //       process the next one.
                                //
                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }
                            else
                            {
                                //
                                // BUGFIX: We may have evaluated some code and the host
                                //         may have been changed; grab it again.
                                //
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    GetShellErrorLine(interpreter, errorLine),
                                    true, false, ref argv, ref interactiveHost,
                                    ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <script>\"",
                                CommandLineOption.AnyInitialize),
                                ref argv, ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Arguments))
                    {
                        if (argc >= 2)
                        {
                            //
                            // NOTE: Get the stream reader for the file containing
                            //       the arguments to process.  If the file name is
                            //       "-" or "stdin", we will end up reading arguments
                            //       from the standard input stream.  Currently, this
                            //       is always done via the Console; however, in the
                            //       future it may use the interpreter host.
                            //
                            TextReader textReader = ShellOps.GetTextReaderForFile(
                                encoding, argv[1], true, ref result);

                            if (textReader != null)
                            {
                                //
                                // NOTE: This method pops its own arguments from
                                //       the list.  The literal "2" in the parameter
                                //       list for ReadArgumentsFromFile is the
                                //       number of arguments that need to be popped
                                //       from the front of the list prior to
                                //       appending any arguments found in the
                                //       specified file.
                                //
                                code = ShellOps.ReadArgumentsFromFile(
                                    interpreter, textReader, /* POP */ 2,
                                    false, ref argv, ref result);

                                if (code == ReturnCode.Ok)
                                    goto retry;
                            }
                            else
                            {
                                code = ReturnCode.Error;
                            }

                            if (code != ReturnCode.Ok)
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <fileName>\"",
                                CommandLineOption.Arguments), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Break))
                    {
                        #region Requires Console Support
#if CONSOLE
                        //
                        // NOTE: Display the debugger prompt and then wait for
                        //       the user to press a key.
                        //
                        Console.WriteLine(String.Format(
                            _Constants.Prompt.Debugger,
                            RuntimeOps.GetCurrentProcessId()));

                        try
                        {
                            Console.ReadKey(true); /* throw */
                        }
                        catch (InvalidOperationException) // Console.ReadKey
                        {
                            // do nothing.
                        }
#endif
                        #endregion

                        ///////////////////////////////////////////////////////

                        //
                        // NOTE: Break into the managed debugger, skipping no
                        //       method to obtain the method name, and force
                        //       the issue because this is the result of a
                        //       direct user request.
                        //
                        DebugOps.Break(interpreter, null, true); /* throw */

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Debug))
                    {
                        //
                        // NOTE: Set the debug flag for the interpreter now.
                        //
                        interpreter.Debug = true;

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Evaluate))
                    {
                        if (initialize)
                        {
                            code = interpreter.PrivateInitialize(
                                forceInitialize, false, ref result);
                        }
                        else
                        {
                            code = ReturnCode.Ok;
                        }

                        int errorLine = 0;

                        if (code == ReturnCode.Ok)
                        {
                            for (int argIndex = 1; argIndex < argc; argIndex++)
                            {
                                string text = argv[argIndex];

                                code = interpreter.ShellEvaluateScript(
                                    evaluateScriptCallback, text, ref result,
                                    ref errorLine);

                                if (code != ReturnCode.Ok)
                                    break;
                            }
                        }

                        if (code != ReturnCode.Ok)
                        {
                            //
                            // BUGFIX: We may have evaluated some code and the host
                            //         may have been changed; grab it again.
                            //
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                GetShellErrorLine(interpreter, errorLine),
                                true, false, ref argv, ref interactiveHost,
                                ref quiet);
                        }

                        //
                        // NOTE: If the exit code for the interpreter is successful,
                        //       use the return code to figure out what this method
                        //       should return (i.e. just in case of a failure to
                        //       initialize, evaluate a script, etc).
                        //
                        if (interpreter.exitCode == ResultOps.SuccessExitCode())
                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        else
                            exitCode = interpreter.exitCode;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.EvaluateEncoded))
                    {
                        if (initialize)
                        {
                            code = interpreter.PrivateInitialize(
                                forceInitialize, false, ref result);
                        }
                        else
                        {
                            code = ReturnCode.Ok;
                        }

                        int errorLine = 0;

                        if (code == ReturnCode.Ok)
                        {
                            Encoding argEncoding = (encoding != null) ?
                                encoding : DefaultEncoding;

                            for (int argIndex = 1; argIndex < argc; argIndex++)
                            {
                                string text = argv[argIndex];

                                try
                                {
                                    text = argEncoding.GetString(
                                        Convert.FromBase64String(text));
                                }
                                catch (Exception e)
                                {
                                    result = e;
                                    code = ReturnCode.Error;
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    code = interpreter.ShellEvaluateScript(
                                        evaluateScriptCallback, text, ref result,
                                        ref errorLine);
                                }

                                if (code != ReturnCode.Ok)
                                    break;
                            }
                        }

                        if (code != ReturnCode.Ok)
                        {
                            //
                            // BUGFIX: We may have evaluated some code and the host
                            //         may have been changed; grab it again.
                            //
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                GetShellErrorLine(interpreter, errorLine),
                                true, false, ref argv, ref interactiveHost,
                                ref quiet);
                        }

                        //
                        // NOTE: If the exit code for the interpreter is successful,
                        //       use the return code to figure out what this method
                        //       should return (i.e. just in case of a failure to
                        //       initialize, evaluate a script, etc).
                        //
                        if (interpreter.exitCode == ResultOps.SuccessExitCode())
                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        else
                            exitCode = interpreter.exitCode;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Encoding))
                    {
                        if (argc >= 2)
                        {
                            code = GetEncoding(interpreter, argv[1],
                                ref encoding, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Ok, remove the first two arguments and
                                //       process the next one.
                                //
                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <encodingName>\"",
                                CommandLineOption.Encoding), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.File))
                    {
                        if (argc >= 2)
                        {
                            if (initialize)
                            {
                                code = interpreter.PrivateInitialize(
                                    forceInitialize, false, ref result);
                            }
                            else
                            {
                                code = ReturnCode.Ok;
                            }

                            if (code == ReturnCode.Ok)
                            {
                                code = interpreter.SetArguments(
                                    new StringList(argv, 2), ref result);
                            }

                            int errorLine = 0;

                            if (code == ReturnCode.Ok)
                            {
                                code = interpreter.ShellEvaluateFile(
                                    evaluateEncodedFileCallback, encoding, argv[1],
                                    ref result, ref errorLine);
                            }

                            if (code != ReturnCode.Ok)
                            {
                                //
                                // BUGFIX: We may have evaluated some code and the host
                                //         may have been changed; grab it again.
                                //
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    GetShellErrorLine(interpreter, errorLine),
                                    true, false, ref argv, ref interactiveHost,
                                    ref quiet);
                            }

                            //
                            // NOTE: If the exit code for the interpreter is successful,
                            //       use the return code to figure out what this method
                            //       should return (i.e. just in case of a failure to
                            //       initialize, evaluate a script, etc).
                            //
                            if (interpreter.exitCode == ResultOps.SuccessExitCode())
                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            else
                                exitCode = interpreter.exitCode;
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <fileName> [arguments]\"",
                                CommandLineOption.File), ref argv, ref interactiveHost,
                                ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.About))
                    {
                        //
                        // NOTE: Show the version banner and copyright notice
                        //       only.
                        //
                        showOptions = false;
                        showEnvironment = false;

                        //
                        // NOTE: We will use the common help option to
                        //       display the information we want.
                        //
                        arg = Characters.MinusSign + CommandLineOption.Help;

                        //
                        // NOTE: Force a jump to the start of the option
                        //       dispatcher.
                        //
                        goto option;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.CommandHelp))
                    {
                        //
                        // NOTE: Show command line options.
                        //
                        showOptions = true;
                        showEnvironment = false;

                        //
                        // NOTE: We will use the common help option to
                        //       display the information we want.
                        //
                        arg = Characters.MinusSign + CommandLineOption.Help;

                        //
                        // NOTE: Force a jump to the start of the option
                        //       dispatcher.
                        //
                        goto option;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.EnvironmentHelp))
                    {
                        //
                        // NOTE: Show environment variables.
                        //
                        showOptions = false;
                        showEnvironment = true;

                        //
                        // NOTE: We will use the common help option to
                        //       display the information we want.
                        //
                        arg = Characters.MinusSign + CommandLineOption.Help;

                        //
                        // NOTE: Force a jump to the start of the option
                        //       dispatcher.
                        //
                        goto option;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.ForceInitialize))
                    {
                        //
                        // NOTE: Always force the interpreter to be initialized.
                        //
                        forceInitialize = true;

                        //
                        // NOTE: If not running in quiet mode, show what we did.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.ForceInitialize);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.FullHelp))
                    {
                        //
                        // NOTE: Show command line options and environment
                        //       settings.
                        //
                        showOptions = true;
                        showEnvironment = true;

                        //
                        // NOTE: We will use the common help option to
                        //       display the information we want.
                        //
                        arg = Characters.MinusSign + CommandLineOption.Help;

                        //
                        // NOTE: Force a jump to the start of the option
                        //       dispatcher.
                        //
                        goto option;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Help))
                    {
                        code = HelpOps.WriteUsage(
                            interpreter, null, true, true, showOptions,
                            showEnvironment, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            if (!quiet && (interactiveHost != null) &&
                                !showOptions && !showEnvironment)
                            {
                                interactiveHost.WriteLine();
                                interactiveHost.WriteLine(String.Format(
                                    "Use the \"-{0}\", \"-{1}\", \"-{2}\", or " +
                                    "\"-{3}\" options for more information.",
                                    CommandLineOption.About,
                                    CommandLineOption.CommandHelp,
                                    CommandLineOption.EnvironmentHelp,
                                    CommandLineOption.FullHelp));
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);
                        }

                        exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Interactive))
                    {
                        //
                        // NOTE: Enable interactive mode for the script debugger.
                        //
                        interpreter.Interactive = true;

                        //
                        // NOTE: If not running in quiet mode, show what we did.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.Interactive);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Initialize))
                    {
                        if (initialize)
                        {
                            code = interpreter.PrivateInitialize(
                                forceInitialize, false, ref result);
                        }
                        else
                        {
                            code = ReturnCode.Ok;
                        }

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Ok, remove the first argument and process
                            //       the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            //
                            // BUGFIX: We may have evaluated some code and the host
                            //         may have been changed; grab it again.
                            //
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                Interpreter.GetErrorLine(interpreter),
                                true, false, ref argv, ref interactiveHost,
                                ref quiet);
                        }

                        exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Library))
                    {
                        //
                        // NOTE: Actually, this argument should have already been
                        //       processed by the GetStartupLibraryPath() method;
                        //       therefore, just skip over it.  However, first
                        //       issue a warning to make sure that the user knows
                        //       about this.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.LibraryPath);

                        //
                        // NOTE: Ok, remove the first two arguments and
                        //       process the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Namespaces))
                    {
                        if (argc >= 2)
                        {
                            bool enable = false;

                            code = Value.GetBoolean2(argv[1], ValueFlags.AnyBoolean,
                                interpreter.CultureInfo, ref enable, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                code = NamespaceOps.Enable(
                                    interpreter, enable, true, ref result);
                            }

                            if (code == ReturnCode.Ok)
                            {
                                if (!quiet && (interactiveHost != null))
                                    interactiveHost.WriteLine(String.Format(
                                        _Constants.Prompt.Namespaces, enable ?
                                            "enabled" : "disabled"));

                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }

                            if (code != ReturnCode.Ok)
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <enable>\"",
                                CommandLineOption.Namespaces), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.NoArgumentsFileName))
                    {
                        //
                        // NOTE: Issue a warning to indicate that processing of
                        //       the arguments file name was skipped.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.NoArgumentsFileName);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.NoExit))
                    {
                        //
                        // NOTE: Always enter the interactive loop instead of
                        //       exiting.
                        //
                        noExit = true;

                        //
                        // NOTE: If not running in quiet mode, show what we did.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.NoExit);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.NoTrace))
                    {
                        //
                        // NOTE: Disable all tracing to the console, etc.
                        //
                        DebugOps.ClearTraceListeners(
                            interpreter.Debug, true, true);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Pause))
                    {
                        if (interactiveHost != null) /* EXEMPT */
                        {
                            //
                            // NOTE: Wait for the user to [attach a debugger
                            //       and] press a key.
                            //
                            interactiveHost.WriteLine(String.Format(
                                _Constants.Prompt.Debugger,
                                RuntimeOps.GetCurrentProcessId()));

                            interactiveHost.Pause();

                            //
                            // NOTE: Ok, remove the first argument and process
                            //       the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            HostOps.WriteConsoleOrComplain(
                                ReturnCode.Error, "interpreter host not available");

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.PluginArguments))
                    {
                        if (argc >= 3)
                        {
                            if (interpreter.AddPluginArguments(argv[1], argv[2], false))
                            {
                                if (!quiet && (interactiveHost != null))
                                    interactiveHost.WriteLine(String.Format(
                                        _Constants.Prompt.PluginArguments, argv[1]));

                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "failed to add plugin arguments",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <pluginName> <arguments>\"",
                                CommandLineOption.PluginArguments), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.PostFile))
                    {
                        if (argc >= 2)
                        {
                            if (interpreter.PrivateInitialized)
                            {
                                int errorLine = 0;

                                code = interpreter.ShellEvaluateFile(
                                    evaluateFileCallback, argv[1], ref result,
                                    ref errorLine);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The shell callbacks may have been changed via
                                    //       the evaluated script; therefore, refresh the
                                    //       ones which were not directly supplied by the
                                    //       caller.
                                    //
                                    /* NO RESULT */
                                    interpreter.RefreshShellCallbacks(
                                        hadArgumentCallback, hadEvaluateScriptCallback,
                                        hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                                        hadInteractiveLoopCallback, ref argumentCallback,
                                        ref evaluateScriptCallback, ref evaluateFileCallback,
                                        ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    //
                                    // BUGFIX: We may have evaluated some code and the host
                                    //         may have been changed; grab it again.
                                    //
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg, code, result,
                                        GetShellErrorLine(interpreter, errorLine),
                                        true, false, ref argv, ref interactiveHost,
                                        ref quiet);
                                }

                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "script library is not initialized",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <fileName>\"",
                                CommandLineOption.PostFile), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.PostInitialize))
                    {
                        if (argc >= 2)
                        {
                            if (interpreter.PrivateInitialized)
                            {
                                int errorLine = 0;

                                code = interpreter.ShellEvaluateScript(
                                    evaluateScriptCallback, argv[1], ref result,
                                    ref errorLine);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The shell callbacks may have been changed via
                                    //       the evaluated script; therefore, refresh the
                                    //       ones which were not directly supplied by the
                                    //       caller.
                                    //
                                    /* NO RESULT */
                                    interpreter.RefreshShellCallbacks(
                                        hadArgumentCallback, hadEvaluateScriptCallback,
                                        hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                                        hadInteractiveLoopCallback, ref argumentCallback,
                                        ref evaluateScriptCallback, ref evaluateFileCallback,
                                        ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    //
                                    // BUGFIX: We may have evaluated some code and the host
                                    //         may have been changed; grab it again.
                                    //
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg, code, result,
                                        GetShellErrorLine(interpreter, errorLine),
                                        true, false, ref argv, ref interactiveHost,
                                        ref quiet);
                                }

                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "script library is not initialized",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <script>\"",
                                CommandLineOption.PostInitialize), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.PreFile))
                    {
                        if (argc >= 2)
                        {
                            if (!interpreter.PrivateInitialized)
                            {
                                int errorLine = 0;

                                code = interpreter.ShellEvaluateFile(
                                    evaluateFileCallback, argv[1], ref result,
                                    ref errorLine);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The shell callbacks may have been changed via
                                    //       the evaluated script; therefore, refresh the
                                    //       ones which were not directly supplied by the
                                    //       caller.
                                    //
                                    /* NO RESULT */
                                    interpreter.RefreshShellCallbacks(
                                        hadArgumentCallback, hadEvaluateScriptCallback,
                                        hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                                        hadInteractiveLoopCallback, ref argumentCallback,
                                        ref evaluateScriptCallback, ref evaluateFileCallback,
                                        ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    //
                                    // BUGFIX: We may have evaluated some code and the host
                                    //         may have been changed; grab it again.
                                    //
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg, code, result,
                                        GetShellErrorLine(interpreter, errorLine),
                                        true, false, ref argv, ref interactiveHost,
                                        ref quiet);
                                }

                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "script library is already initialized",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <fileName>\"",
                                CommandLineOption.PreFile),
                                ref argv, ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.PreInitialize))
                    {
                        if (argc >= 2)
                        {
                            if (!interpreter.PrivateInitialized)
                            {
                                int errorLine = 0;

                                code = interpreter.ShellEvaluateScript(
                                    evaluateScriptCallback, argv[1], ref result,
                                    ref errorLine);

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The shell callbacks may have been changed via
                                    //       the evaluated script; therefore, refresh the
                                    //       ones which were not directly supplied by the
                                    //       caller.
                                    //
                                    /* NO RESULT */
                                    interpreter.RefreshShellCallbacks(
                                        hadArgumentCallback, hadEvaluateScriptCallback,
                                        hadEvaluateFileCallback, hadEvaluateEncodedFileCallback,
                                        hadInteractiveLoopCallback, ref argumentCallback,
                                        ref evaluateScriptCallback, ref evaluateFileCallback,
                                        ref evaluateEncodedFileCallback, ref interactiveLoopCallback);

                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    //
                                    // BUGFIX: We may have evaluated some code and the host
                                    //         may have been changed; grab it again.
                                    //
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg, code, result,
                                        GetShellErrorLine(interpreter, errorLine),
                                        true, false, ref argv, ref interactiveHost,
                                        ref quiet);
                                }

                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "script library is already initialized",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <script>\"",
                                CommandLineOption.PreInitialize),
                                ref argv, ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Profile))
                    {
                        if (argc >= 2)
                        {
                            _Hosts.Core coreHost = interactiveHost as _Hosts.Core;

                            if (coreHost != null)
                            {
                                //
                                // NOTE: Set the profile to the one specified on the
                                //       command line.
                                //
                                coreHost.Profile = argv[1];

                                //
                                // NOTE: Now, we can grab the dynamically constructed
                                //       host profile file name and use it to reload
                                //       the profile.
                                //
                                string fileName = coreHost.HostProfileFileName;

                                if (_Hosts.Core.LoadHostProfile(
                                        interpreter, coreHost, coreHost.GetType(),
                                        encoding, fileName, false, false, ref result))
                                {
                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg, String.Format(
                                        "failed to reload host profile: {0}", result),
                                        ref argv, ref interactiveHost, ref quiet);

                                    exitCode = ResultOps.FailureExitCode();
                                }
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    String.Format(HostOps.NoFeatureError,
                                        typeof(_Hosts.Core).Name),
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <profile>\"",
                                CommandLineOption.Profile), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Reconfigure))
                    {
                        if (argc >= 2)
                        {
#if XML && SERIALIZATION
                            InterpreterSettings interpreterSettings = null;

                            code = InterpreterSettings.LoadFrom(argv[1], true,
                                ref interpreterSettings, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                try
                                {
                                    //
                                    // NOTE: We plan on re-creating the active
                                    //       interpreter (below); therefore, we
                                    //       must dispose the current one first.
                                    //
                                    if (interpreter != null)
                                    {
                                        interpreter.Dispose(); /* throw */
                                        interpreter = null;

                                        //
                                        // NOTE: If this command line option has
                                        //       been used before, the disposal
                                        //       flag will be set (i.e. because
                                        //       we created the interpreter that
                                        //       was just disposed).  Therefore,
                                        //       reset it now since the disposal
                                        //       of the interpreter is complete.
                                        //
                                        dispose = false;
                                    }
                                }
                                catch (Exception e)
                                {
                                    result = e;
                                    code = ReturnCode.Error;
                                }
                            }

                            if (code == ReturnCode.Ok)
                            {
                                interpreter = Create(
                                    interpreterSettings, true, ref result);

                                if (interpreter != null)
                                {
                                    //
                                    // NOTE: This method has now re-created the
                                    //       active interpreter; therefore, it
                                    //       must be disposed by this method
                                    //       before exiting.
                                    //
                                    dispose = true;

                                    //
                                    // NOTE: Ok, remove the first two arguments
                                    //       and process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    code = ReturnCode.Error;
                                }
                            }
#else
                            result = "not implemented";
                            code = ReturnCode.Error;
#endif

                            if (code != ReturnCode.Ok)
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <settings>\"",
                                CommandLineOption.Reconfigure), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.RuntimeOption))
                    {
                        if (argc >= 2)
                        {
                            if (interpreter.PrivateInitialized)
                            {
                                if (interpreter.ChangeRuntimeOption(argv[1]))
                                {
                                    //
                                    // NOTE: Ok, remove the first two arguments and
                                    //       process the next one.
                                    //
                                    GenericOps<string>.PopFirstArgument(ref argv);
                                    GenericOps<string>.PopFirstArgument(ref argv);

                                    goto retry;
                                }
                                else
                                {
                                    //
                                    // BUGFIX: We may have evaluated some code and the host
                                    //         may have been changed; grab it again.
                                    //
                                    ShellOps.ShellMainCoreError(
                                        interpreter, savedArg, arg,
                                        "failed to change runtime option",
                                        ref argv, ref interactiveHost, ref quiet);
                                }

                                exitCode = ResultOps.FailureExitCode();
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg,
                                    "script library is not initialized",
                                    ref argv, ref interactiveHost, ref quiet);

                                exitCode = ResultOps.FailureExitCode();
                            }
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <optionName>\"",
                                CommandLineOption.RuntimeOption),
                                ref argv, ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Safe))
                    {
                        //
                        // NOTE: Make the interpreter "safe".
                        //
                        code = interpreter.MakeSafe(
                            MakeFlags.SafeShell, true, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Ok, remove the first argument and process
                            //       the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);
                        }

                        exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.SetInitialize))
                    {
                        if (argc >= 2)
                        {
                            code = Value.GetBoolean2(argv[1], ValueFlags.AnyBoolean,
                                interpreter.CultureInfo, ref initialize, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: If not running in quiet mode, show what we did.
                                //
                                if (!quiet && (interactiveHost != null))
                                {
                                    if (initialize)
                                        interactiveHost.WriteLine(_Constants.Prompt.Initialize);
                                    else
                                        interactiveHost.WriteLine(_Constants.Prompt.NoInitialize);
                                }

                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }

                            if (code != ReturnCode.Ok)
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <enable>\"",
                                CommandLineOption.SetInitialize), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.SetLoop))
                    {
                        if (argc >= 2)
                        {
                            code = Value.GetBoolean2(argv[1], ValueFlags.AnyBoolean,
                                interpreter.CultureInfo, ref loop, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: If not running in quiet mode, show what we did.
                                //
                                if (!quiet && (interactiveHost != null))
                                {
                                    if (loop)
                                        interactiveHost.WriteLine(_Constants.Prompt.Loop);
                                    else
                                        interactiveHost.WriteLine(_Constants.Prompt.NoLoop);
                                }

                                GenericOps<string>.PopFirstArgument(ref argv);
                                GenericOps<string>.PopFirstArgument(ref argv);

                                goto retry;
                            }

                            if (code != ReturnCode.Ok)
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, savedArg, arg, code, result,
                                    ref argv, ref interactiveHost, ref quiet);
                            }

                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <enable>\"",
                                CommandLineOption.SetLoop), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Standard))
                    {
                        //
                        // NOTE: Make the interpreter "standard".
                        //
                        code = interpreter.MakeStandard(
                            MakeFlags.StandardShell, true, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Ok, remove the first argument and process
                            //       the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);
                        }

                        exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Step))
                    {
#if DEBUGGER
                        //
                        // NOTE: Enable single-step mode for the script debugger.
                        //
                        interpreter.SingleStep = true;

                        //
                        // NOTE: If not running in quiet mode, show what we did.
                        //
                        if (!quiet && (interactiveHost != null))
                            interactiveHost.WriteLine(_Constants.Prompt.SingleStep);
#else
                        //
                        // NOTE: Issue a warning because the script debugger is
                        //       not available.
                        //
                        if (interactiveHost != null)
                            interactiveHost.WriteLine(_Constants.Prompt.NoDebugger);
#endif

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        (StringOps.MatchSwitch(arg, CommandLineOption.Test) ||
                        StringOps.MatchSwitch(arg, CommandLineOption.PluginTest)))
                    {
                        if (initialize)
                        {
                            code = interpreter.PrivateInitialize(
                                forceInitialize, false, ref result);
                        }
                        else
                        {
                            code = ReturnCode.Ok;
                        }

                        if (code == ReturnCode.Ok)
                        {
                            code = interpreter.SetArguments(
                                new StringList(argv, 3), ref result);
                        }

                        bool all = false;

                        if ((code == ReturnCode.Ok) && (argc >= 3))
                        {
                            code = Value.GetBoolean2(argv[2], ValueFlags.AnyBoolean,
                                interpreter.CultureInfo, ref all, ref result);
                        }

                        int errorLine = 0;

                        if (code == ReturnCode.Ok)
                        {
                            code = TestOps.ShellMain(
                                interpreter, (argc >= 2) ? argv[1] : null,
                                interpreter.EngineFlags, interpreter.SubstitutionFlags,
                                interpreter.EngineEventFlags, interpreter.ExpressionFlags,
                                StringOps.MatchSwitch(arg, CommandLineOption.PluginTest),
                                all, ref result, ref errorLine);
                        }

                        if (code != ReturnCode.Ok)
                        {
                            //
                            // BUGFIX: We may have evaluated some code and the host
                            //         may have been changed; grab it again.
                            //
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                GetShellErrorLine(interpreter, errorLine),
                                true, false, ref argv, ref interactiveHost,
                                ref quiet);
                        }

                        //
                        // NOTE: If the exit code for the interpreter is successful,
                        //       use the return code to figure out what this method
                        //       should return (i.e. just in case of a failure to
                        //       initialize, evaluate a script, etc).
                        //
                        if (interpreter.exitCode == ResultOps.SuccessExitCode())
                            exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                        else
                            exitCode = interpreter.exitCode;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.TestDirectory))
                    {
                        if (argc >= 2)
                        {
                            interpreter.TestPath = argv[1];

                            //
                            // NOTE: Ok, remove the first two arguments and
                            //       process the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <directory>\"",
                                CommandLineOption.TestDirectory), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Trace))
                    {
                        //
                        // NOTE: Add our standard trace listeners (if necessary).
                        //       This should have no effect if they have already
                        //       been added (i.e. by the environment variable
                        //       being set).
                        //
                        DebugOps.SetupTraceListeners(
                            true, interpreter.Debug, true, true);

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.TraceToHost))
                    {
                        //
                        // NOTE: Set the trace-to-host interpreter flag now.
                        //
                        interpreter.InterpreterFlags |= InterpreterFlags.TraceToHost;

                        //
                        // NOTE: Ok, remove the first argument and process
                        //       the next one.
                        //
                        GenericOps<string>.PopFirstArgument(ref argv);

                        goto retry;
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.VendorPath))
                    {
                        if (argc >= 2)
                        {
                            GlobalState.SetEnvironmentVariable(
                                EnvVars.VendorPath, argv[1], true);

                            //
                            // NOTE: Ok, remove the first two arguments and
                            //       process the next one.
                            //
                            GenericOps<string>.PopFirstArgument(ref argv);
                            GenericOps<string>.PopFirstArgument(ref argv);

                            goto retry;
                        }
                        else
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, String.Format(
                                "wrong # args: should be \"-{0} <directory>\"",
                                CommandLineOption.VendorPath), ref argv,
                                ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else if ((count > 0) &&
                        StringOps.MatchSwitch(arg, CommandLineOption.Version))
                    {
                        code = HelpOps.WriteVersion(
                            interpreter, true, true, true, true, true, true,
                            ref result);

                        if (code != ReturnCode.Ok)
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);
                        }

                        exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                    }
                    else if (argumentCallback != null)
                    {
                        try
                        {
                            code = argumentCallback(
                                interpreter, interactiveHost, clientData,
                                count, arg, ref argv, ref result);
                        }
                        catch (Exception e)
                        {
                            result = e;
                            code = ReturnCode.Error;
                        }

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Process the next [standard or custom]
                            //       argument now.
                            //
                            goto retry;
                        }
                        else
                        {
                            //
                            // BUGFIX: We may have evaluated some code and the host
                            //         may have been changed; grab it again.
                            //
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                    else
                    {
                        code = HelpOps.WriteUsage(interpreter, String.Format(
                            "invalid argument \"{0}\", use \"-{1}\" for help",
                            savedArg, CommandLineOption.Help), false, false,
                            false, false, ref result);

                        if (code != ReturnCode.Ok)
                        {
                            ShellOps.ShellMainCoreError(
                                interpreter, savedArg, arg, code, result,
                                ref argv, ref interactiveHost, ref quiet);
                        }

                        exitCode = ResultOps.FailureExitCode();
                    }

                    //
                    // NOTE: If requested, force entry into interactive loop.
                    //
                    if (noExit)
                    {
                        //
                        // NOTE: It is necessary to invalidate the command line
                        //       arguments here; otherwise, the interactive loop
                        //       will not be entered.
                        //
                        argv = null;
                        argc = 0;

                        goto retry;
                    }
                }
                else if (loop)
                {
                    if (initialize)
                    {
                        code = interpreter.PrivateInitialize(
                            forceInitialize, false, ref result);
                    }
                    else
                    {
                        code = ReturnCode.Ok;
                    }

                    if (code == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Always use the original command line arguments
                        //       (as passed by the caller) here; otherwise, we
                        //       should always end up with a null argument list
                        //       because we cannot get to this block of code
                        //       unless there are no arguments left to process
                        //       (or there never were any to begin with).
                        //
                        if (interactiveLoopCallback != null)
                        {
                            //
                            // NOTE: Use the specified interactive loop callback
                            //       instead of the default interactive loop
                            //       implementation.  All the defaulted parameter
                            //       values here should match those used by the
                            //       InteractiveLoop method overload that accepts
                            //       three parameters (i.e. the one used by this
                            //       method).
                            //
                            bool exit = false; /* NOT USED */

                            try
                            {
                                code = interactiveLoopCallback(
                                    interpreter, false, args, ReturnCode.Ok,
                                    BreakpointType.None, null, null, null,
                                    EngineFlags.None, SubstitutionFlags.Default,
                                    EventFlags.Default, ExpressionFlags.Default,
                                    HeaderFlags.None, null, null, ref exit,
                                    ref result);
                            }
                            catch (Exception e)
                            {
                                result = e;
                                code = ReturnCode.Error;

                                //
                                // NOTE: *SPECIAL* The custom interactive loop
                                //       threw an exception and may not have set
                                //       the exit code; therefore, use the error
                                //       return code instead.
                                //
                                exitCode = ResultOps.ReturnCodeToExitCode(
                                    code, true);
                            }
                        }
                        else
                        {
                            code = InteractiveLoop(interpreter, args, ref result);
                        }
                    }
                    else
                    {
                        //
                        // BUGFIX: We may have evaluated some code and the host
                        //         may have been changed; grab it again.
                        //
                        ShellOps.ShellMainCoreError(
                            interpreter, null, null, code, result,
                            Interpreter.GetErrorLine(interpreter),
                            false, false, ref argv, ref interactiveHost,
                            ref quiet);
                    }

                    //
                    // NOTE: The return code is not used here to determine
                    //       the exit code.  Instead, the exit code for the
                    //       interpreter is used directly.
                    //
                    exitCode = interpreter.exitCode;
                }
                else
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: ShellMainCore: interactive loop skipped{1}",
                        GlobalState.GetCurrentThreadId(), Environment.NewLine),
                        typeof(Interpreter).Name);

                    //
                    // NOTE: The return code is not used here to determine
                    //       the exit code.  Instead, the exit code for the
                    //       interpreter is used directly.
                    //
                    exitCode = interpreter.exitCode;
                }
            }
            else
            {
                result = "invalid interpreter";

                //
                // NOTE: Interpreter is invalid and we have no host available.
                //
                HostOps.WriteConsoleOrComplain(ReturnCode.Error, result);

                exitCode = ResultOps.FailureExitCode();
            }

        done:

            //
            // NOTE: Do we need to dispose of the interpreter now?  This will only
            //       occur if the -reconfigure command line option was used, which
            //       causes the interpreter to be re-created locally in this method.
            //       Otherwise, the using statement in use by the caller, if any,
            //       would take care of any disposal.
            //
            if (dispose)
            {
                ReturnCode disposeCode;
                Result disposeError = null;

                disposeCode = ObjectOps.TryDispose(interpreter,
                    ref disposeError);

                if (disposeCode != ReturnCode.Ok)
                    DebugOps.Complain(interpreter, disposeCode, disposeError);
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: ShellMainCore: exited, interpreter = {1}, " +
                "argumentCallback = {2}, evaluateScriptCallback = {3}, " +
                "evaluateFileCallback = {4}, evaluateEncodedFileCallback = {5}, " +
                "interactiveLoopCallback = {6}, clientData = {7}, argv = {8}, " +
                "initialize = {9}, loop = {10}, result = {11}, exitCode = {12}{13}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    (interpreter != null) ? (object)interpreter.IdNoThrow : null),
                FormatOps.WrapOrNull(FormatOps.DelegateName(argumentCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateScriptCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateFileCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(evaluateEncodedFileCallback)),
                FormatOps.WrapOrNull(FormatOps.DelegateName(interactiveLoopCallback)),
                FormatOps.WrapOrNull(clientData), FormatOps.WrapOrNull(true, true, argv),
                initialize, loop, FormatOps.WrapOrNull(true, true, result), exitCode,
                Environment.NewLine), typeof(Interpreter).Name);

            return exitCode;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Standard Shell Entry Point
#if SHELL
        public static ExitCode ShellMain(
            IEnumerable<string> args
            ) /* ENTRY-POINT, THREAD-SAFE, RE-ENTRANT */
        {
            ExitCode exitCode;

            try
            {
                //
                // NOTE: Start with default shell flags.
                //
                CreateFlags createFlags = CreateFlags.ShellUse;

                //
                // NOTE: Get the effective interpreter creation flags for the
                //       shell from the environment, etc.
                //
                createFlags = GetStartupCreateFlags(args, createFlags,
                    OptionOriginFlags.All, true, true);

                //
                // NOTE: Start with the default library path (i.e. automatic).
                //
                string libraryPath = null;

                //
                // NOTE: We need return code and a result variable very early
                //       on now for startup library path processing and/or in
                //       case interpreter creation fails.
                //
                ReturnCode code;
                Result result = null;

                code = GetStartupLibraryPath(args, createFlags,
                    OptionOriginFlags.All, true, true, ref libraryPath,
                    ref result);

                if (code == ReturnCode.Ok)
                {
                    //
                    // NOTE: Create an interpreter now inside of a using block
                    //       so that we can be relatively sure it will be
                    //       finalized on this thread.
                    //
                    using (Interpreter interpreter = Create(
                            args, createFlags, libraryPath, ref result))
                    {
                        //
                        // NOTE: Make sure the interpreter was created.  This
                        //       can (in theory) be a problem if/when the
                        //       ThrowOnError flag ends up getting removed
                        //       somehow prior to the call to actually create
                        //       the interpreter.
                        //
                        if (interpreter != null)
                        {
                            //
                            // NOTE: By default, initialize the script library
                            //       and enter the interactive loop.
                            //
                            bool initialize = true;
                            bool loop = true;

                            //
                            // NOTE: Process all the remaining startup options
                            //       (i.e. the ones that do not modify the
                            //       interpreter creation flags or library path)
                            //       now.
                            //
                            code = ProcessStartupOptions(
                                interpreter, args, createFlags,
                                OptionOriginFlags.All, true, true,
                                ref initialize, ref loop, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                exitCode = ShellMainCore(
                                    interpreter, null, null, null, null, null,
                                    null, args, initialize, loop, ref result);
                            }
                            else
                            {
                                ShellOps.ShellMainCoreError(
                                    interpreter, null, null, code, result);

                                exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Creation of the interpreter failed.
                            //
                            HostOps.WriteConsoleOrComplain(ReturnCode.Error, result);

                            exitCode = ResultOps.FailureExitCode();
                        }
                    }
                }
                else
                {
                    //
                    // NOTE: Library path processing failed.
                    //
                    HostOps.WriteConsoleOrComplain(ReturnCode.Error, result);

                    exitCode = ResultOps.ReturnCodeToExitCode(code, true);
                }
            }
            catch (Exception e)
            {
                //
                // WARNING: Top-level unhandled exception handler.
                //          We should never get here.  If we do then
                //          something has gone really wrong and should
                //          be complained about loudly.
                //
                string message = String.Format("UNHANDLED EXCEPTION: {0}", e);

                //
                // NOTE: We cannot rely on the Interpreter now (nor the
                //       IHost contained within it); therefore, output
                //       directly to the console.
                //
                HostOps.WriteConsoleOrComplain(ReturnCode.Error, message);

                //
                // NOTE: Output to trace listeners.
                //
                DebugOps.TraceWriteLine(message, null);

                //
                // NOTE: Break into the debugger, if one is attached.
                //
                if (DebugOps.IsAttached())
                {
                    DebugOps.Log(message);
                    DebugOps.Break();
                }

                //
                // NOTE: Re-throw the exception if we have been requested
                //       to do so.
                //
                if (GlobalState.GetEnvironmentVariable(EnvVars.Throw, true,
                        false) != null)
                {
                    throw;
                }

                //
                // TODO: The ability to diagnostic send memory dumps here.
                //
                exitCode = ResultOps.ExceptionExitCode();
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            try
            {
                long[] totalMemory = { 0, 0 };

                ObjectOps.GetTotalMemory(true,
                    ref totalMemory[0], ref totalMemory[1]);

                TraceOps.DebugTrace(String.Format(
                    "{0}: ShellMain: exited, exitCode = {1}, " +
                    "totalMemory[0] = {2}, totalMemory[1] = {3}{4}",
                    GlobalState.GetCurrentThreadId(), exitCode,
                    totalMemory[0], totalMemory[1], Environment.NewLine),
                    typeof(Interpreter).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }

            return exitCode;
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Loop Support
        #region Interactive Debugger Support
#if DEBUGGER
        private EngineFlags BeginDebuggerExecution()
        {
            lock (syncRoot)
            {
                EngineFlags savedEngineFlags = engineFlags;

                engineFlags |= EngineFlags.DebuggerExecution;

                return savedEngineFlags;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void EndDebuggerExecution(
            EngineFlags savedEngineFlags
            )
        {
            lock (syncRoot)
            {
                engineFlags = savedEngineFlags;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Exit Support
#if SHELL
        private static void CheckExit(
            Interpreter interpreter,
            ref bool exit
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
                {
                    if (!interpreter.PrivateDisposed)
                    {
                        bool newExit = interpreter.Exit;

                        if (newExit && !exit)
                            exit = newExit;
                    }
                }
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Prompt Support
#if SHELL
        private static void Prompt(
            IInteractiveHost interactiveHost,
            HostFlags hostFlags,
            PromptType type,
            bool trace,
            bool debug,
            bool queue,
            ref bool done
            )
        {
            PromptFlags promptFlags = PromptFlags.None;

            //
            // NOTE: Set the prompt flags based on the parameters specified
            //       by our caller.
            //
            if (debug) promptFlags |= PromptFlags.Debug;
            if (queue) promptFlags |= PromptFlags.Queue;

            //
            // NOTE: We require an interactive host to display a custom prompt
            //       (or even to display a default prompt).
            //
            if (interactiveHost != null)
            {
                ReturnCode code;
                Result error = null;

                //
                // NOTE: Request the host to display some a prompt appropriate
                //       for the specified prompt type and flags.
                //
                try
                {
                    if (FlagOps.HasFlags(hostFlags, HostFlags.Prompt, true))
                    {
                        code = interactiveHost.Prompt(
                            type, ref promptFlags, ref error); /* throw */
                    }
                    else
                    {
                        error = String.Format(
                            HostOps.NoFeatureError, HostFlags.Prompt);

                        code = ReturnCode.Error;
                    }
                }
                catch (Exception e)
                {
                    error = e;
                    code = ReturnCode.Error;
                }

                //
                // NOTE: If tracing is enabled, emit key information about the
                //       success -OR- failure to display the prompt.
                //
                if (trace)
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: Prompt: code = {1}, flags = {2}, error = {3}{4}",
                        GlobalState.GetCurrentThreadId(), code,
                        FormatOps.WrapOrNull(promptFlags), FormatOps.WrapOrNull(
                        true, true, error), Environment.NewLine),
                        typeof(Interpreter).Name);
                }

                //
                // NOTE: If the host failed to display some type of prompt,
                //       fallback to an appropriate default prompt now.
                //
                if (!FlagOps.HasFlags(promptFlags, PromptFlags.Done, true))
                {
                    //
                    // NOTE: Get the appropriate default prompt for this
                    //       situation.
                    //
                    string prompt = HostOps.GetDefaultPrompt(type, promptFlags);

                    //
                    // NOTE: If there is a prompt configured and we cannot
                    //       write it, this is considered to be an error
                    //       fatal to the interactive loop.
                    //
                    if ((prompt != null) && !interactiveHost.Write(prompt))
                    {
                        //
                        // NOTE: If we cannot display prompts, there is not
                        //       much point in the interactive loop.
                        //
                        done = true;
                    }
                }
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Input Support
#if SHELL
        private static bool ReadInteractiveInput(
            IInteractiveHost interactiveHost,
            bool trace,
            ref string value,
            ref bool done
            )
        {
            if (interactiveHost != null)
            {
                try
                {
                    return interactiveHost.ReadLine(ref value); /* throw */
                }
                catch (ThreadAbortException)
                {
                    Thread.ResetAbort();

                    done = true; /* NOTE: Aborted, we are done. */

                    if (trace)
                    {
                        TraceOps.DebugTrace(String.Format(
                            "{0}: ReadInteractiveInput: caught thread abort.{1}",
                            GlobalState.GetCurrentThreadId(), Environment.NewLine),
                            typeof(Interpreter).Name);
                    }
                }
                catch
                {
                    // do nothing.
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: This method is private, very specialized, subject to change
        //          at any time, and is really only designed to be called from
        //          within the InteractiveLoop method.  Therefore, use this
        //          method at your own risk.
        //
        internal static void GetInteractiveInput(
            Interpreter interpreter,              /* in */
            bool noInteractive,                   /* in */
            bool trace,                           /* in */
            bool debug,                           /* in */
            bool queue,                           /* in */
            SubstitutionFlags substitutionFlags,  /* in */
            IClientData clientData,               /* in */
            bool forceCancel,                     /* in */
            bool forceHalt,                       /* in */
            ref IInteractiveHost interactiveHost, /* in, out */
            ref string savedText,                 /* in, out */
            ref bool exit,                        /* in, out */
            ref bool done,                        /* in, out */
            ref bool previous,                    /* out */
            out bool canceled,                    /* out */
            out string text,                      /* out */
            out bool notReady,                    /* out */
            out Result parseError                 /* out */
            )
        {
            //
            // NOTE: Grab the host flags now as we need them to determine if
            //       the prompt can and should [always] be displayed.
            //
            HostFlags hostFlags = HostOps.GetFlags(interactiveHost);

            //
            // NOTE: Re-fetch the interpreter host in case it has been
            //       externally modified or closed.  Also, make sure it is
            //       still open.  If either of these checks fail or return
            //       false, bail out now.
            //
            bool isOpen = HostOps.IsOpen(
                interpreter, hostFlags, ref interactiveHost);

            //
            // BUGFIX: Verify that the interactive host is still valid and
            //         open.  If not, the rest of this method is basically
            //         useless and we are done.
            //
            if (!isOpen)
            {
                done = true; /* NOTE: Invalid or closed host, we are done. */

                if (trace)
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetInteractiveInput: leaving, host " +
                        "is already invalid or closed, exit = {1}, " +
                        "interactiveHost = {2}, isOpen = {3}{4}",
                        GlobalState.GetCurrentThreadId(), exit,
                        (interactiveHost != null), isOpen,
                        Environment.NewLine), typeof(Interpreter).Name);

                //
                // NOTE: Reset the variables used by our caller (the main
                //       interactive loop).
                //
                canceled = false;
                text = null;
                notReady = false;
                parseError = null;

                return;
            }

            ReturnCode resetCode;
            Result resetError = null;

            //
            // NOTE: We must reset the script cancellation flags if we can
            //       (i.e. if no evals are pending), because the IsComplete
            //       method now relies upon the Ready method prior to the
            //       Engine.Evaluate* method having been called (which would
            //       normally cooperatively reset the script cancellation
            //       flags prior to checking them), which checks the script
            //       cancellation flags.
            //
            bool resetCancel = false;

            resetCode = Engine.ResetCancel(
                interpreter, forceCancel, ref resetCancel, ref resetError);

            if (resetCode == ReturnCode.Ok)
            {
                if (trace)
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetInteractiveInput: cancel flags {1}.{2}",
                        GlobalState.GetCurrentThreadId(), resetCancel ?
                        "reset" : "not reset", Environment.NewLine),
                        typeof(Interpreter).Name);
            }
            else
            {
                if (trace)
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetInteractiveInput: failed to reset cancel " +
                        "flags.{1}", GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(Interpreter).Name);

                DebugOps.Complain(interpreter, resetCode, resetError);
            }

            //
            // NOTE: We must reset the debugger halt flags if we can (i.e.
            //       if no evals are pending and no other interactive loops
            //       are active), because Parser.IsComplete now relies upon
            //       Interpreter.Ready prior to Engine.Evaluate* having been
            //       called (which would normally cooperatively reset the
            //       debugger halt flags prior to checking them), which checks
            //       the debugger halt flags.
            //
            bool resetHalt = false;

            resetCode = Engine.ResetHalt(
                interpreter, forceHalt, true, ref resetHalt, ref resetError);

            if (resetCode == ReturnCode.Ok)
            {
                if (trace)
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetInteractiveInput: halt flags {1}.{2}",
                        GlobalState.GetCurrentThreadId(), resetHalt ?
                        "reset" : "not reset", Environment.NewLine),
                        typeof(Interpreter).Name);
            }
            else
            {
                if (trace)
                    TraceOps.DebugTrace(String.Format(
                        "{0}: GetInteractiveInput: failed to reset halt " +
                        "flags.{1}", GlobalState.GetCurrentThreadId(),
                        Environment.NewLine), typeof(Interpreter).Name);

                DebugOps.Complain(interpreter, resetCode, resetError);
            }

            //
            // NOTE: Does the host want to force the prompt to be displayed
            //       even if input has been redirected?  If so, just do it.
            //       Otherwise, check if the host input is NOT currently being
            //       redirected (i.e. we currently have an interactive user)
            //       and then display the prompt prior to requesting any input
            //       from the host.
            //
            if (FlagOps.HasFlags(hostFlags, HostFlags.ForcePrompt, true) ||
                !HostOps.IsInputRedirected(interactiveHost))
            {
                Prompt(interactiveHost,
                    hostFlags, PromptType.Start, trace, debug, queue,
                    ref done);

                if (done)
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: leaving, done flag " +
                            "was set by start prompt{1}",
                            GlobalState.GetCurrentThreadId(),
                            Environment.NewLine), typeof(Interpreter).Name);

                    //
                    // NOTE: Reset the variables used by our caller (the main
                    //       interactive loop).
                    //
                    canceled = false;
                    text = null;
                    notReady = false;
                    parseError = null;

                    return;
                }
            }

            //
            // NOTE: Check if the debugger is set to enter the interactive loop
            //       upon script cancellation.
            //
            bool breakOnCancel =
                DebuggerOps.GetBreakOnCancel(interpreter, false);

            //
            // NOTE: Reset the variables used by our caller (the main
            //       interactive loop).
            //
            canceled = false;
            text = String.Empty; // NOTE: Cannot be null.
            notReady = breakOnCancel; // NOTE: Bypass readiness?
            parseError = null;

            //
            // NOTE: This is the starting index used for the call to the parser
            //       to check if the input is complete.  This value should be
            //       just past the interactive command indicator, if present;
            //       otherwise, it should be zero.
            //
            int startIndex;

            do
            {
                //
                // NOTE: Re-grab the host flags now as they may have changed
                //       (?) and we need them to determine if the prompt can
                //       and should [always] be displayed.
                //
                hostFlags = HostOps.GetFlags(interactiveHost);

                //
                // NOTE: Was there a parser error just now when we checked if
                //       the input text was a complete command?
                //
                if (parseError != null)
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: incomplete input, " +
                            "parseError = {1}{2}",
                            GlobalState.GetCurrentThreadId(),
                            FormatOps.WrapOrNull(parseError),
                            Environment.NewLine), typeof(Interpreter).Name);

                    //
                    // NOTE: Does this host support multiple-line input?
                    //
                    if (FlagOps.HasFlags(
                            hostFlags, HostFlags.MultipleLineInput, true))
                    {
                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: multiple-line " +
                                "input is supported, setting canceled " +
                                "flag...{1}", GlobalState.GetCurrentThreadId(),
                                Environment.NewLine), typeof(Interpreter).Name);

                        //
                        // NOTE: For hosts that support multiple-line input,
                        //       we will not accept any incomplete input.
                        //       Therefore, bail out now with an "error" (i.e.
                        //       or at least our closest approximation of one).
                        //
                        canceled = true;

                        break;
                    }

                    //
                    // NOTE: In the event of a parser error (i.e. if the line
                    //       entered does not represent a complete command)
                    //       display the error in the host title.
                    //
                    /* IGNORED */
                    HostOps.SetTitle(interactiveHost, String.Format(
                        "incomplete: {0}", parseError));

                    /* IGNORED */
                    // HostOps.WriteLine(interactiveHost,
                    //     String.Format("incomplete: {0}", parseError));

                    parseError = null;
                }

                //
                // NOTE: Re-check if the host input is being redirected (i.e.
                //       we do not have an interactive user) then display the
                //       input continuation prompt if necessary prior to
                //       requesting more input from the host.
                //
                bool redirected = HostOps.IsInputRedirected(interactiveHost);

                if (!String.IsNullOrEmpty(text) && (!redirected ||
                    FlagOps.HasFlags(hostFlags, HostFlags.ForcePrompt, true)))
                {
                    Prompt(interactiveHost,
                        hostFlags, PromptType.Continue, trace, debug, queue,
                        ref done);

                    if (done)
                    {
                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: leaving, done flag " +
                                "was set by continue prompt{1}",
                                GlobalState.GetCurrentThreadId(),
                                Environment.NewLine), typeof(Interpreter).Name);

                        //
                        // NOTE: Reset the variables used by our caller (the main
                        //       interactive loop).
                        //
                        canceled = false;
                        text = null;
                        notReady = false;
                        parseError = null;

                        return;
                    }
                }

                string line = null; // NOTE: Current input line.
                int length; // NOTE: Length of the current input line.

                //
                // NOTE: Check and see if the previous iteration of the primary
                //       loop saved some input for us to use.  If so, use it
                //       and set the saved input to null.
                //
                if (!String.IsNullOrEmpty(savedText))
                {
                    line = savedText;
                    savedText = null;

                    length = line.Length;

                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: using saved input " +
                            "containing {1} characters...{2}",
                            GlobalState.GetCurrentThreadId(), length,
                            Environment.NewLine), typeof(Interpreter).Name);
                }

                //
                // NOTE: Is the current line of input still null (i.e. there
                //       was no saved input to use)?
                //
                if (line == null)
                {
                    //
                    // NOTE: Check and see if the debugger has command input
                    //       injected via the [debug icommand] sub-command for
                    //       us to use.
                    //
                    line = DebuggerOps.GetCommand(interpreter, false);

                    if (line != null)
                    {
                        length = line.Length;

                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: injecting line " +
                                "of input from debugger containing {1} " +
                                "characters...{2}",
                                GlobalState.GetCurrentThreadId(), length,
                                Environment.NewLine), typeof(Interpreter).Name);
                    }
                }

                //
                // NOTE: Are we processing input injected via saved input text
                //       or the debugger?
                //
                if (!String.IsNullOrEmpty(line))
                {
                    //
                    // NOTE: Prevent this command from being used [again?] as
                    //       the previous interactive input and disable the
                    //       ability to use the "again" command.
                    //
                    previous = false;

                    //
                    // NOTE: Simulate the command having been entered via the
                    //       host.
                    //
                    /* IGNORED */
                    HostOps.WriteLine(interactiveHost, line);
                }

                //
                // NOTE: Has the request for input been canceled by the host
                //       (i.e. either a null line was returned and no input
                //       redirection is in use OR the ReadLine method returned
                //       false).
                //
                bool cancel = false;

                //
                // NOTE: Get a line of input from the host, if necessary (i.e.
                //       we do not already have a command injected via the
                //       debugger, etc).
                //
                if (!String.IsNullOrEmpty(line) ||
                    ReadInteractiveInput(interactiveHost, trace, ref line, ref done))
                {
                    if (line != null) /* more input? */
                    {
                        length = line.Length;

                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: read line of " +
                                "input containing {1} characters.{2}",
                                GlobalState.GetCurrentThreadId(), length,
                                Environment.NewLine), typeof(Interpreter).Name);

                        if (length > 0)
                            text += line + Characters.NewLine;
                        else
                            text += Characters.NewLine;

                        SetInteractiveInput(interpreter, text);
                    }
                    else if (redirected)
                    {
                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: hit end of " +
                                "redirected input, setting exit flag...{1}",
                                GlobalState.GetCurrentThreadId(),
                                Environment.NewLine), typeof(Interpreter).Name);

                        //
                        // NOTE: It looks like console input is being redirected
                        //       and we have run out of it; therefore, bail out
                        //       of the interactive loop now.
                        //
                        exit = true;
                    }
                    else
                    {
                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: read null line " +
                                "of input, setting cancel flag...{1}",
                                GlobalState.GetCurrentThreadId(),
                                Environment.NewLine), typeof(Interpreter).Name);

                        //
                        // NOTE: The ReadLine method returned true; however,
                        //       the actual input line is null and input is not
                        //       being redirected.  Therefore, assume the user
                        //       has canceled the input request.
                        //
                        cancel = true;
                    }
                }
                else if (done)
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: leaving, aborted " +
                            "while reading line of input...{1}",
                            GlobalState.GetCurrentThreadId(),
                            Environment.NewLine), typeof(Interpreter).Name);

                    //
                    // NOTE: The ReadLine method has returned false and the
                    //       done flag is set; therefore, we were aborted by
                    //       another thread while reading input.
                    //
                    break;
                }
                else
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: failed to read line " +
                            "of input, setting cancel flag...{1}",
                            GlobalState.GetCurrentThreadId(),
                            Environment.NewLine), typeof(Interpreter).Name);

                    //
                    // NOTE: The ReadLine method has returned false; therefore,
                    //       assume the input request was canceled by the user.
                    //
                    cancel = true;
                }

                //
                // NOTE: Re-grab the host flags now as they may have changed
                //       during a host read (?) and we need them to determine
                //       if the host is still open.
                //
                hostFlags = HostOps.GetFlags(interactiveHost);

                //
                // NOTE: Re-fetch the interpreter host in case it has been
                //       externally modified or closed.  Also, make sure it is
                //       still open.  If either of these checks fail or return
                //       false, bail out now.
                //
                isOpen = HostOps.IsOpen(
                    interpreter, hostFlags, ref interactiveHost);

                //
                // NOTE: Make sure that we exit if the [exit] command was used.
                //       This is needed because another thread may have set the
                //       exit flag for the interpreter while we were waiting
                //       for input.
                //
                CheckExit(interpreter, ref exit);

                //
                // NOTE: Did the interpreter exit while we were reading (or was
                //       the host invalidated, perhaps by Dispose)?
                //
                if (exit || !isOpen)
                {
                    done = true; /* NOTE: Async exit, we are done. */

                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: leaving, exit = {1}, " +
                            "interactiveHost = {2}, isOpen = {3}{4}",
                            GlobalState.GetCurrentThreadId(), exit,
                            (interactiveHost != null), isOpen,
                            Environment.NewLine), typeof(Interpreter).Name);

                    break;
                }
                //
                // NOTE: Was input canceled while we were reading?
                //
                else if (cancel)
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: leaving, input was " +
                            "canceled...{1}", GlobalState.GetCurrentThreadId(),
                            Environment.NewLine), typeof(Interpreter).Name);

                    /* IGNORED */
                    HostOps.WriteLine(interactiveHost, null);
                    canceled = true; /* skip command processing */

                    break;
                }
                else if (String.IsNullOrEmpty(text) || (text.Trim().Length == 0))
                {
                    if (trace)
                        TraceOps.DebugTrace(String.Format(
                            "{0}: GetInteractiveInput: leaving, null or empty " +
                            "input...{1}", GlobalState.GetCurrentThreadId(),
                            Environment.NewLine), typeof(Interpreter).Name);

                    break;
                }

                //
                // NOTE: Figure out if this looks like an interactive command;
                //       if so, start checking if the input is complete at the
                //       character just after the interactive command prefix;
                //       otherwise, start at index zero.
                //
                startIndex = 0;

                /* IGNORED */
                ShellOps.LooksLikeInteractiveCommand(text, ref startIndex);

                /* IGNORED */
                ShellOps.LooksLikeInteractiveSystemCommand(text, ref startIndex);

                //
                // NOTE: Finally, see if the input is complete enough to return
                //       to the caller -OR- if we are done processing for some
                //       other reason (i.e. user canceled).
                //
            } while (String.IsNullOrEmpty(text) || (text.Trim().Length == 0) ||
                     !Parser.IsComplete(interpreter, null, Parser.StartLine,
                            text, startIndex, Length.Invalid, substitutionFlags,
                            ref notReady, ref parseError) &&
                     !notReady);

            //
            // NOTE: Make sure that we have not exited and that the host is
            //       still valid and open.
            //
            if (!done)
            {
                /* IGNORED */
                HostOps.SetTitle(interactiveHost, null);

                if (notReady)
                {
#if INTERACTIVE_COMMANDS
                    //
                    // NOTE: If this is an interactive debugger command, fake
                    //       the interpreter being "ready" (at least as far as
                    //       input validation goes) because we need to give the
                    //       user the opportunity to reset the script
                    //       cancellation flag, etc.
                    //
                    if (!noInteractive && CheckInteractiveCommand(
                            interpreter, text, null, clientData, true, false))
                    {
                        if (trace)
                            TraceOps.DebugTrace(String.Format(
                                "{0}: GetInteractiveInput: input looks like " +
                                "an interactive command, interpreter readiness " +
                                "faked.{1}", GlobalState.GetCurrentThreadId(),
                                Environment.NewLine), typeof(Interpreter).Name);

                        notReady = false;
                    }
                    else // NOTE: Dangling else (see "if" statement below).
#endif
                    if (!breakOnCancel)
                    {
                        //
                        // NOTE: Show the user why the interpreter is not ready.
                        //
                        /* IGNORED */
                        HostOps.WriteResultLine(interactiveHost,
                            ReturnCode.Error, String.Format(
                                "interpreter not ready: {0}", parseError));
                    }
                }
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Command Support
#if SHELL && INTERACTIVE_COMMANDS
        #region GC Test Thread Support
        internal Thread TestGcThread
        {
            get { return testGcThread; }
            set { testGcThread = value; }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool HasTraceInteractiveCommand(
            InterpreterFlags interpreterFlags
            )
        {
            return FlagOps.HasFlags(interpreterFlags,
                InterpreterFlags.TraceInteractiveCommand, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool CheckInteractiveCommand(
            Interpreter interpreter, /* in */
            string text,             /* in */
            string command,          /* in */
            IClientData clientData,  /* in */
            bool usePrefix,          /* in */
            bool extensions          /* in */
            )
        {
            bool verbose = false; /* NOTE: Mask substitution errors. */
            ArgumentList arguments = null;
            ReturnCode code = ReturnCode.Ok;
            Result result = null;

            return CheckInteractiveCommand(interpreter, text, command, clientData,
                usePrefix, ref verbose, ref arguments, ref code, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool CheckInteractiveCommand(
            Interpreter interpreter,    /* in */
            string text,                /* in */
            string command,             /* in */
            IClientData clientData,     /* in */
            bool usePrefix,             /* in */
            ref bool verbose,           /* in, out */
            ref ArgumentList arguments, /* in, out */
            ref ReturnCode code,        /* out */
            ref Result result           /* out */
            )
        {
            if (!String.IsNullOrEmpty(text))
            {
                ReturnCode localCode = ReturnCode.Ok;
                EngineFlags engineFlags = EngineFlags.None;
                EngineFlags interactiveEngineFlags = EngineFlags.None;
                InterpreterFlags interpreterFlags = InterpreterFlags.None;

                //
                // NOTE: To do anything with substitution, we require a
                //       valid interpreter context.
                //
                if (interpreter != null)
                {
                    //
                    // NOTE: Grab the current engine flags for the
                    //       interpreter.  Also, grab the engine and
                    //       substitution flags specific to interactive
                    //       commands.
                    //
                    engineFlags = interpreter.EngineFlags;

                    interactiveEngineFlags =
                        interpreter.InteractiveEngineFlags;

                    interpreterFlags = interpreter.InterpreterFlags;

                    //
                    // NOTE: Only perform substitution if the text looks
                    //       like it contains an interactive command.
                    //
                    if (ShellOps.LooksLikeInteractiveCommand(text) ||
                        ShellOps.LooksLikeInteractiveSystemCommand(text))
                    {
                        SubstitutionFlags interactiveSubstitutionFlags =
                            interpreter.InteractiveSubstitutionFlags;

                        EventFlags interactiveEventFlags =
                            interpreter.InteractiveEventFlags;

                        ExpressionFlags interactiveExpressionFlags =
                            interpreter.InteractiveExpressionFlags;

                        //
                        // NOTE: Has substitution been disabled by the interpreter
                        //       or via the interactive substitution flags?
                        //
                        if (!Engine.HasNoSubstitute(engineFlags) &&
                            !Engine.HasNoSubstitute(interactiveEngineFlags) &&
                            (interactiveSubstitutionFlags != SubstitutionFlags.None))
                        {
                            Result localResult = null;

                            //
                            // NOTE: Perform the substitions on the text using
                            //       the current flags.
                            //
                            localCode = Engine.SubstituteString(
                                interpreter, text, interactiveEngineFlags,
                                interactiveSubstitutionFlags, interactiveEventFlags,
                                interactiveExpressionFlags, ref localResult);

                            if (localCode == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Success, replace original command text
                                //       with substituted result.
                                //
                                text = localResult;
                            }
                            else if (verbose)
                            {
                                //
                                // NOTE: Only show this error once per actual
                                //       interactive command entered, not per
                                //       call to this method.
                                //
                                verbose = false;

                                //
                                // NOTE: Complain about substitution failure.
                                //
                                DebugOps.Complain(interpreter, localCode, localResult);
                            }
                        }
                    }
                }

                //
                // NOTE: Make sure the above subsitution step succeeded,
                //       if applicable.
                //
                if (localCode == ReturnCode.Ok)
                {
                    //
                    // NOTE: Are we checking for a specific command?
                    //
                    if (!String.IsNullOrEmpty(command))
                    {
                        //
                        // NOTE: Does the text end in a new line character?
                        //       If so, strip it off now.
                        //
                        if (text[text.Length - 1] == Characters.NewLine)
                            text = text.Substring(0, text.Length - 1);

                        //
                        // NOTE: Does the caller want to prefix the command to
                        //       check for with the interactive command prefix?
                        //       This is used so that the caller does not have
                        //       to hard-code the prefix inline in their calls
                        //       to this method.
                        //
                        string normalCommand = null;
                        string systemCommand = null;

                        if (usePrefix)
                        {
                            string prefix = ShellOps.InteractiveCommandPrefix;

                            if (!String.IsNullOrEmpty(prefix) && !command.StartsWith(
                                    prefix, StringOps.SystemNoCaseStringComparisonType))
                            {
                                normalCommand = prefix + command;
                            }

                            prefix = ShellOps.InteractiveSystemCommandPrefix;

                            if (!String.IsNullOrEmpty(prefix) && !command.StartsWith(
                                    prefix, StringOps.SystemNoCaseStringComparisonType))
                            {
                                systemCommand = prefix + command;
                            }
                        }
                        else
                        {
                            //
                            // NOTE: Do not use any interactive command prefix.
                            //
                            normalCommand = command;
                        }

                        //
                        // NOTE: Did the caller supply pre-existing arguments?
                        //       If so, check the command name (i.e. the first
                        //       argument) against the command to check for.
                        //
                        if (arguments != null)
                        {
                            if ((arguments.Count > 0) &&
                                ((String.Compare(arguments[0], normalCommand,
                                    StringOps.SystemNoCaseStringComparisonType) == 0) ||
                                (String.Compare(arguments[0], systemCommand,
                                    StringOps.SystemNoCaseStringComparisonType) == 0)))
                            {
                                //
                                // NOTE: Attempt to handle the interactive command
                                //       as an external interactive command.  Since
                                //       this method was called with the name of a
                                //       pre-existing command to check against, this
                                //       will be an overridden built-in interactive
                                //       command if it exists.
                                //
                                if (!Engine.HasNoInteractiveCommand(engineFlags) &&
                                    !Engine.HasNoInteractiveCommand(interactiveEngineFlags) &&
                                    !ShellOps.LooksLikeInteractiveSystemCommand(arguments[0]))
                                {
                                    bool executed = ExecuteInteractiveCommand(
                                        interpreter, arguments, clientData,
                                        ref code, ref result);

#if HISTORY
                                    //
                                    // NOTE: Add the command to the history even if
                                    //       it was not executed.  If the command was
                                    //       just executed, it has NOT been recorded
                                    //       yet (because ExecuteInteractiveCommand
                                    //       does not handle command history).  If
                                    //       the command was NOT executed, we assume
                                    //       it will be by the caller since the
                                    //       command name does match the one they
                                    //       specified.
                                    //
                                    if ((interpreter != null) && interpreter.History)
                                        interpreter.AddHistory(arguments,
                                            interpreter.Levels, HistoryFlags.Interactive);
#endif

                                    if (!executed && HasTraceInteractiveCommand(interpreterFlags))
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: CheckInteractiveCommand: executed command " +
                                            "with arguments, interpreter = {1}, text = {2}, " +
                                            "command = {3}, clientData = {4}, usePrefix = {5}, " +
                                            "verbose = {6}, arguments = {7}, code = {8}, " +
                                            "result = {9}{10}", GlobalState.GetCurrentThreadId(),
                                            FormatOps.WrapOrNull(interpreter),
                                            FormatOps.WrapOrNull(text),
                                            FormatOps.WrapOrNull(command),
                                            FormatOps.WrapOrNull(clientData), usePrefix,
                                            verbose, FormatOps.WrapOrNull(true, true, arguments),
                                            code, FormatOps.WrapOrNull(true, true, result),
                                            Environment.NewLine), typeof(Interpreter).Name);
                                    }

                                    return !executed;
                                }

#if HISTORY
                                if ((interpreter != null) && interpreter.History)
                                    interpreter.AddHistory(arguments,
                                        interpreter.Levels, HistoryFlags.Interactive);
#endif

                                if (HasTraceInteractiveCommand(interpreterFlags))
                                {
                                    TraceOps.DebugTrace(String.Format(
                                        "{0}: CheckInteractiveCommand: matched command " +
                                        "with arguments, interpreter = {1}, text = {2}, " +
                                        "command = {3}, clientData = {4}, usePrefix = {5}, " +
                                        "verbose = {6}, arguments = {7}, code = {8}, " +
                                        "result = {9}{10}", GlobalState.GetCurrentThreadId(),
                                        FormatOps.WrapOrNull(interpreter),
                                        FormatOps.WrapOrNull(text),
                                        FormatOps.WrapOrNull(command),
                                        FormatOps.WrapOrNull(clientData), usePrefix,
                                        verbose, FormatOps.WrapOrNull(true, true, arguments),
                                        code, FormatOps.WrapOrNull(true, true, result),
                                        Environment.NewLine), typeof(Interpreter).Name);
                                }

                                return true;
                            }
                        }
                        else
                        {
                            //
                            // NOTE: The interactive command, like all other commands,
                            //       must be a well-formed list.  Split it into its
                            //       elements now.
                            //
                            StringList list = null;

                            if (Parser.SplitList(
                                    interpreter, text, 0, Length.Invalid, true,
                                    ref list) == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Save the caller some work by giving them
                                //       all the arguments for the interactive
                                //       command in a list.
                                //
                                arguments = new ArgumentList(list, ArgumentFlags.None);

                                //
                                // NOTE: Compare the first element of the list (i.e.
                                //       the command name) against the command to
                                //       check for.
                                //
                                if ((list.Count > 0) &&
                                    ((String.Compare(list[0], normalCommand,
                                        StringOps.SystemNoCaseStringComparisonType) == 0) ||
                                    (String.Compare(list[0], systemCommand,
                                        StringOps.SystemNoCaseStringComparisonType) == 0)))
                                {
                                    //
                                    // NOTE: Attempt to handle the interactive command
                                    //       as an external interactive command.  Since
                                    //       this method was called with the name of a
                                    //       pre-existing command to check against, this
                                    //       will be an overridden built-in interactive
                                    //       command if it exists.
                                    //
                                    if (!Engine.HasNoInteractiveCommand(engineFlags) &&
                                        !Engine.HasNoInteractiveCommand(interactiveEngineFlags) &&
                                        !ShellOps.LooksLikeInteractiveSystemCommand(list[0]))
                                    {
                                        bool executed = ExecuteInteractiveCommand(
                                            interpreter, arguments, clientData,
                                            ref code, ref result);

#if HISTORY
                                        //
                                        // NOTE: Add the command to the history even if
                                        //       it was not executed.  If the command was
                                        //       just executed, it has NOT been recorded
                                        //       yet (because ExecuteInteractiveCommand
                                        //       does not handle command history).  If
                                        //       the command was NOT executed, we assume
                                        //       it will be by the caller since the
                                        //       command name does match the one they
                                        //       specified.
                                        //
                                        if ((interpreter != null) && interpreter.History)
                                            interpreter.AddHistory(arguments,
                                                interpreter.Levels, HistoryFlags.Interactive);
#endif

                                        if (!executed && HasTraceInteractiveCommand(interpreterFlags))
                                        {
                                            TraceOps.DebugTrace(String.Format(
                                                "{0}: CheckInteractiveCommand: executed command, " +
                                                "interpreter = {1}, text = {2}, command = {3}, " +
                                                "clientData = {4}, usePrefix = {5}, verbose = {6}, " +
                                                "arguments = {7}, code = {8}, result = {9}{10}",
                                                GlobalState.GetCurrentThreadId(),
                                                FormatOps.WrapOrNull(interpreter),
                                                FormatOps.WrapOrNull(text),
                                                FormatOps.WrapOrNull(command),
                                                FormatOps.WrapOrNull(clientData), usePrefix,
                                                verbose, FormatOps.WrapOrNull(true, true, arguments),
                                                code, FormatOps.WrapOrNull(true, true, result),
                                                Environment.NewLine), typeof(Interpreter).Name);
                                        }

                                        return !executed;
                                    }

#if HISTORY
                                    if ((interpreter != null) && interpreter.History)
                                        interpreter.AddHistory(arguments,
                                            interpreter.Levels, HistoryFlags.Interactive);
#endif

                                    if (HasTraceInteractiveCommand(interpreterFlags))
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: CheckInteractiveCommand: matched command, " +
                                            "interpreter = {1}, text = {2}, command = {3}, " +
                                            "clientData = {4}, usePrefix = {5}, verbose = {6}, " +
                                            "arguments = {7}, code = {8}, result = {9}{10}",
                                            GlobalState.GetCurrentThreadId(),
                                            FormatOps.WrapOrNull(interpreter),
                                            FormatOps.WrapOrNull(text),
                                            FormatOps.WrapOrNull(command),
                                            FormatOps.WrapOrNull(clientData), usePrefix,
                                            verbose, FormatOps.WrapOrNull(true, true, arguments),
                                            code, FormatOps.WrapOrNull(true, true, result),
                                            Environment.NewLine), typeof(Interpreter).Name);
                                    }

                                    return true;
                                }
                            }
                        }
                    }
                    else if (usePrefix)
                    {
                        //
                        // NOTE: Just return non-zero if this looks like an
                        //       interactive command.
                        //
                        bool hasPrefix = ShellOps.LooksLikeInteractiveCommand(text) ||
                            ShellOps.LooksLikeInteractiveSystemCommand(text);

                        if (hasPrefix && HasTraceInteractiveCommand(interpreterFlags))
                        {
                            TraceOps.DebugTrace(String.Format(
                                "{0}: CheckInteractiveCommand: matched prefix, " +
                                "interpreter = {1}, text = {2}, command = {3}, " +
                                "clientData = {4}, usePrefix = {5}, verbose = {6}, " +
                                "arguments = {7}, code = {8}, result = {9}{10}",
                                GlobalState.GetCurrentThreadId(),
                                FormatOps.WrapOrNull(interpreter),
                                FormatOps.WrapOrNull(text),
                                FormatOps.WrapOrNull(command),
                                FormatOps.WrapOrNull(clientData), usePrefix,
                                verbose, FormatOps.WrapOrNull(true, true, arguments),
                                code, FormatOps.WrapOrNull(true, true, result),
                                Environment.NewLine), typeof(Interpreter).Name);
                        }

                        return hasPrefix;
                    }
                    else if (!Engine.HasNoInteractiveCommand(engineFlags) &&
                        !Engine.HasNoInteractiveCommand(interactiveEngineFlags) &&
                        ShellOps.LooksLikeInteractiveCommand(text) &&
                        !ShellOps.LooksLikeInteractiveSystemCommand(text))
                    {
                        //
                        // NOTE: Does the text end in a new line character?
                        //       If so, strip it off now.
                        //
                        if (text[text.Length - 1] == Characters.NewLine)
                            text = text.Substring(0, text.Length - 1);

                        //
                        // NOTE: Did the caller supply pre-existing arguments?
                        //       If so, check the command name (i.e. the first
                        //       argument) against the command to check for.
                        //
                        if (arguments != null)
                        {
                            //
                            // NOTE: Attempt to handle the interactive command
                            //       as an external interactive command.  Since
                            //       this method was not called with the name of
                            //       a pre-existing command to check against,
                            //       this will be an interactive extension
                            //       command if it exists.
                            //
                            bool executed = ExecuteInteractiveCommand(
                                interpreter, arguments, clientData,
                                ref code, ref result);

#if HISTORY
                            if (executed && (interpreter != null) && interpreter.History)
                                interpreter.AddHistory(arguments,
                                    interpreter.Levels, HistoryFlags.Interactive);
#endif

                            if (executed && HasTraceInteractiveCommand(interpreterFlags))
                            {
                                TraceOps.DebugTrace(String.Format(
                                    "{0}: CheckInteractiveCommand: executed arguments, " +
                                    "interpreter = {1}, text = {2}, command = {3}, " +
                                    "clientData = {4}, usePrefix = {5}, verbose = {6}, " +
                                    "arguments = {7}, code = {8}, result = {9}{10}",
                                    GlobalState.GetCurrentThreadId(),
                                    FormatOps.WrapOrNull(interpreter),
                                    FormatOps.WrapOrNull(text),
                                    FormatOps.WrapOrNull(command),
                                    FormatOps.WrapOrNull(clientData), usePrefix,
                                    verbose, FormatOps.WrapOrNull(true, true, arguments),
                                    code, FormatOps.WrapOrNull(true, true, result),
                                    Environment.NewLine), typeof(Interpreter).Name);
                            }

                            return executed;
                        }
                        else
                        {
                            //
                            // NOTE: The interactive command, like all other commands,
                            //       must be a well-formed list.  Split it into its
                            //       elements now.
                            //
                            StringList list = null;

                            if (Parser.SplitList(
                                    interpreter, text, 0, Length.Invalid, true,
                                    ref list) == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Save the caller some work by giving them
                                //       all the arguments for the interactive
                                //       command in a list.
                                //
                                arguments = new ArgumentList(list, ArgumentFlags.None);

                                //
                                // NOTE: Attempt to handle the interactive command
                                //       as an external interactive command.  Since
                                //       this method was not called with the name of
                                //       a pre-existing command to check against,
                                //       this will be an interactive extension
                                //       command if it exists.
                                //
                                bool executed = ExecuteInteractiveCommand(
                                    interpreter, arguments, clientData,
                                    ref code, ref result);

#if HISTORY
                                if (executed && (interpreter != null) && interpreter.History)
                                    interpreter.AddHistory(arguments,
                                        interpreter.Levels, HistoryFlags.Interactive);
#endif

                                if (executed && HasTraceInteractiveCommand(interpreterFlags))
                                {
                                    TraceOps.DebugTrace(String.Format(
                                        "{0}: CheckInteractiveCommand: executed text, " +
                                        "interpreter = {1}, text = {2}, command = {3}, " +
                                        "clientData = {4}, usePrefix = {5}, verbose = {6}, " +
                                        "arguments = {7}, code = {8}, result = {9}{10}",
                                        GlobalState.GetCurrentThreadId(),
                                        FormatOps.WrapOrNull(interpreter),
                                        FormatOps.WrapOrNull(text),
                                        FormatOps.WrapOrNull(command),
                                        FormatOps.WrapOrNull(clientData), usePrefix,
                                        verbose, FormatOps.WrapOrNull(true, true, arguments),
                                        code, FormatOps.WrapOrNull(true, true, result),
                                        Environment.NewLine), typeof(Interpreter).Name);
                                }

                                return executed;
                            }
                        }
                    }
                }
            }

            //
            // NOTE: No, it is not the command they are checking for OR
            //       we had some failure during the substitution process
            //       and skipped further checking.
            //
            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool ResolveInteractiveCommand(
            Interpreter interpreter,
            ArgumentList arguments,
            EngineFlags engineFlags,
            ref string name,
            ref IExecute execute
            )
        {
            //
            // NOTE: If the interactive command prefix is invalid (null or
            //       zero length) we cannot resolve or execute any
            //       interactive commands.
            //
            string prefix = ShellOps.InteractiveCommandPrefix;

            if (!String.IsNullOrEmpty(prefix))
            {
                if (interpreter != null)
                {
                    if ((arguments != null) && (arguments.Count > 0))
                    {
                        //
                        // NOTE: Extract the name of the interactive command to
                        //       resolve and execute.  It must start with the
                        //       interactive command prefix (e.g. "#") in order
                        //       to be properly resolved and executed.
                        //
                        name = ScriptOps.MakeCommandName(arguments[0]);

                        if ((name != null) && name.StartsWith(
                                prefix, StringOps.SystemNoCaseStringComparisonType))
                        {
                            //
                            // NOTE: If the name of the interactive command consists
                            //       only of the interactive command prefix itself
                            //       then try for an exact match; otherwise, partial
                            //       non-ambiguous prefix matching will be used.  See
                            //       if this interactive command has been officially
                            //       registered with the interpreter (i.e. it is an
                            //       interactive extension command, which may also
                            //       shadow an existing built-in interactive command).
                            //       Not finding the interactive command is not an
                            //       error; therefore, the error message is ignored.
                            //
                            if (name.Length <= prefix.Length)
                                engineFlags |= EngineFlags.ExactMatch;

                            if (interpreter.GetIExecuteViaResolvers(
                                    engineFlags, name, arguments, LookupFlags.Default,
                                    ref execute) == ReturnCode.Ok)
                            {
                                return true;
                            }
                        }
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool ExecuteInteractiveCommand(
            Interpreter interpreter,
            ArgumentList arguments,
            IClientData clientData,
            ref ReturnCode code,
            ref Result result
            )
        {
            if (interpreter != null)
            {
                EngineFlags engineFlags = interpreter.EngineFlags;

                EngineFlags interactiveEngineFlags =
                    interpreter.InteractiveEngineFlags;

                SubstitutionFlags interactiveSubstitutionFlags =
                    interpreter.InteractiveSubstitutionFlags;

                EventFlags interactiveEventFlags =
                    interpreter.InteractiveEventFlags;

                ExpressionFlags interactiveExpressionFlags =
                    interpreter.InteractiveExpressionFlags;

                if (!Engine.HasNoInteractiveCommand(engineFlags) &&
                    !Engine.HasNoInteractiveCommand(interactiveEngineFlags))
                {
                    string name = null;
                    IExecute execute = null;

                    if (ResolveInteractiveCommand(interpreter, arguments,
                            interpreter.GetResolveEngineFlags(
                            interactiveEngineFlags, false), ref name,
                            ref execute))
                    {
                        ICallFrame frame = interpreter.NewTrackingCallFrame(
                            StringList.MakeList("interactive", name),
                            CallFrameFlags.Interactive);

                        interpreter.PushAutomaticCallFrame(frame);

                        //
                        // NOTE: Save the current engine flags and then enable
                        //       the external execution flags.
                        //
                        EngineFlags savedEngineFlags = Engine.AddStackCheckFlags(
                            ref interactiveEngineFlags);

                        //
                        // NOTE: Execute the command using the interactive engine
                        //       and substitution flags with the interactive
                        //       engine flags having been modified to include the
                        //       flags necessary for external command execution
                        //       (i.e. command execution outside of the engine).
                        //
                        code = Engine.Execute(
                            name, execute, interpreter, clientData, arguments,
                            interactiveEngineFlags, interactiveSubstitutionFlags,
                            interactiveEventFlags, interactiveExpressionFlags,
                            ref result);

                        //
                        // NOTE: Restore the saved engine flags, masking off the
                        //       external execution flags as necessary.
                        //
                        Engine.RemoveStackCheckFlags(savedEngineFlags,
                            ref interactiveEngineFlags);

                        //
                        // NOTE: Pop the original call frame that we pushed above
                        //       and any intervening scope call frames that may be
                        //       leftover (i.e. they were not explicitly closed).
                        //
                        /* IGNORED */
                        interpreter.PopCallFrame(CallFrameFlags.Scope, true);

                        //
                        // NOTE: Yes, we just executed an interactive extension
                        //       command; therefore, prevent the default handling
                        //       of the built-in interactive command, if any.
                        //
                        return true;
                    }
                }
            }

            //
            // NOTE: We did nothing.  Either the interactive (extension?)
            //       command was not found OR we could not search for it
            //       because the caller provided us invalid arguments.
            //       Therefore, continue default processing.  This will
            //       involve executing the built-in behavior for the
            //       interactive command or doing nothing if it is not
            //       found by the built-in interactive command processor.
            //
            return false;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Script Cancellation Support
#if CONSOLE
        private static void CancelAnyEvaluate(
            Interpreter interpreter,
            bool unwind,
            bool strict
            )
        {
            if (interpreter == null)
                return;

            try
            {
                ReturnCode code;
                Result error = null;

                code = interpreter.CancelAnyEvaluate(
                    unwind, strict, demandCancelResultFormat,
                    ref error);

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(interpreter, code, error);
            }
            catch (InterpreterDisposedException)
            {
                //
                // NOTE: The interpreter is disposed, do nothing.
                //
                TraceOps.DebugTrace(String.Format(
                    "{0}: CancelAnyEvaluate: interpreter = {1}, caught " +
                    "InterpreterDisposedException{2}",
                    GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    (interpreter != null) ? (object)interpreter.IdNoThrow :
                    null), Environment.NewLine), typeof(Interpreter).Name);
            }
            finally
            {
                //
                // BUGFIX: Cleanup any stray contexts that were created
                //         on this [random thread-pool] thread?
                //
                /* IGNORED */
                interpreter.MaybeDisposeThread();
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void CancelAnyEvaluate(
            InterpreterDictionary interpreters,
            bool unwind,
            bool strict
            )
        {
            if (interpreters == null)
                return;

            foreach (KeyValuePair<string, Interpreter> pair in interpreters)
            {
                Interpreter interpreter = pair.Value;

                if (interpreter == null)
                    continue;

                CancelAnyEvaluate(interpreter, unwind, strict);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static void ConsoleCancelEventHandler(
            object sender,
            ConsoleCancelEventArgs e
            ) /* THREAD-SAFE */
        {
            //
            // NOTE: Cancel all currently running scripts in all threads.  Only
            //       handle the first event generated by the Ctrl-C.
            //
            if ((e == null) || !e.Cancel)
            {
                //
                // NOTE: Obtain the master list of interpreters.  This requires
                //       holding the master lock; therefore, do it first.
                //
                InterpreterDictionary interpreters = GlobalState.GetInterpreters();

                if (interpreters != null)
                {
                    foreach (KeyValuePair<string, Interpreter> pair in interpreters)
                    {
                        Interpreter interpreter = pair.Value;

                        if (interpreter == null)
                            continue;

                        CancelAnyEvaluate(interpreter, true, false);

                        CancelAnyEvaluate(interpreter.CopySlaveInterpreters(),
                            true, false);
                    }
                }

                //
                // NOTE: Finally, prevent default event handling (which would
                //       terminate the process); however, we cannot prevent
                //       Ctrl-Break from terminating the process (only Ctrl-C).
                //
                if ((e != null) && (e.SpecialKey == ConsoleSpecialKey.ControlC))
                    e.Cancel = true;
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Timeout Thread Support
        private Thread TimeoutThread
        {
            get { return timeoutThread; }
            set { timeoutThread = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static bool HasTimeoutThread(
            Interpreter interpreter
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    return (interpreter.TimeoutThread != null);
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void TimeoutThreadStart(
            object obj
            ) /* THREAD-SAFE */
        {
            try
            {
                Interpreter interpreter = obj as Interpreter;

                if (interpreter != null)
                {
                    int timeout;
                    IInteractiveHost interactiveHost;

                    //
                    // HACK: Workaround for Mono disposal race condition.
                    //
                    lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                    {
                        timeout = interpreter.PrivateTimeout;
                        interactiveHost = interpreter.PrivateHost;
                    }

                    if (timeout != _Timeout.Infinite) // never timeout?
                    {
                        //
                        // NOTE: Keep going while the interactive host is actively
                        //       reading input from the user.  This allows commands
                        //       that enter the interactive loop recursively (like
                        //       [debug break]) to be used with the script timeout
                        //       feature.  This loop will terminate when the user
                        //       attempts to cancel the running script -OR- allows
                        //       it to continue running.
                        //
                        while (true)
                        {
                            ReturnCode code;
                            Exception exception = null;
                            Result error = null;

                            //
                            // NOTE: Give the script some time to execute.  If this
                            //       thread is interrupted during the wait, do not
                            //       attempt to do anything else.
                            //
                            code = HostOps.Sleep(timeout, ref exception, ref error);

                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: If the interactive host is actively reading
                                //       from the user there is probably no need to
                                //       cancel the running script (if there actually
                                //       is a running script).
                                //
                                if (HostOps.GetReadLevels(interactiveHost) > 0)
                                    continue;

                                //
                                // NOTE: Prompt the interactive user and check if they
                                //       would like to cancel the running script.
                                //
                                if (WindowOps.YesOrNo(
                                        String.Format(timeoutCancelPromptFormat, timeout),
                                        GlobalState.GetPackageName(), true))
                                {
                                    code = interpreter.CancelAnyEvaluate(true, false,
                                        String.Format(timeoutCancelResultFormat, timeout),
                                        ref error);

                                    if (code != ReturnCode.Ok)
                                        DebugOps.Complain(interpreter, code, error);
                                }
                            }
                            else if (!(exception is ThreadInterruptedException))
                            {
                                DebugOps.Complain(interpreter, code, error);
                            }

                            //
                            // NOTE: Either the script in progress (if any) completed
                            //       successfully -OR- we managed to cancel it.
                            //
                            break;
                        }
                    }
                }
            }
            catch (ThreadInterruptedException)
            {
                // do nothing.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode StartTimeoutThread(
            Interpreter interpreter,
            bool force,
            bool strict,
            ref Result result
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    //
                    // NOTE: If there is not timeout we do not bother starting the
                    //       dedicated script cancellation thread unless we are
                    //       forced to by the caller.
                    //
                    if (force ||
                        (interpreter.Timeout != _Timeout.Infinite))
                    {
                        Thread thread = interpreter.TimeoutThread;

                        if (thread == null)
                        {
                            try
                            {
                                thread = Engine.CreateThread(
                                    interpreter, TimeoutThreadStart, 0, false,
                                    false);

                                if (thread != null)
                                {
                                    thread.Name = String.Format(
                                        "timeoutThread: {0}", interpreter);

                                    thread.Start(interpreter);

                                    interpreter.TimeoutThread = thread;
                                    result = "created and started cancel thread";

                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "could not create cancel thread";
                                }
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "failed to start cancel thread, caught exception \"{0}\"",
                                    e);
                            }
                        }
                        else
                        {
                            result = "cancel thread already started";

                            //
                            // NOTE: This is not really always an error due to nested
                            //       interactive loops.
                            //
                            if (!strict)
                                return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        //
                        // NOTE: Skipped, we were not forced to start the cancel thread and
                        //       there is no timeout set.
                        //
                        result = "skipped checking cancel thread";

                        return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode InterruptTimeoutThread(
            Interpreter interpreter,
            bool strict,
            ref Result result
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    Thread thread = interpreter.TimeoutThread;

                    if (thread != null)
                    {
                        try
                        {
                            if (thread.IsAlive)
                            {
                                thread.Interrupt(); /* throw */

                                if (!thread.Join(ThreadOps.DefaultJoinTimeout))
                                    /* BUGBUG: Leaks? */
                                    thread.Abort(); /* throw */

                                interpreter.TimeoutThread = null;
                                result = "interrupted cancel thread";

                                return ReturnCode.Ok;
                            }
                            else
                            {
                                interpreter.TimeoutThread = null; /* NOTE: Dead. */
                                result = "cancel thread is not alive";

                                //
                                // NOTE: This is not really always an error due
                                //        to subtle timing issues.
                                //
                                if (!strict)
                                    return ReturnCode.Ok;
                            }
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "failed to interrupt cancel thread, " +
                                "caught exception \"{0}\"",
                                e);
                        }
                    }
                    else
                    {
                        result = "cancel thread already stopped";

                        //
                        // NOTE: This is not really always an error due to
                        //       nested interactive loops.
                        //
                        if (!strict)
                            return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Finally Timeout Thread Support
        private Thread FinallyTimeoutThread
        {
            get { return finallyTimeoutThread; }
            set { finallyTimeoutThread = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static bool HasFinallyTimeoutThread(
            Interpreter interpreter
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    return (interpreter.FinallyTimeoutThread != null);
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void FinallyTimeoutThreadStart(
            object obj
            ) /* THREAD-SAFE */
        {
            try
            {
                Interpreter interpreter = obj as Interpreter;

                if (interpreter != null)
                {
                    int timeout;

                    //
                    // HACK: Workaround for Mono disposal race condition.
                    //
                    lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                    {
                        timeout = interpreter.PrivateFinallyTimeout;
                    }

                    if (timeout != _Timeout.Infinite) // never timeout?
                    {
                        //
                        // NOTE: Keep going while the interactive host is actively
                        //       reading input from the user.  This allows commands
                        //       that enter the interactive loop recursively (like
                        //       [debug break]) to be used with the script timeout
                        //       feature.  This loop will terminate when the user
                        //       attempts to cancel the running script -OR- allows
                        //       it to continue running.
                        //
                        while (true)
                        {
                            ReturnCode code;
                            Exception exception = null;
                            Result error = null;

                            //
                            // NOTE: Give the script some time to execute.  If this
                            //       thread is interrupted during the wait, do not
                            //       attempt to do anything else.
                            //
                            code = HostOps.Sleep(timeout, ref exception, ref error);

                            if (code == ReturnCode.Ok)
                            {
                                code = interpreter.CancelAnyEvaluate(true, false,
                                    String.Format(finallyTimeoutCancelResultFormat,
                                    timeout), ref error);

                                if (code != ReturnCode.Ok)
                                    DebugOps.Complain(interpreter, code, error);
                            }
                            else if (!(exception is ThreadInterruptedException))
                            {
                                DebugOps.Complain(interpreter, code, error);
                            }

                            //
                            // NOTE: Either the script in progress (if any) completed
                            //       successfully -OR- we managed to cancel it.
                            //
                            break;
                        }
                    }
                }
            }
            catch (ThreadInterruptedException)
            {
                // do nothing.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode StartFinallyTimeoutThread(
            Interpreter interpreter,
            bool force,
            bool strict,
            ref Result result
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    //
                    // NOTE: If there is not timeout we do not bother starting the
                    //       dedicated finally timeout thread unless we are forced
                    //       to by the caller.
                    //
                    if (force ||
                        (interpreter.FinallyTimeout != _Timeout.Infinite))
                    {
                        Thread thread = interpreter.FinallyTimeoutThread;

                        if (thread == null)
                        {
                            try
                            {
                                thread = Engine.CreateThread(
                                    interpreter, FinallyTimeoutThreadStart, 0, false,
                                    false);

                                if (thread != null)
                                {
                                    thread.Name = String.Format(
                                        "finallyTimeoutThread: {0}", interpreter);

                                    thread.Start(interpreter);

                                    interpreter.FinallyTimeoutThread = thread;
                                    result = "created and started finally timeout thread";

                                    return ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "could not create finally timeout thread";
                                }
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "failed to start finally timeout thread, caught exception \"{0}\"",
                                    e);
                            }
                        }
                        else
                        {
                            result = "finally timeout thread already started";

                            //
                            // NOTE: This is not really always an error due to nested
                            //       interactive loops.
                            //
                            if (!strict)
                                return ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        //
                        // NOTE: Skipped, we were not forced to start the cancel thread and
                        //       there is no timeout set.
                        //
                        result = "skipped checking finally timeout thread";

                        return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode InterruptFinallyTimeoutThread(
            Interpreter interpreter,
            bool strict,
            ref Result result
            )
        {
            if (interpreter != null)
            {
                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                {
                    Thread thread = interpreter.FinallyTimeoutThread;

                    if (thread != null)
                    {
                        try
                        {
                            if (thread.IsAlive)
                            {
                                thread.Interrupt(); /* throw */

                                if (!thread.Join(ThreadOps.DefaultJoinTimeout))
                                    /* BUGBUG: Leaks? */
                                    thread.Abort(); /* throw */

                                interpreter.FinallyTimeoutThread = null;
                                result = "interrupted finally timeout thread";

                                return ReturnCode.Ok;
                            }
                            else
                            {
                                interpreter.FinallyTimeoutThread = null; /* NOTE: Dead. */
                                result = "finally timeout thread is not alive";

                                //
                                // NOTE: This is not really always an error due
                                //        to subtle timing issues.
                                //
                                if (!strict)
                                    return ReturnCode.Ok;
                            }
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "failed to interrupt finally timeout thread, " +
                                "caught exception \"{0}\"",
                                e);
                        }
                    }
                    else
                    {
                        result = "finally timeout thread already stopped";

                        //
                        // NOTE: This is not really always an error due to
                        //       nested evaluations, etc.
                        //
                        if (!strict)
                            return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Loop
#if SHELL
        private static void InteractiveLoopThreadStart(
            object obj
            )
        {
            try
            {
                IAnyPair<Interpreter, IEnumerable<string>> pair =
                    obj as IAnyPair<Interpreter, IEnumerable<string>>;

                if (pair == null)
                {
                    DebugOps.Complain(ReturnCode.Error,
                        "thread argument is not a pair");

                    return;
                }

                TraceOps.DebugTrace(String.Format(
                    "{0}: InteractiveLoopThreadStart: entered, " +
                    "interpreter = {1}, args = {2}{3}",
                    GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    pair.X), FormatOps.WrapOrNull(true, true, pair.Y),
                    Environment.NewLine), typeof(Interpreter).Name);

                ReturnCode code;
                Result result = null;

                code = InteractiveLoop(pair.X, pair.Y, ref result);

                TraceOps.DebugTrace(String.Format(
                    "{0}: InteractiveLoopThreadStart: exited, " +
                    "interpreter = {1}, args = {2}, code = {3}, " +
                    "result = {4}{5}", GlobalState.GetCurrentThreadId(),
                    FormatOps.WrapOrNull(pair.X), FormatOps.WrapOrNull(
                    true, true, pair.Y), code, FormatOps.WrapOrNull(
                    true, true, result), Environment.NewLine),
                    typeof(Interpreter).Name);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Thread InteractiveLoopThread(
            Interpreter interpreter,
            IEnumerable<string> args,
            bool start,
            ref Result error
            ) /* ENTRY-POINT, THREAD-SAFE, RE-ENTRANT */
        {
            try
            {
                Thread interactiveLoopThread = Engine.CreateThread(
                    InteractiveLoopThreadStart, 0, true, false);

                if (interactiveLoopThread != null)
                {
                    interactiveLoopThread.Name = String.Format(
                        "interactiveLoopThread: {0}", interpreter);

                    if (start)
                    {
                        IAnyPair<Interpreter, IEnumerable<string>> pair =
                            new AnyPair<Interpreter, IEnumerable<string>>(
                                interpreter, args);

                        interactiveLoopThread.Start(pair); /* throw */
                    }

                    return interactiveLoopThread;
                }
                else
                {
                    error = "failed to create engine thread";
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);

                error = e;
            }

            return null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode InteractiveLoop(
            Interpreter interpreter,
            IEnumerable<string> args,
            ref Result result
            )
        {
            bool exit = false;

            return InteractiveLoop(interpreter, args, ref exit, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode InteractiveLoop(
            Interpreter interpreter,
            IEnumerable<string> args,
            ref bool exit,
            ref Result result
            )
        {
            return InteractiveLoop(
                interpreter, false, args, ReturnCode.Ok, BreakpointType.None,
                null, null, null, EngineFlags.None, SubstitutionFlags.Default,
                EventFlags.Default, ExpressionFlags.Default, HeaderFlags.None,
                null, null, ref exit, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode InteractiveLoop(
            Interpreter interpreter,
            bool debug,
            IEnumerable<string> args,
            ReturnCode code,
            BreakpointType breakpointType,
            string breakpointName,
            IToken token,
            ITraceInfo traceInfo,
            EngineFlags engineFlags,
            SubstitutionFlags substitutionFlags,
            EventFlags eventFlags,
            ExpressionFlags expressionFlags,
            HeaderFlags headerFlags,
            IClientData clientData,
            ArgumentList arguments,
            ref bool exit,
            ref Result result
            )
        {
            TraceOps.DebugTrace(String.Format(
                "{0}: InteractiveLoop: entered, interpreter = {1}, debug = {2}, " +
                "args = {3}, code = {4}, breakpointType = {5}, breakpointName = {6}, " +
                "token = {7}, traceInfo = {8}, engineFlags = {9}, substitutionFlags = {10}, " +
                "eventFlags = {11}, expressionFlags = {12}, headerFlags = {13}, " +
                "clientData = {14}, arguments = {15}, exit = {16}, result = {17}{18}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    (interpreter != null) ? (object)interpreter.IdNoThrow : null), debug,
                FormatOps.WrapArgumentsOrNull(true, true, args), code, breakpointType,
                FormatOps.WrapOrNull(breakpointName), (token != null), (traceInfo != null),
                FormatOps.WrapOrNull(engineFlags), FormatOps.WrapOrNull(substitutionFlags),
                FormatOps.WrapOrNull(eventFlags), FormatOps.WrapOrNull(expressionFlags),
                FormatOps.WrapOrNull(headerFlags), FormatOps.WrapOrNull(clientData),
                FormatOps.WrapOrNull(true, true, arguments), exit, FormatOps.WrapOrNull(
                true, true, result), Environment.NewLine), typeof(Interpreter).Name);

            if (interpreter != null)
            {
                //
                // NOTE: Make sure that we exit if the [exit] command was used.
                //
                CheckExit(interpreter, ref exit);

                if (!exit)
                {
                    //
                    // NOTE: Grab the interactive host from the interpreter.  The
                    //       methods of this interface represent the absolute bare
                    //       minimum functionality we need for the interactive loop
                    //       to function correctly.
                    //
                    IInteractiveHost interactiveHost = interpreter.Host;

                    //
                    // NOTE: Check for the host after checking whether we are exiting
                    //       because the host may have already been torn down and that
                    //       is not an error.
                    //
                    if (interactiveHost != null)
                    {
                        //
                        // NOTE: Make sure we have checked for native stack space at
                        //       least once at this point.
                        //
#if NATIVE && WINDOWS
                        if (RuntimeOps.CheckForStackSpace(interpreter,
                                Engine.GetExtraStackSpace()) == ReturnCode.Ok)
#endif
                        {
                            #region Push Active Interpreter
                            //
                            // NOTE: Push this interpreter onto the activation stack
                            //       because it is considered "active" while the
                            //       interactive loop is using it.
                            //
                            GlobalState.PushActiveInterpreter(interpreter);
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Save / Push Interactive Loop Level
                            //
                            // NOTE: Save the current interactive thread property so
                            //       that we can restore it later, if necessary.
                            //
                            Thread savedInteractiveThread = null;

                            //
                            // NOTE: The thread for the interactive user is this one.
                            //       This can only be done in the primary application
                            //       domain for the interpreter.
                            //
                            if (AppDomainOps.IsSame(interpreter))
                            {
                                savedInteractiveThread = interpreter.InteractiveThread;
                                interpreter.InteractiveThread = Thread.CurrentThread;
                            }

                            //
                            // NOTE: Save the current interactive property so that we can
                            //       restore it later, if necessary.
                            //
                            bool savedInteractive = interpreter.Interactive;

                            //
                            // NOTE: This is an interactive loop and requires user input;
                            //       therefore, we are in interactive mode.
                            //
                            interpreter.Interactive = true;

                            //
                            // NOTE: We are entering an[other] instance of the interactive
                            //       loop; therefore, increase our tracking count.
                            //
                            interpreter.InteractiveLoops++; /* THREAD-SAFE */
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Local Halt State Variables
                            //
                            // NOTE: These variables are used when halting the interpreter (i.e.
                            //       cancel any scripts in progress and break out of any nested
                            //       interactive loops).
                            //
                            ReturnCode haltCode;
                            bool haltReset = false;
                            Result haltResult = null;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region [Maybe] Initialize Interactive (Shell) Script Library
                            //
                            // NOTE: Have we initialized the interactive shell yet?  If not,
                            //       do it now.
                            //
                            if (interpreter.PrivateInitialized && /* NOTE: We must be initialized. */
                                (interpreter.InteractiveLoops == 1)) /* NOTE: Outermost loop only. */
                            {
                                #region Enter Debugger Active Level
#if DEBUGGER
                                //
                                // NOTE: Get the active debugger from the interpreter itself.
                                //
                                IDebugger debugger = interpreter.Debugger;

                                //
                                // NOTE: If we are debugging and the debugger is available for
                                //       this interpreter, increase one level of nested debugger
                                //       evaluations.  This is critical because it is used by the
                                //       engine to determine if breakpoints should occur in the
                                //       evaluated script and if the halt flag for the interpreter
                                //       should be reset after the script is evaluated (below).
                                //
                                if (debug && (debugger != null) && !debugger.Disposed)
                                    debugger.SetActive(true);
#endif
                                #endregion

                                ///////////////////////////////////////////////////////////////////////

                                try
                                {
                                    //
                                    // NOTE: Evaluate the user-specific shell startup file and the
                                    //       interactive shell startup file, if any.
                                    //
                                    ReturnCode shellCode;
                                    Result shellResult = null;

                                    shellCode = interpreter.PrivateInitializeShell(
                                        false, debug, ref shellResult);

                                    if (shellCode != ReturnCode.Ok)
                                    {
                                        DebugOps.Complain(interpreter, shellCode,
                                            String.Format("shell: {0}", shellResult));
                                    }

                                    //
                                    // BUGFIX: If the shell initialization script somehow set the
                                    //         exit flag for the interpreter, bail out before
                                    //         entering the actual interactive loop and without
                                    //         displaying any debugging related information.
                                    //
                                    CheckExit(interpreter, ref exit);

                                    //
                                    // NOTE: Did the shell initialization script somehow mark the
                                    //       interpreter as exited?
                                    //
                                    if (exit)
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: InteractiveLoop: leaving, shell " +
                                            "initialization script set the exit flag...{1}",
                                            GlobalState.GetCurrentThreadId(),
                                            Environment.NewLine), typeof(Interpreter).Name);

                                        goto skipLoop;
                                    }
                                }
                                finally
                                {
                                    #region Exit Debugger Active Level
#if DEBUGGER
                                    //
                                    // NOTE: Back out one level of nested debugger evaluations.
                                    //
                                    debugger = interpreter.Debugger; /* NOTE: Refresh. */

                                    if (debug && (debugger != null) && !debugger.Disposed)
                                        debugger.SetActive(false);
#endif
                                    #endregion
                                }
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Write Interactive Header
                            //
                            // BUGFIX: Skip writing anything if the interpreter host has been
                            //         disposed.
                            //
                            if (debug && (interactiveHost != null) &&
                                !HostOps.IsDisposed(interactiveHost))
                            {
                                //
                                // NOTE: Attempt to cast the interactive host to an informational
                                //       host.  If this fails, we simply ignore it because it is
                                //       not strictly required for proper functioning of the
                                //       interactive loop.
                                //
                                IInformationHost informationHost =
                                    interactiveHost as IInformationHost;

                                bool proxy = AppDomainOps.IsTransparentProxy(informationHost);

                                if (informationHost != null)
                                    informationHost.WriteHeader(
                                        interpreter, code, breakpointType, breakpointName,
                                        !proxy ? token : null, !proxy ? traceInfo : null,
                                        engineFlags, substitutionFlags, eventFlags, expressionFlags,
                                        DebuggerOps.GetHeaderFlags(headerFlags, debug, true,
                                            false, debug),
                                        clientData, arguments, result);
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Determine Local Header Flags
                            //
                            // NOTE: Get the header display flags for the interpreter and add
                            //       the necessary flags for our debugging mode.
                            //
                            HeaderFlags localHeaderFlags = DebuggerOps.GetHeaderFlags(
                                interpreter.HeaderFlags, debug, false, false, debug);
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Save / Push Engine Flags
                            //
                            // NOTE: Initialize the saved engine flags (to nothing).
                            //
                            EngineFlags savedEngineFlags = EngineFlags.None;

                            //
                            // NOTE: Are we being called by the debugger?
                            //
                            if (debug)
                            {
                                //
                                // BUGFIX: Save the current engine flags for this interpreter to
                                //         be restored as this [potentially nested] interactive
                                //         loop is exiting.
                                //
                                savedEngineFlags = interpreter.ContextEngineFlags;

                                //
                                // NOTE: For functions called from inside the interactive loop
                                //       that do not, directly or indirectly, receive engine
                                //       flags as a formal argument, we still need to be sure
                                //       that the engine flags received from our caller are in
                                //       effect for the entire duration of this interactive
                                //       loop; therefore, we combine the engine flags received
                                //       from our caller into the engine flags for the
                                //       interpreter.
                                //
                                interpreter.ContextEngineFlags |= engineFlags;
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Local Flag Variables
                            //
                            // NOTE: Get the local engine, substitution, and event flags for
                            //       this interpreter.
                            //
                            EngineFlags localEngineFlags = interpreter.EngineFlags;
                            SubstitutionFlags localSubstitutionFlags = interpreter.SubstitutionFlags;
                            EventFlags localEventFlags = interpreter.EngineEventFlags;
                            ExpressionFlags localExpressionFlags = interpreter.ExpressionFlags;

                            ///////////////////////////////////////////////////////////////////////////

                            //
                            // NOTE: Add the engine flags for our debugging mode to our local
                            //       engine flags, if necessary.
                            //
                            localEngineFlags |= DebuggerOps.GetEngineFlags(debug);
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Force Cancel / Halt Flags
                            //
                            // NOTE: The "forceCancel" and "forceHalt" variables are used as
                            //       the "force" argument to the ResetCancel and ResetHalt
                            //       methods, respectively.  These methods are used at the top
                            //       of each loop iteration to reset the interpreter flags as
                            //       necessary prior to doing anything with the interpreter.
                            //
                            bool forceCancel = false;
                            bool forceHalt = false;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Local Return Code / Result / Error Line
                            //
                            // NOTE: These result variables need to be preserved between loop
                            //       iterations for possible modification of the REAL result(s)
                            //       (primarily in debug mode).
                            //
                            ReturnCode localCode = ReturnCode.Ok;
                            Result localResult = null;
                            int localErrorLine = 0;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Tcl Shell Emulation Mode Variables
                            //
                            // NOTE: This variable controls which script engine is used to
                            //       evaluate all interactively entered scripts (i.e. using
                            //       Eagle or using "tclsh emulation mode").  By default (zero),
                            //       all interactively entered scripts will be evaluated using
                            //       the interactive Eagle interpreter.  When this variable is
                            //       non-zero, all interactively entered scripts will be
                            //       evaluated using the master Tcl interpreter, if available.
                            //
                            bool tclsh = false;

                            ///////////////////////////////////////////////////////////////////////////

#if INTERACTIVE_COMMANDS || (NATIVE && TCL)
                            //
                            // NOTE: This variable will contain the native Tcl interpreter name
                            //       to use when evaluating scripts in "tclsh emulation mode".
                            //
                            string tclInterpName = null;
#endif

                            ///////////////////////////////////////////////////////////////////////////

                            //
                            // NOTE: This variable will contain the saved setting for the current
                            //       "tclsh emulation mode" setting if it needs to be restored by
                            //       the current iteration of the primary loop -OR- null if the
                            //       "tclsh emulation mode" setting has not [yet] been saved or
                            //       has already been restored.
                            //
                            bool? savedTclsh = null;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region GC Test Thread Variables
#if INTERACTIVE_COMMANDS
                            //
                            // NOTE: Does the GC test thread need to be shutdown upon exiting
                            //       THIS interactive loop?
                            //
                            bool startedGcThread = false;
#endif
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Interactive Input Variables
                            //
                            // NOTE: This variable will contain interactive input saved from a
                            //       previous iteration of the primary loop (below) or null if
                            //       no such input has been saved since it was last reset.
                            //
                            string savedText = null;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Interactive Loop Variables
                            //
                            // NOTE: This variable controls the primary loop (below).  When it
                            //       is true, the loop will terminate (i.e. there is no more
                            //       input available, the user has exited, etc).
                            //
                            bool done = false;
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            //
                            // NOTE: This is the start of the interactive input processing loop.
                            //       Exiting this loop will cause one level of the interactive
                            //       loop to exit.  If the interactive loop being exited is the
                            //       final one remaining, the Eagle Shell process will exit.
                            //       However, other applications may continue running if they no
                            //       longer require an interactive loop or intend on restarting
                            //       it at some point.
                            //
                            while (!done)
                            {
                                #region Interactive Input / Result Processing Variables
                                //
                                // NOTE: Reset the interactive processing variables used by input
                                //       loop(s) and the output handling code.
                                //
                                bool previous = true; /* NOTE: Update previous interactive input? */
                                bool show = true; /* NOTE: Show local result by default. */
                                #endregion

                                ///////////////////////////////////////////////////////////////////////

                                #region Interactive Loop Input Processing
                                //
                                // NOTE: Re-grab the current interpreter flags.
                                //
                                InterpreterFlags interpreterFlags =
                                    interpreter.PrivateInterpreterFlags;

                                //
                                // NOTE: Disable all interactive commands?
                                //
                                bool noInteractive = FlagOps.HasFlags(
                                    interpreterFlags, InterpreterFlags.NoInteractiveCommand, true);

                                //
                                // NOTE: Enable traces in the interactive input processing?
                                //
                                bool trace = FlagOps.HasFlags(
                                    interpreterFlags, InterpreterFlags.TraceInput, true);

                                ///////////////////////////////////////////////////////////////////////

                                //
                                // NOTE: Declare the variables used for processing all interactive
                                //       input, redirected or otherwise (i.e. from the actual
                                //       interactive user).
                                //
                                bool canceled;
                                string text;
                                bool notReady;
                                Result parseError;

                                //
                                // NOTE: Invoke the method directly responsible for getting a complete
                                //       [logical] line of interactive input.  This method may return
                                //       input injected via the debugger interface -OR- input, that may
                                //       have been modified, from a previous iteration of this loop
                                //       (e.g. from the interactive "#eval" command).
                                //
                                GetInteractiveInput(
                                    interpreter, noInteractive, trace, debug, false,
                                    localSubstitutionFlags, clientData, forceCancel, forceHalt,
                                    ref interactiveHost, ref savedText, ref exit, ref done,
                                    ref previous, out canceled, out text, out notReady,
                                    out parseError);
                                #endregion

                                ///////////////////////////////////////////////////////////////////////

                                #region Interactive Host Begin-Processing Hook Callback
                                //
                                // NOTE: Give the interactive host the opportunity to preview
                                //       and possibly respond to the entered command.
                                //
                                if (!done && (interactiveHost != null) &&
                                    !HostOps.IsDisposed(interactiveHost))
                                {
                                    ReturnCode beginCode;
                                    Result beginError = null;

                                    beginCode = interactiveHost.BeginProcessing(
                                        interpreter.InteractiveLoops, ref text, ref beginError);

                                    if (beginCode != ReturnCode.Ok)
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: InteractiveLoop: host processing error, " +
                                            "beginCode = {1}, beginError = {2}{3}",
                                            GlobalState.GetCurrentThreadId(), beginCode,
                                            FormatOps.WrapOrNull(true, true, beginError),
                                            Environment.NewLine), typeof(Interpreter).Name);

                                        //
                                        // NOTE: Processing has been halted by the interactive
                                        //       host, bail out of the interactive loop now.
                                        //
                                        done = true;
                                    }
                                }
                                #endregion

                                ///////////////////////////////////////////////////////////////////////
                                //
                                // NOTE: Now, evaluate the completed script entered by the user
                                //       (if they have not canceled).
                                //
                                if (!done && !canceled && !notReady)
                                {
                                    if (!String.IsNullOrEmpty(text) && (text.Trim().Length > 0))
                                    {
                                        #region Interactive Command Argument Processing
#if INTERACTIVE_COMMANDS
                                        //
                                        // NOTE: Reset the interactive command processing variables
                                        //       used by the CheckInteractiveCommand method.
                                        //
                                        bool debugVerbose = true;
                                        ArgumentList debugArguments = null;
#endif
                                        #endregion

                                        ///////////////////////////////////////////////////////////////

                                        #region Enter Debugger Active Level
#if DEBUGGER
                                        //
                                        // NOTE: Refresh the active debugger from the interpreter itself.
                                        //
                                        IDebugger debugger = interpreter.Debugger;

                                        //
                                        // NOTE: If we are debugging and the debugger is available for
                                        //       this interpreter, increase one level of nested debugger
                                        //       evaluations.  This is critical because it is used by the
                                        //       engine to determine if breakpoints should occur in the
                                        //       evaluated script and if the halt flag for the interpreter
                                        //       should be reset after the script is evaluated (below).
                                        //
                                        if (debug && (debugger != null) && !debugger.Disposed)
                                            debugger.SetActive(true);
#endif
                                        #endregion

                                        ///////////////////////////////////////////////////////////////

                                        #region Reset Local Error Line Flag
                                        //
                                        // NOTE: In order to accurately preserve and display the error
                                        //       line information, we need to know whether the current
                                        //       command, interactive or otherwise, actually set the
                                        //       error line.
                                        //
                                        bool haveErrorLine = false;
                                        #endregion

                                        ///////////////////////////////////////////////////////////////

                                        try
                                        {
                                            //
                                            // NOTE: First, check and see if an "interactive" command
                                            //       was entered (e.g. one that starts with "#");
                                            //       otherwise, evaluate the entered input as a script.
                                            //
                                            // TODO: This code is still too messy.  Resolving and
                                            //       executing interactive commands should be a lot
                                            //       cleaner, simpler, and more efficient.
                                            //
                                            ///////////////////////////////////////////////////////////

                                            #region Interactive Commands
#if INTERACTIVE_COMMANDS
                                            #region "Special" Interactive Commands
                                            //
                                            // NOTE: This first interactive command check is designed
                                            //       to allow any overridden interactive commands to
                                            //       be executed properly (e.g. "#show") even if they
                                            //       do not actually represent a built-in interactive
                                            //       command (e.g. "#foo").  This call modifies the
                                            //       local return code and result.  The result of the
                                            //       interactive command execution will be displayed
                                            //       using the normal mechanisms, after this huge
                                            //       "if/else" block (below).
                                            //
                                            if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, null, clientData, false,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                #region Interactive Extension Command
                                                //
                                                // NOTE: Do nothing.
                                                //
                                                #endregion
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "nop", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                #region Interactive Nop Command
                                                //
                                                // NOTE: This interactive command is specifically
                                                //       designed to do nothing.
                                                //
                                                #endregion
                                            }
                                            #endregion

                                            ///////////////////////////////////////////////////////////

                                            #region "Normal" Interactive Commands
                                            #region Previously "Special" Interactive Commands
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "go", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.go(
                                                    debug, ref done, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "run", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.run(
                                                    interpreter, debug, ref done, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "break", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands._break(
                                                    interpreter, debugArguments, token, traceInfo,
                                                    localEngineFlags, localSubstitutionFlags,
                                                    localEventFlags, localExpressionFlags,
                                                    localHeaderFlags, clientData, arguments,
                                                    ref done, ref localCode, ref localResult,
                                                    ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "halt", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.halt(
                                                    interpreter, debug, ref done, ref localCode,
                                                    ref localResult, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "done", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands._done(
                                                    debugArguments, ref done, ref localCode,
                                                    ref localResult, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "exit", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.exit(
                                                    ref exit, ref localCode, ref localResult);
                                            }
                                            #endregion

                                            ///////////////////////////////////////////////////////////

                                            else if (!noInteractive && (CheckInteractiveCommand(
                                                    interpreter, text, "cmd", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult) ||
                                                CheckInteractiveCommand(
                                                    interpreter, text, "cmd.exe", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult) ||
                                                CheckInteractiveCommand(
                                                    interpreter, text, "cmd", clientData, false,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult) ||
                                                CheckInteractiveCommand(
                                                    interpreter, text, "cmd.exe", clientData, false,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult)))
                                            {
                                                InteractiveOps.Commands.cmd(
                                                    interpreter, debugArguments, localEventFlags,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tclshrc", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tclshrc(
                                                    interpreter, interactiveHost as IEngineHost,
                                                    debugArguments, localEventFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "reset", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.reset(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "useattach", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.useattach(
                                                    interactiveHost, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "color", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.color(
                                                    interactiveHost, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "exceptions", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.exceptions(
                                                    interactiveHost, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "testgc", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.testgc(
                                                    interpreter, debugArguments, ref startedGcThread,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "hcancel", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.hcancel(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "hexit", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.hexit(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "check", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                localErrorLine = 0;

                                                InteractiveOps.Commands.check(
                                                    interpreter, debugArguments, localEngineFlags,
                                                    localSubstitutionFlags, localEventFlags,
                                                    localExpressionFlags, ref localCode,
                                                    ref localResult, ref localErrorLine);

                                                haveErrorLine = true;
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "eval", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.eval(
                                                    text, debugArguments, ref savedText,
                                                    ref tclsh, ref savedTclsh,
                                                    ref show, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "again", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.again(
                                                    interpreter, ref previous, ref show,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "help", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.help(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "usage", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.usage(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "version", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.version(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "args", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.args(
                                                    args, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "ainfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.ainfo(
                                                    interpreter, interactiveHost, code,
                                                    breakpointType, breakpointName, arguments,
                                                    result, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "clearq", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.clearq(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "oinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.oinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "vinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.vinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "complaint", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.complaint(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "cuinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.cuinfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "dinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.dinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "testinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.testinfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "toinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.toinfo(
                                                    interpreter, interactiveHost, token,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tcancel", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tcancel(
                                                    interpreter, debugArguments, traceInfo,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tcode", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tcode(
                                                    interpreter, debugArguments, traceInfo,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "toldvalue", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.toldvalue(
                                                    interpreter, debugArguments, traceInfo,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tnewvalue", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tnewvalue(
                                                    interpreter, debugArguments, traceInfo,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    traceInfo, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "stack", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.stack(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "finfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.finfo(
                                                    interpreter, interactiveHost, engineFlags,
                                                    substitutionFlags, eventFlags, expressionFlags,
                                                    headerFlags, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "lfinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.lfinfo(
                                                    interpreter, interactiveHost, localEngineFlags,
                                                    localSubstitutionFlags, localEventFlags,
                                                    localExpressionFlags, localHeaderFlags,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "frinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.frinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "einfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.einfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "cinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.cinfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "eninfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.eninfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "sinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.sinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "histfile", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.histfile(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "histinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.histinfo(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "histclear", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.histclear(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "histload", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.histload(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "histsave", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.histsave(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "hinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.hinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "iinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.iinfo(
                                                    interpreter, interactiveHost, result,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "fresc", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.fresc(
                                                    ref forceCancel, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "fresh", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.fresh(
                                                    ref forceHalt, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "resc", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.resc(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "resh", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.resh(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "rehash", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.rehash(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "deval", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                localErrorLine = 0;

                                                InteractiveOps.Commands.deval(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult, ref localErrorLine);

                                                haveErrorLine = true;
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "dsubst", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.dsubst(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "suspend", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.suspend(
                                                    interpreter, debug, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "resume", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.resume(
                                                    interpreter, debug, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "about", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.about(
                                                    interpreter, interactiveHost, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "chans", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.chans(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "init", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.init(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "dpath", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.dpath(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "cancel", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.cancel(
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && (CheckInteractiveCommand(
                                                    interpreter, text, "test", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult) ||
                                                CheckInteractiveCommand(
                                                    interpreter, text, "ptest", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult)))
                                            {
                                                localErrorLine = 0;

                                                InteractiveOps.Commands.test(
                                                    interpreter, debugArguments, localEngineFlags,
                                                    localSubstitutionFlags, localEventFlags,
                                                    localExpressionFlags, ref localCode,
                                                    ref localResult, ref localErrorLine);

                                                haveErrorLine = true;
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "trustclr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.trustclr(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "trustdir", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.trustdir(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "testdir", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.testdir(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "purge", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.purge(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "restc", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.restc(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "restv", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.restv(
                                                    interpreter, args, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "vout", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.vout(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "relimit", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.relimit(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "rlimit", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.rlimit(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "ntypes", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.ntypes(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "nflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.nflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "hflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.hflags(
                                                    interpreter, debugArguments, debug,
                                                    ref localHeaderFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "lhflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.lhflags(
                                                    interpreter, debugArguments, debug,
                                                    ref localHeaderFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "cflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.cflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "scflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.scflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "iflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.iflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "prflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.prflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "pflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.pflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "ceflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.ceflags(
                                                    interpreter, debugArguments,
                                                    ref localEngineFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "seflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.seflags(
                                                    interpreter, debugArguments,
                                                    ref localEngineFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "evflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.evflags(
                                                    interpreter, debugArguments,
                                                    ref localEventFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "exflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.exflags(
                                                    interpreter, debugArguments,
                                                    ref localExpressionFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "ieflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.ieflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "ievflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.ievflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "iexflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.iexflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "leflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.leflags(
                                                    interpreter, debugArguments,
                                                    ref localEngineFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "levflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.levflags(
                                                    interpreter, debugArguments, ref localEventFlags,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "lexflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.lexflags(
                                                    interpreter, debugArguments,
                                                    ref localExpressionFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "sflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.sflags(
                                                    interpreter, debugArguments,
                                                    ref localSubstitutionFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "isflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.isflags(
                                                    interpreter, debugArguments, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "lsflags", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.lsflags(
                                                    interpreter, debugArguments,
                                                    ref localSubstitutionFlags, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "step", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.step(
                                                    interpreter, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "style", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.style(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "canexit", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.canexit(
                                                    interactiveHost, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "show", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.show(
                                                    interpreter, interactiveHost, debugArguments,
                                                    debug, code, breakpointType, breakpointName,
                                                    token, traceInfo, engineFlags, substitutionFlags,
                                                    eventFlags, expressionFlags, clientData, arguments,
                                                    result, localHeaderFlags, localCode, localResult,
                                                    ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "overr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.overr(
                                                    interpreter, interactiveHost, debugArguments,
                                                    ref show, ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "prevr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.prevr(
                                                    interpreter, interactiveHost, ref show,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "nextr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.nextr(
                                                    interpreter, interactiveHost, localCode,
                                                    localResult, ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "fresr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.fresr(
                                                    interactiveHost, ref show, ref localCode,
                                                    ref localResult, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "resr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.resr(
                                                    interactiveHost, ref show, ref localCode,
                                                    ref localResult, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "clearr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.clearr(
                                                    interactiveHost, ref show, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "nullr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.nullr(
                                                    interactiveHost, ref show, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "copyr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.copyr(
                                                    interactiveHost, code, result, ref show,
                                                    ref localCode, ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "setr", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.setr(
                                                    interactiveHost, localCode, localResult,
                                                    ref show, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "mover", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.mover(
                                                    interactiveHost, ref show, ref localCode,
                                                    ref localResult, ref code, ref result);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "lrinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.lrinfo(
                                                    interactiveHost, localCode, localResult,
                                                    localErrorLine, ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "mrinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.mrinfo(
                                                    interpreter, interactiveHost, debugArguments,
                                                    code, result, ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "rinfo", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.rinfo(
                                                    interpreter, interactiveHost, localCode,
                                                    localResult, localErrorLine, code, result,
                                                    ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "sresult", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.sresult(
                                                    interpreter, interactiveHost, debugArguments,
                                                    localCode, localResult, localErrorLine, code,
                                                    result, ref show);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tclsh", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tclsh(interpreter,
                                                    interactiveHost, ref tclsh, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "tclinterp", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.tclinterp(
                                                    debugArguments, ref tclInterpName, ref localCode,
                                                    ref localResult);
                                            }
                                            else if (!noInteractive && CheckInteractiveCommand(
                                                    interpreter, text, "queue", clientData, true,
                                                    ref debugVerbose, ref debugArguments,
                                                    ref localCode, ref localResult))
                                            {
                                                InteractiveOps.Commands.queue(
                                                    interpreter, noInteractive, trace, debug,
                                                    localEngineFlags, localSubstitutionFlags,
                                                    localEventFlags, localExpressionFlags,
                                                    clientData, forceCancel, forceHalt,
                                                    ref interactiveHost, ref savedText, ref exit,
                                                    ref done, ref previous, ref canceled, ref text,
                                                    ref notReady, ref parseError, ref localCode,
                                                    ref localResult);
                                            }
                                            #endregion

                                            ///////////////////////////////////////////////////////////

                                            else // NOTE: Dangling else (see "if" statement below).
#endif
                                            #endregion

                                            ///////////////////////////////////////////////////////////

                                            #region Interactive Script Evaluation
                                            if (!String.IsNullOrEmpty(text) && (text.Trim().Length > 0))
                                            {
                                                try
                                                {
#if NATIVE && TCL
                                                    #region Tcl Shell Emulation Mode
                                                    //
                                                    // NOTE: Are we operating in "tclsh emulation mode"?
                                                    //       If so, try to get the active Tcl master
                                                    //       interpreter and use it to do the script
                                                    //       evaluation; otherwise, fallback on the normal
                                                    //       behavior of using the Eagle interpreter.
                                                    //
                                                    if (tclsh)
                                                    {
                                                        localErrorLine = 0;

                                                        ///////////////////////////////////////////////////

                                                        #region Get Native Tcl Interpreter
                                                        string interpName = null;
                                                        IntPtr interp = IntPtr.Zero;

                                                        if (tclInterpName != null)
                                                        {
                                                            interpName = tclInterpName;

                                                            localCode = interpreter.GetTclInterpreter(
                                                                interpName, LookupFlags.Default,
                                                                ref interp, ref localResult);
                                                        }
                                                        else
                                                        {
                                                            localCode = interpreter.GetAnyTclMasterInterpreter(
                                                                LookupFlags.Default, ref interpName, ref interp,
                                                                ref localResult);
                                                        }
                                                        #endregion

                                                        ///////////////////////////////////////////////////

                                                        #region Evaluate Tcl Script
                                                        if (localCode == ReturnCode.Ok)
                                                        {
                                                            localCode = interpreter.RecordAndEvaluateTclScript(
                                                                interpName, text, ref localResult);

                                                            if (localCode != ReturnCode.Ok)
                                                                localErrorLine = TclWrapper.GetErrorLine(
                                                                    interpreter.tclApi, interp);
                                                        }

                                                        ///////////////////////////////////////////////////

                                                        haveErrorLine = true;
                                                        #endregion
                                                    }
                                                    #endregion
                                                    else
#endif
                                                    {
                                                        #region Start Script Timeout Thread
                                                        //
                                                        // NOTE: Core interactive shell evaluation sequence.
                                                        //       This is somewhat tricky because of various
                                                        //       re-entrancy concerns.  Matters are further
                                                        //       complicated by script cancellation and
                                                        //       timeouts.
                                                        //
                                                        ReturnCode timeoutCode;
                                                        Result timeoutResult = null;

                                                        //
                                                        // NOTE: Start the runaway script detection /
                                                        //       cancellation thread.
                                                        //
                                                        timeoutCode = StartTimeoutThread(
                                                            interpreter, false, false, ref timeoutResult);

                                                        if (timeoutCode != ReturnCode.Ok)
                                                            DebugOps.Complain(interpreter, timeoutCode,
                                                                timeoutResult);
                                                        #endregion

                                                        ///////////////////////////////////////////////////

                                                        #region Evaluate Eagle Script
                                                        //
                                                        // NOTE: Perform the script evaluation using our
                                                        //       local code and result variables (i.e. do
                                                        //       not change the primary "interpreter
                                                        //       result").  It should also be noted that
                                                        //       this evaluation is not isolated in any
                                                        //       other way and will change the interpreter
                                                        //       state.
                                                        //
                                                        localErrorLine = 0;

                                                        ///////////////////////////////////////////////////

                                                        localCode = Engine.EvaluateScript(
                                                            interpreter, text, localEngineFlags,
                                                            localSubstitutionFlags, localEventFlags,
                                                            localExpressionFlags, ref localResult,
                                                            ref localErrorLine);

                                                        ///////////////////////////////////////////////////

                                                        haveErrorLine = true;
                                                        #endregion

                                                        ///////////////////////////////////////////////////

                                                        //
                                                        // NOTE: Make sure that the script just evaluated
                                                        //       did not dispose of the interpreter before
                                                        //       we try to access it.
                                                        //
                                                        if (!interpreter.PrivateDisposed)
                                                        {
                                                            #region [Maybe] Reset Halt Flag
                                                            //
                                                            // NOTE: Reset the interpreter halt flag if
                                                            //       this is the outermost interactive
                                                            //       loop and the interpreter evaluation
                                                            //       nesting level is zero.
                                                            //
                                                            haltCode = Engine.ResetHalt(
                                                                interpreter, false, true, ref haltReset,
                                                                ref haltResult);

                                                            if (haltCode != ReturnCode.Ok)
                                                            {
                                                                DebugOps.Complain(interpreter, haltCode,
                                                                    haltResult);
                                                            }
#if PREVIOUS_RESULT
                                                            else if (haltReset)
                                                            {
                                                                //
                                                                // NOTE: Reset the previous result here;
                                                                //       otherwise, the [debug break]
                                                                //       command will pick up the now
                                                                //       stale "INTERPRETER HALTED"
                                                                //       result and run with it otherwise.
                                                                //
                                                                Interpreter.SetPreviousResult(interpreter,
                                                                    null);
                                                            }
#endif
                                                            #endregion

                                                            ///////////////////////////////////////////////

                                                            #region Stop Script Timeout Thread
                                                            //
                                                            // NOTE: Stop the runaway script detection /
                                                            //       cancellation thread.
                                                            //
                                                            timeoutCode = InterruptTimeoutThread(
                                                                interpreter, false, ref timeoutResult);

                                                            if (timeoutCode != ReturnCode.Ok)
                                                                DebugOps.Complain(interpreter, timeoutCode,
                                                                    timeoutResult);
                                                            #endregion

                                                            ///////////////////////////////////////////////

                                                            #region Check Halt Flag
                                                            //
                                                            // NOTE: If debugging is still halted (i.e.
                                                            //       the ResetHalt above had no effect
                                                            //       because this is not the outermost
                                                            //       interactive loop), then exit this
                                                            //       interactive loop.
                                                            //
                                                            if (Engine.IsHalted(
                                                                    interpreter, true,
                                                                    ref localResult) != ReturnCode.Ok)
                                                            {
                                                                result = localResult; /* TRANSFER */
                                                                code = ReturnCode.Error;

                                                                //
                                                                // NOTE: Set the "done" flag for this
                                                                //       nested interactive loop now.
                                                                //       This code used to simply use
                                                                //       a C# "break" statement here;
                                                                //       however, this is much cleaner
                                                                //       because it permits the extra
                                                                //       tasks performed at the bottom
                                                                //       of this loop to be completed.
                                                                //
                                                                done = true;
                                                            }
                                                            #endregion
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    #region Restore Saved Tcl Shell Emulation Mode
                                                    //
                                                    // NOTE: If necessary, restore the saved setting
                                                    //       for "tclsh emulation mode".
                                                    //
                                                    if (savedTclsh != null)
                                                    {
                                                        tclsh = (bool)savedTclsh;
                                                        savedTclsh = null;
                                                    }
                                                    #endregion
                                                }
                                            }
                                            else
                                            {
                                                //
                                                // NOTE: We did absolutely nothing, record no previous
                                                //       interactive input and show no result.
                                                //
                                                previous = false;
                                                show = false;
                                            }
                                            #endregion
                                        }
                                        catch (Exception e)
                                        {
                                            TraceOps.DebugTrace(String.Format(
                                                "{0}: InteractiveLoop: caught exception, e = {1}{2}",
                                                GlobalState.GetCurrentThreadId(), e,
                                                Environment.NewLine), typeof(Interpreter).Name);
                                        }
                                        finally
                                        {
                                            #region Exit Debugger Active Level
#if DEBUGGER
                                            //
                                            // NOTE: Back out one level of nested debugger evaluations.
                                            //
                                            debugger = interpreter.Debugger; /* NOTE: Refresh. */

                                            if (debug && (debugger != null) && !debugger.Disposed)
                                                debugger.SetActive(false);
#endif
                                            #endregion
                                        }

                                        ///////////////////////////////////////////////////////////////

                                        #region Refresh Interpreter Host
                                        //
                                        // BUGFIX: We must reload the local interpreter host variable
                                        //         from the actual property because it may have been
                                        //         changed by an interactive command or script.  Also,
                                        //         skip trying to grab the interpreter host if the
                                        //         interpreter has been disposed.
                                        //
                                        interactiveHost = !interpreter.PrivateDisposed ?
                                            interpreter.Host : null;
                                        #endregion

                                        ///////////////////////////////////////////////////////////////

                                        #region Set Debugger Result
                                        //
                                        // NOTE: If there is a debugger available, store a copy of the
                                        //       local result in the debugger result.
                                        //
                                        DebuggerOps.SetResult(
                                            interpreter, localCode, localResult, false);
                                        #endregion

                                        ///////////////////////////////////////////////////////////////

                                        #region Refresh Exit Flag & Process "Previous" / "Show" Flags
                                        //
                                        // NOTE: Make sure that we exit if the [exit] command was used.
                                        //
                                        CheckExit(interpreter, ref exit);

                                        //
                                        // NOTE: Check if we are supposed to exit; if not, write the
                                        //       result of the last operation.
                                        //
                                        if (exit)
                                        {
                                            //
                                            // NOTE: Exit from entire interactive loop [and possibly
                                            //       the entire interpreter as well].  If the entire
                                            //       interpreter has been marked as exited all nested
                                            //       interactive loops will still exit cleanly.
                                            //
                                            done = true;
                                        }
                                        else
                                        {
                                            if (previous && !interpreter.PrivateDisposed)
                                                interpreter.PreviousInteractiveInput = text;

                                            if (show && (interactiveHost != null) &&
                                                !HostOps.IsDisposed(interactiveHost))
                                            {
                                                interactiveHost.WriteResultLine(
                                                    localCode, localResult, haveErrorLine ?
                                                        localErrorLine : 0);
                                            }
                                        }
                                        #endregion
                                    }
                                }

                                ///////////////////////////////////////////////////////////////////////

                                #region Interactive Host End-Processing Hook Callback
                                if (!done && (interactiveHost != null) &&
                                    !HostOps.IsDisposed(interactiveHost))
                                {
                                    ReturnCode endCode;
                                    Result endError = null;

                                    endCode = interactiveHost.EndProcessing(
                                        interpreter.InteractiveLoops, ref text, ref endError);

                                    if (endCode != ReturnCode.Ok)
                                    {
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: InteractiveLoop: host processing error, " +
                                            "endCode = {1}, endError = {2}{3}",
                                            GlobalState.GetCurrentThreadId(), endCode,
                                            FormatOps.WrapOrNull(true, true, endError),
                                            Environment.NewLine), typeof(Interpreter).Name);

                                        //
                                        // NOTE: Processing has been halted by the interactive
                                        //       host, bail out of the interactive loop now.
                                        //
                                        done = true;
                                    }
                                }
                                #endregion
                            } /* while (!done) */

                            ///////////////////////////////////////////////////////////////////////////

                            #region Interactive Host Done-Processing Hook Callback
                            if ((interactiveHost != null) &&
                                !HostOps.IsDisposed(interactiveHost))
                            {
                                ReturnCode doneCode;
                                Result doneError = null;

                                doneCode = interactiveHost.DoneProcessing(
                                    interpreter.InteractiveLoops, ref doneError);

                                if (doneCode != ReturnCode.Ok)
                                {
                                    TraceOps.DebugTrace(String.Format(
                                        "{0}: InteractiveLoop: host processing error, " +
                                        "doneCode = {1}, doneError = {2}{3}",
                                        GlobalState.GetCurrentThreadId(), doneCode,
                                        FormatOps.WrapOrNull(true, true, doneError),
                                        Environment.NewLine), typeof(Interpreter).Name);
                                }
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Restore / Pop Engine Flags
                            if (debug && !interpreter.PrivateDisposed)
                            {
                                //
                                // BUGFIX: Restore engine flags to the state they were in upon
                                //         entry into this interactive loop.
                                //
                                interpreter.ContextEngineFlags = savedEngineFlags;

                                //
                                // NOTE: clear out the previously saved engine flags.  This
                                //       statement serves as a reminder to re-think the
                                //       interpreter engine flag management, including
                                //       possibly adding a saved engine flags member to the
                                //       interpreter state.
                                //
                                savedEngineFlags = EngineFlags.None;
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region GC Test Thread Cleanup
#if INTERACTIVE_COMMANDS
                            //
                            // BUGFIX: Always try to stop the garbage collection test thread
                            //         if this interactive loop started it unless the current
                            //         interpreter has already been disposed.
                            //
                            if (startedGcThread && !interpreter.PrivateDisposed)
                            {
                                //
                                // NOTE: Acquire and hold the interpreter lock while shutting
                                //       down the garbage collection test thread, if it is
                                //       active.
                                //
                                lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                                {
                                    //
                                    // NOTE: Does the interpreter have an active garbage
                                    //       collection test thread?
                                    //
                                    if (TestOps.HasGcThread(interpreter))
                                    {
                                        ReturnCode gcCode;
                                        Result gcResult = null;

                                        gcCode = TestOps.InterruptGcThread(
                                            interpreter, false, ref gcResult);

                                        if (gcCode != ReturnCode.Ok)
                                            DebugOps.Complain(interpreter, gcCode,
                                                gcResult);
                                    }
                                }
                            }
#endif
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Write Interactive Footer
                            //
                            // BUGFIX: Skip writing anything if the interpreter host has already
                            //         been disposed.
                            //
                            if (debug && !exit && (interactiveHost != null) &&
                                !HostOps.IsDisposed(interactiveHost))
                            {
                                //
                                // NOTE: Attempt to cast the interactive host to an informational
                                //       host.  If this fails, we simply ignore it because it is
                                //       not strictly required for proper functioning of the
                                //       interactive loop.
                                //
                                IInformationHost informationHost =
                                    interactiveHost as IInformationHost;

                                bool proxy = AppDomainOps.IsTransparentProxy(informationHost);

                                if (informationHost != null)
                                    informationHost.WriteFooter(
                                        interpreter, code, breakpointType, breakpointName,
                                        !proxy ? token : null, !proxy ? traceInfo : null,
                                        engineFlags, substitutionFlags, eventFlags, expressionFlags,
                                        DebuggerOps.GetHeaderFlags(
                                            headerFlags, debug, true, false, debug),
                                        clientData, arguments, result);
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////
                            //
                            // NOTE: We can get to this label if the script evaluated
                            //       in the script initialization code block (above)
                            //       calls the [exit] command (or does something else
                            //       that causes the interpreter to be marked as exited)
                            //       for some (any?) reason.
                            //
                        skipLoop:

                            ///////////////////////////////////////////////////////////////////////////

                            #region Restore / Pop Interactive Loop Level
                            //
                            // BUGFIX: No need to restore these settings if the interpreter
                            //         has been disposed.
                            //
                            if (!interpreter.PrivateDisposed)
                            {
                                //
                                // NOTE: We are exiting this instance of the interactive
                                //       loop; therefore, decrease our tracking count.
                                //
                                interpreter.InteractiveLoops--; /* THREAD-SAFE */

                                //
                                // BUGFIX: Restore the interactive property to its previous
                                //         setting here, do not simply set it to false.
                                //
                                interpreter.Interactive = savedInteractive;

                                //
                                // BUGFIX: Restore the interactive thread property to its
                                //         previous value here, do not simply set it to null.
                                //         This can only be done in the primary application
                                //         domain for the interpreter.
                                //
                                if (AppDomainOps.IsSame(interpreter))
                                    interpreter.InteractiveThread = savedInteractiveThread;
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region [Maybe] Reset Halt Flag
                            //
                            // NOTE: This must be done _after_ the block (above) that reduces
                            //       the number of active interactive loops; otherwise, the
                            //       halt flag will not be reset when it really should be.
                            //
                            // BUGFIX: No need to reset the halt flag if the interpreter has
                            //         been disposed.
                            //
                            if (!interpreter.PrivateDisposed)
                            {
                                //
                                // NOTE: Possibly reset the "halt" state for the interpreter
                                //       (if there are no more nested loops).
                                //
                                haltCode = Engine.ResetHalt(
                                    interpreter, false, true, ref haltReset, ref haltResult);

                                if (haltCode != ReturnCode.Ok)
                                {
                                    DebugOps.Complain(interpreter, haltCode, haltResult);
                                }
#if PREVIOUS_RESULT
                                else if (haltReset)
                                {
                                    //
                                    // NOTE: Reset the previous result here; otherwise, the
                                    //       [debug break] command will pick up the now stale
                                    //       "INTERPRETER HALTED" result and run with it
                                    //       otherwise.
                                    //
                                    Interpreter.SetPreviousResult(interpreter, null);
                                }
#endif
                            }
                            #endregion

                            ///////////////////////////////////////////////////////////////////////////

                            #region Pop Active Interpreter
                            //
                            // NOTE: Pop this interpreter from the activation stack
                            //       because the interactive loop is now done using it.
                            //
                            /* IGNORED */
                            GlobalState.PopActiveInterpreter();
                            #endregion
                        }
#if NATIVE && WINDOWS
                        else
                        {
                            //
                            // NOTE: We are out of native stack space.  Perhaps there
                            //       are too many nested interactive loops?
                            //
                            result = "out of stack space (infinite loop?)";
                            code = ReturnCode.Error;
                        }
#endif
                    }
                    else
                    {
                        //
                        // NOTE: We absolutely require an interpreter hosting
                        //       environment (such as the provided Console Host)
                        //       for the interactive loop to function properly.
                        //
                        result = "interpreter host not available"; /* ERROR */
                        code = ReturnCode.Error;
                    }
                }
            }
            else
            {
                result = "invalid interpreter"; /* ERROR */
                code = ReturnCode.Error;
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: InteractiveLoop: exited, interpreter = {1}, debug = {2}, " +
                "args = {3}, code = {4}, breakpointType = {5}, breakpointName = {6}, " +
                "token = {7}, traceInfo = {8}, engineFlags = {9}, substitutionFlags = {10}, " +
                "eventFlags = {11}, expressionFlags = {12}, headerFlags = {13}, " +
                "clientData = {14}, arguments = {15}, exit = {16}, result = {17}{18}",
                GlobalState.GetCurrentThreadId(), FormatOps.WrapOrNull(
                    (interpreter != null) ? (object)interpreter.IdNoThrow : null), debug,
                FormatOps.WrapArgumentsOrNull(true, true, args), code, breakpointType,
                FormatOps.WrapOrNull(breakpointName), (token != null), (traceInfo != null),
                FormatOps.WrapOrNull(engineFlags), FormatOps.WrapOrNull(substitutionFlags),
                FormatOps.WrapOrNull(eventFlags), FormatOps.WrapOrNull(expressionFlags),
                FormatOps.WrapOrNull(headerFlags), FormatOps.WrapOrNull(clientData),
                FormatOps.WrapOrNull(true, true, arguments), exit, FormatOps.WrapOrNull(
                true, true, result), Environment.NewLine), typeof(Interpreter).Name);

            return code;
        }
#endif
        #endregion
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Entity Manager Support
        #region Policy Support
        #region Engine Interface Methods
        internal ReturnCode CheckCommandPolicies(
            PolicyFlags flags,
            IExecute execute,
            ArgumentList arguments,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            return CheckPolicies(
                MethodFlags.CommandPolicy, flags, execute, arguments, null,
                null, null, null, null, null, clientData, ref decision,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckScriptPolicies(
            PolicyFlags flags,
            IScript script,
            Encoding encoding,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            string hashAlgorithm = null; /* NOTE: Means "use default". */
            byte[] hashValue = null;

            if (!FlagOps.HasFlags(flags, PolicyFlags.NoHash, true))
            {
                Result hashError = null;

                hashValue = RuntimeOps.HashScript(
                    hashAlgorithm, script, encoding, ref hashError);

#if DEBUG && VERBOSE
                if (hashValue == null)
                    DebugOps.Complain(this, ReturnCode.Error, hashError);
#endif
            }

            return CheckPolicies(
                MethodFlags.ScriptPolicy, flags, null, null, script, null, null,
                (encoding != null) ? encoding : GetPolicyEncoding(false), null,
                null, clientData, ref decision, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckBeforeFilePolicies(
            PolicyFlags flags,
            string fileName,
            Encoding encoding,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            string hashAlgorithm = null; /* NOTE: Means "use default". */
            byte[] hashValue = null;

            if (!FlagOps.HasFlags(flags, PolicyFlags.NoHash, true))
            {
                Result hashError = null;

                hashValue = RuntimeOps.HashFile(
                    hashAlgorithm, fileName, encoding, ref hashError);

#if DEBUG && VERBOSE
                if (hashValue == null)
                    DebugOps.Complain(this, ReturnCode.Error, hashError);
#endif
            }

            return CheckPolicies(
                MethodFlags.FilePolicy, flags, null, null, null, fileName,
                null, (encoding != null) ? encoding : GetPolicyEncoding(true),
                hashValue, hashAlgorithm, clientData, ref decision, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckAfterFilePolicies(
            PolicyFlags flags,
            string fileName,
            string text,
            Encoding encoding,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            string hashAlgorithm = null; /* NOTE: Means "use default". */
            byte[] hashValue = null;

            if (!FlagOps.HasFlags(flags, PolicyFlags.NoHash, true))
            {
                Result hashError = null;

                hashValue = RuntimeOps.HashString(
                    hashAlgorithm, text, encoding, ref hashError);

#if DEBUG && VERBOSE
                if (hashValue == null)
                    DebugOps.Complain(this, ReturnCode.Error, hashError);
#endif
            }

            return CheckPolicies(
                MethodFlags.FilePolicy, flags, null, null, null, fileName,
                text, (encoding != null) ? encoding : GetPolicyEncoding(true),
                hashValue, hashAlgorithm, clientData, ref decision, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckBeforeStreamPolicies(
            PolicyFlags flags,
            string name,
            Encoding encoding,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            return CheckPolicies(
                MethodFlags.StreamPolicy, flags, null, null, null, name, null,
                (encoding != null) ? encoding : GetPolicyEncoding(false), null,
                null, clientData, ref decision, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CheckAfterStreamPolicies(
            PolicyFlags flags,
            string name,
            string text,
            Encoding encoding,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            string hashAlgorithm = null; /* NOTE: Means "use default". */
            byte[] hashValue = null;

            if (!FlagOps.HasFlags(flags, PolicyFlags.NoHash, true))
            {
                Result hashError = null;

                hashValue = RuntimeOps.HashString(
                    hashAlgorithm, text, encoding, ref hashError);

#if DEBUG && VERBOSE
                if (hashValue == null)
                    DebugOps.Complain(this, ReturnCode.Error, hashError);
#endif
            }

            return CheckPolicies(
                MethodFlags.StreamPolicy, flags, null, null, null, name, text,
                (encoding != null) ? encoding : GetPolicyEncoding(false),
                hashValue, hashAlgorithm, clientData, ref decision, ref result);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private bool HasNoPolicies()
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.NoPolicies, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void SetNoPolicies(
            bool noPolicies
            )
        {
            if (noPolicies)
                interpreterFlags |= InterpreterFlags.NoPolicies;
            else
                interpreterFlags &= ~InterpreterFlags.NoPolicies;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static Encoding GetPolicyEncoding(
            bool rawBytes
            )
        {
            return rawBytes ? OneByteEncoding.OneByte : DefaultEncoding;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode CheckPolicies(
            MethodFlags methodFlags,
            PolicyFlags policyFlags,
            IExecute execute,
            ArgumentList arguments,
            IScript script,
            string fileName,
            string text,
            Encoding encoding,
            byte[] hashValue,
            string hashAlgorithm,
            IClientData clientData,
            ref PolicyDecision decision,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (HasNoPolicies() || (PolicyLevels != 0))
                return code;

            //
            // NOTE: Grab a copy of the policy collection.
            //
            PolicyWrapperDictionary policies = CopyPolicies();

            //
            // NOTE: Does this interpreter support policies?
            //
            if (policies == null)
                return code;

            //
            // NOTE: Prevent endless policy recursion.
            //
            SetNoPolicies(true);

            try
            {
                //
                // NOTE: Create the policy data object with the current policy
                //       related information (including the original decision,
                //       which is typically "unknown").
                //
                IPolicyContext policyContext = PolicyContext.Create(
                    policyFlags, execute, arguments, script, fileName,
                    text, encoding, hashValue, hashAlgorithm, clientData,
                    /* plugin */ null, decision);

                //
                // NOTE: When going through the generic callback delegates, we
                //       need to wrap our object in a clientData.
                //
                IClientData policyClientData = new ClientData(policyContext);

                //
                // NOTE: Process each policy (as long as they all continue
                //       to succeed).
                //
                foreach (KeyValuePair<string, _Wrappers.Policy> pair in policies)
                {
                    IPolicy policy = pair.Value;

                    //
                    // NOTE: Skip invalid policies.
                    //
                    if (policy == null)
                        continue;

                    //
                    // NOTE: Do not invoke the policy if it has been disabled.
                    //
                    if (EntityOps.IsDisabled(policy))
                        continue;

                    //
                    // NOTE: Only execute the policies which match the specified
                    //       flags (i.e. command or file policies).
                    //
                    // FIXME: *PERF* Make sure this does not impact policy
                    //        performance too seriously.
                    //
                    if (!EntityOps.HasFlags(policy, methodFlags, true))
                        continue;

                    //
                    // NOTE: Since policies can basically do anything they want,
                    //       we wrap them in a try block to prevent exceptions
                    //       from escaping.
                    //
                    EnterPolicyLevel();

                    try
                    {
                        //
                        // HACK: Since we need the plugin to vary with each
                        //       policy called, do that now (i.e. to provide
                        //       more context for isolated policy support).
                        //
                        // TODO: Improve the locking semantics here.
                        //
                        policyContext.Plugin = policy.Plugin;

                        code = policy.Execute(
                            this, policyClientData, arguments, ref result);
                    }
                    catch (Exception e)
                    {
                        //
                        // NOTE: Translate exceptions to a failure return.
                        //
                        result = String.Format(
                            "caught exception while checking policies: {0}",
                            e);

                        code = ReturnCode.Error;
                    }
                    finally
                    {
                        ExitPolicyLevel();
                    }

                    //
                    // NOTE: Check for exception results specially because we
                    //       treat "Break" different from other return codes.
                    //
                    if (code == ReturnCode.Break)
                    {
                        //
                        // NOTE: Success; however, skip processing further
                        //       traces for this policy operation.
                        //
                        code = ReturnCode.Ok;
                        break;
                    }
                    else if (code != ReturnCode.Ok)
                    {
                        //
                        // NOTE: Some type of failure (or exception), stop
                        //       processing for this policy operation.
                        //
                        break;
                    }
                }

                //
                // NOTE: If all the policies succeeded and our local "pass" status
                //       is valid, copy it to the variable provided by the caller.
                //
                if (code == ReturnCode.Ok)
                {
                    //
                    // NOTE: Each policy gets one "vote" about whether or not to
                    //       allow the execution of the command.  One or more of
                    //       the current policies must agree for the execution of
                    //       the command to be allowed.  There must always be at
                    //       least one policy that "votes" to allow execution of
                    //       the command before it will be allowed (i.e. the
                    //       default policy denies everything).
                    //
                    decision = policyContext.Decision;

                    //
                    // NOTE: If there is no result so far, use the reason given
                    //       for the policy decision, if any.  We do not care if
                    //       the reason is null at this point.
                    //
                    if (result == null)
                        result = policyContext.Reason;
                }

#if POLICY_TRACE
                if (policyTrace)
                {
                    TraceOps.DebugTrace(String.Format(
                        "{0}: CheckPolicies: methodFlags = {1}, " +
                        "policyFlags = {2}, execute = {3}, " +
                        "arguments = {4}, script = {5}, " +
                        "fileName = {6}, text = {7}, encoding = {8}, " +
                        "hashValue = {9}, hashAlgorithm = {10}, " +
                        "clientData = {11}, decision = {12}, " +
                        "code = {13}, result = {14}{15}",
                        GlobalState.GetCurrentThreadId(),
                        FormatOps.WrapOrNull(methodFlags),
                        FormatOps.WrapOrNull(policyFlags),
                        FormatOps.WrapOrNull(execute),
                        FormatOps.WrapOrNull(true, true, arguments),
                        FormatOps.WrapOrNull(true, true, script),
                        FormatOps.WrapOrNull(fileName),
                        FormatOps.WrapOrNull(true, true, text),
                        FormatOps.WrapOrNull(encoding),
                        ArrayOps.ToHexadecimalString(hashValue),
                        FormatOps.WrapOrNull(hashAlgorithm),
                        FormatOps.WrapOrNull(clientData),
                        decision, code, FormatOps.WrapOrNull(result),
                        Environment.NewLine), typeof(Interpreter).Name);
                }
#endif
            }
            finally
            {
                //
                // NOTE: Remove policy prevention flag.
                //
                SetNoPolicies(false);
            }

            return code;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Trace Support
        private bool HasNoTraces()
        {
            return FlagOps.HasFlags(
                interpreterFlags, InterpreterFlags.NoTraces, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Dead Code
#if DEAD_CODE
        private void SetNoTraces(
            bool noTraces
            )
        {
            if (noTraces)
                interpreterFlags |= InterpreterFlags.NoTraces;
            else
                interpreterFlags &= ~InterpreterFlags.NoTraces;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal TraceList GetTraces(
            TraceList traces
            )
        {
            lock (syncRoot)
            {
                TraceList result = null;

                if ((this.traces != null) || (traces != null))
                {
                    result = new TraceList();

                    if (traces != null)
                        result.AddRange(traces);

                    if (this.traces != null)
                        result.AddRange(this.traces);
                }

                return result;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool NeedNewTraceInfo(
            VariableFlags flags
            )
        {
            if (FlagOps.HasFlags(flags, VariableFlags.NewTraceInfo, true))
                return true;

            //
            // NOTE: Query the number of trace levels at this point.
            //       Normally, this should be exactly one.
            //
            int levels = TraceLevels;

#if DEBUGGER
            //
            // NOTE: When compiled with integrated debugger support,
            //       also count the number of watchpoint levels.
            //
            levels += WatchpointLevels;
#endif

            return (levels > 0);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ClearVariableFlagsOrLink(
            ICallFrame frame,
            IVariable variable,
            ITraceInfo traceInfo,
            TraceList traces,
            ref bool wasUndefined,
            ref Result error
            )
        {
            //
            // BUGFIX: The variable may have been undefined or a link to a
            //         variable in an undefined call frame.
            //
            if (variable != null)
            {
                wasUndefined = EntityOps.IsUndefined(variable);
                bool isLink = EntityOps.IsLink(variable);

                if (wasUndefined || isLink)
                {
                    //
                    // NOTE: First, grab the variable flags from the trace, if
                    //       any.
                    //
                    VariableFlags flags = (traceInfo != null) ?
                        traceInfo.Flags : VariableFlags.None;

                    //
                    // NOTE: Next, attempt to obtain the call frame that this
                    //       variable belongs to.
                    //
                    ICallFrame variableFrame = frame;

                    if (GetVariableFrameViaResolvers(
                            LookupFlags.Default, ref variableFrame, ref flags,
                            ref error) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }

                    //
                    // NOTE: Next, figure out which variable flags need to be
                    //       masked off.  If the variable is being recycled
                    //       (i.e. because it was previously undefined), there
                    //       are additional flags to mask off.
                    //
                    VariableFlags flagsMask = VariableFlags.NonSetMask;

                    if (wasUndefined)
                        flagsMask = VariableFlags.NonDefinedMask;

                    //
                    // NOTE: Next, reset the flags to the ones provided by the
                    //       caller, masking off any invalid ones.
                    //
                    variable.Flags = (flags & ~flagsMask);

                    //
                    // NOTE: Next, make sure the variable is no longer a link
                    //       to another variable, if necessary.
                    //
                    if (isLink)
                    {
                        EntityOps.SetLink(variable, false);

                        variable.Link = null;
                        variable.LinkIndex = null;
                    }

                    //
                    // NOTE: Next, flag the variable as either global or local,
                    //       depending on the call frame it resides in.
                    //
                    if (IsGlobalCallFrame(variableFrame))
                        EntityOps.SetGlobal(variable, true);
                    else
                        EntityOps.SetLocal(variable, true);

                    //
                    // NOTE: Next, reset the traces for this variable to the
                    //       same ones that would be assigned to brand new
                    //       variables.
                    //
                    variable.Traces = GetTraces(traces);
                }
            }
            else
            {
                //
                // NOTE: There is no variable; therefore, it cannot be
                //       undefined.
                //
                wasUndefined = false;
            }

            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Alias Support
        internal ReturnCode GetAliasArguments(
            IAlias alias,
            ArgumentList arguments,
            ref string targetName
            )
        {
            ArgumentList targetArguments = null;

            return GetAliasArguments(
                alias, arguments, ref targetName, ref targetArguments);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetAliasArguments(
            IAlias alias,
            ArgumentList arguments,
            ref string targetName,
            ref ArgumentList targetArguments
            )
        {
            Result error = null;

            return GetAliasArguments(
                alias, arguments, ref targetName, ref targetArguments, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetAliasArguments(
            IAlias alias,
            ArgumentList arguments,
            ref string targetName,
            ref ArgumentList targetArguments,
            ref Result error
            )
        {
            ReturnCode code;

            if (alias != null)
            {
                AliasFlags aliasFlags = alias.AliasFlags;

                bool mergeArguments = FlagOps.HasFlags(
                    aliasFlags, AliasFlags.MergeArguments, true);

                bool skipTargetName = FlagOps.HasFlags(
                    aliasFlags, AliasFlags.SkipTargetName, true);

                bool skipSourceName = FlagOps.HasFlags(
                    aliasFlags, AliasFlags.SkipSourceName, true);

                if (mergeArguments)
                {
                    //
                    // NOTE: Merged argument handling, carefully merge the
                    //       option and non-option arguments from the first
                    //       and second lists.  The start index for the second
                    //       list here is hard-coded to one because we know
                    //       that the command name itself is the first argument
                    //       in the second list.
                    //
                    code = MergeArguments(alias.Options, alias.Arguments,
                        arguments, alias.StartIndex, 1, skipTargetName,
                        skipSourceName, ref targetArguments, ref error);
                }
                else
                {
                    targetArguments = null;

                    //
                    // NOTE: Standard argument handling, simply append the
                    //       arguments from the first and second lists, in that
                    //       order, to the target argument list.
                    //
                    if ((alias.Arguments != null) || (arguments != null))
                        targetArguments = new ArgumentList();

                    if (alias.Arguments != null)
                    {
                        targetArguments.AddRange(ArgumentList.GetRange(
                            alias.Arguments, skipTargetName ? 1 : 0));
                    }

                    if (arguments != null)
                    {
                        targetArguments.AddRange(ArgumentList.GetRange(
                            arguments, skipSourceName ? 1 : 0));
                    }

                    code = ReturnCode.Ok;
                }

                //
                // NOTE: If necessary, modify the first argument to be the
                //       alias name.  Afterwards, always provide the value of
                //       the first argument to the caller.
                //
                targetName = null;

                if ((targetArguments != null) && (targetArguments.Count > 0))
                    targetName = targetArguments[0];
            }
            else
            {
                error = "invalid alias";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetAliasTarget(
            IAlias alias,
            string targetName,
            ArgumentList targetArguments,
            LookupFlags lookupFlags,
            bool strict,
            ref IExecute target
            )
        {
            bool useUnknown = false;
            Result error = null;

            return GetAliasTarget(
                alias, targetName, targetArguments, lookupFlags, strict,
                ref target, ref useUnknown, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetAliasTarget(
            IAlias alias,
            string targetName,
            ArgumentList targetArguments,
            LookupFlags lookupFlags,
            bool strict,
            ref IExecute target,
            ref bool useUnknown,
            ref Result error
            )
        {
            ReturnCode code;

            //
            // NOTE: First, try for the pre-resolved target.
            //
            target = alias.Target;

            //
            // NOTE: Otherwise, is this a late-bound alias?
            //
            if (target != null)
            {
                //
                // NOTE: Success, just return it.
                //
                code = ReturnCode.Ok;
            }
            else
            {
                EngineFlags engineFlags = GetResolveEngineFlags(true);
                Result localError = null;

                //
                // NOTE: Not found; lookup the target by name.
                //
                code = GetIExecuteViaResolvers(
                    engineFlags, targetName, targetArguments, lookupFlags,
                    ref target, ref localError);

                //
                // NOTE: During the alias creation process, the target
                //       does not have to be defined.  However, during
                //       the execution process, it does.
                //
                if (code != ReturnCode.Ok)
                {
                    //
                    // NOTE: Attempt to use the unknown handler for
                    //       the interpreter when the target cannot
                    //       be resolved (COMPAT: Tcl).
                    //
                    code = AttemptToUseUnknown(
                        code, engineFlags | EngineFlags.GlobalOnly,
                        lookupFlags, targetArguments, ref target,
                        ref useUnknown);

                    if (code != ReturnCode.Ok)
                    {
                        if (!strict)
                            code = ReturnCode.Ok;
                        else
                            error = localError;
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string GetAliasNameToken(string name)
        {
            //
            // NOTE: Initially, the name token is the same as the name;
            //       however, this may change later if the command is
            //       renamed.
            //
            string result = name;

            if (!String.IsNullOrEmpty(result))
                while (DoesAliasExist(result) == ReturnCode.Ok)
                    /*
                     * NOTE: This comment stolen from "generic/tclInterp.c".
                     *
                     * The alias name cannot be used as unique token, it is already taken.
                     * We can produce a unique token by prepending "::" repeatedly. This
                     * algorithm is a stop-gap to try to maintain the command name as
                     * token for most use cases, fearful of possible backwards compat
                     * problems. A better algorithm would produce unique tokens that need
                     * not be related to the command name.
                     *
                     * ATTENTION: the tests in interp.test and possibly safe.test depend
                     * on the precise definition of these tokens.
                     *
                     */
                    result = TclVars.NamespaceSeparator + result;

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private IAlias FollowAlias(
            IAlias alias,
            IAlias nextAlias,
            string newName
            )
        {
            IAlias result = null;

            if (nextAlias.Target != null)
            {
                result = nextAlias.Target as IAlias;
            }
            else
            {
                Interpreter targetInterpreter = nextAlias.TargetInterpreter;

                if (targetInterpreter != null)
                {
                    string targetName = null;
                    ArgumentList targetArguments = null;

                    if (targetInterpreter.GetAliasArguments(
                            nextAlias, null, ref targetName,
                            ref targetArguments) == ReturnCode.Ok)
                    {
                        if (targetName != null)
                        {
                            if (targetInterpreter.GetAlias(
                                    targetName, LookupFlags.Default,
                                    ref result) != ReturnCode.Ok)
                            {
                                //
                                // NOTE: If the alias is being renamed, make
                                //       sure we are using the new name (i.e.
                                //       in that case the caller(s) is/are
                                //       responsible for passing it to us).
                                //
                                if (Object.ReferenceEquals(targetInterpreter, this) &&
                                    String.Compare(targetName,
                                        (newName != null) ? newName : alias.Name,
                                        StringOps.SystemStringComparisonType) == 0)
                                {
                                    result = alias;
                                }
                            }
                        }
                    }
                }
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode PreventAliasLoop(
            IAlias alias,
            string newName,
            ref Result error
            )
        {
            IAlias nextAlias = alias;

            while (nextAlias != null)
            {
                //
                // NOTE: Proceed to the next alias in the chain.
                //
                nextAlias = FollowAlias(alias, nextAlias, newName);

                //
                // NOTE: Check to see if we have found a loop.
                //
                if (Object.ReferenceEquals(nextAlias, alias))
                {
                    error = String.Format(
                        "cannot define or rename alias \"{0}\": would create a loop",
                        (newName != null) ? newName : alias.Name);

                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddAliasAndCommand(
            IAlias alias,
            IClientData clientData,
            ref long token,
            ref Result result
            )
        {
            if (PreventAliasLoop(alias, null, ref result) == ReturnCode.Ok)
                //
                // NOTE: If the provided alias is not also a command, this cast will
                //       silently fail; however, that is fine because AddCommand will
                //       return an appropriate error message to the caller.
                //
                if (AddCommand(alias as ICommand, clientData, ref result) == ReturnCode.Ok)
                    if (AddAlias(alias, clientData, ref token, ref result) == ReturnCode.Ok)
                        return ReturnCode.Ok;

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveAliasAndCommand(
            string name,
            IClientData clientData,
            bool strict,
            ref Result result
            )
        {
            /* CheckDisposed(); */

            Result localResult = null;

            lock (syncRoot) /* TRANSACTIONAL */
            {
                if (HasAliases(ref localResult))
                {
                    IAlias alias = null;

                    if (GetAlias(
                            name, LookupFlags.Default, ref alias,
                            ref localResult) == ReturnCode.Ok)
                    {
                        if (RemoveAlias(alias.NameToken, clientData,
                                ref localResult) == ReturnCode.Ok)
                        {
                            if (HasCommands(ref localResult))
                            {
                                string commandName = alias.Name;

                                if ((DoesCommandExist(
                                        commandName) != ReturnCode.Ok) ||
                                    (RemoveCommand(
                                        commandName, clientData,
                                        ref localResult) == ReturnCode.Ok))
                                {
                                    return ReturnCode.Ok;
                                }
                            }
                            else if (!strict)
                            {
                                return ReturnCode.Ok;
                            }
                        }
                    }
                }
                else if (!strict)
                {
                    return ReturnCode.Ok;
                }
            }

            result = localResult;
            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Object Alias Support
        internal ReturnCode GetObjectAliasTarget(
            ref IExecute target,
            ref Result error
            )
        {
            ICommand command = null;

            if (GetCommand(
                    typeof(_Commands.Object), LookupFlags.Default,
                    ref command, ref error) == ReturnCode.Ok)
            {
                target = command;

                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddObjectAlias(
            string objectName,
            string aliasName,
            OptionDictionary options,
            ObjectOptionType objectOptionType,
            bool reference,
            ref IAlias alias,
            ref Result error
            )
        {
            IExecute target = null;

            if (GetObjectAliasTarget(ref target, ref error) == ReturnCode.Ok)
            {
                ArgumentList arguments = null;

                if (RuntimeOps.GetObjectAliasArguments(
                        objectName, objectOptionType,
                        ref arguments, ref error) == ReturnCode.Ok)
                {
                    AliasFlags aliasFlags = AliasFlags.MergeArguments |
                        AliasFlags.Object;

                    int startIndex = 2; /* NOTE: For [object invoke]. */

                    if (aliasName != null)
                    {
                        aliasFlags |= AliasFlags.SkipSourceName;
                        startIndex++; /* NOTE: For $objectName. */
                    }

                    Result result = null;

                    if (AddAlias(
                            (aliasName != null) ? aliasName : objectName,
                            CommandFlags.None, aliasFlags, ClientData.Empty,
                            this, target, arguments, options, startIndex
                            /* [object invoke ?name?] */, ref alias,
                            ref result) == ReturnCode.Ok)
                    {
                        if (reference)
                        {
                            ReturnCode localCode;
                            Result localError = null;

                            localCode = AddObjectReference(ReturnCode.Ok,
                                result, ref localError);

                            if (localCode == ReturnCode.Ok)
                            {
                                if (alias != null)
                                    alias.AliasFlags |= AliasFlags.Reference;
                            }
                            else
                            {
                                DebugOps.Complain(this, localCode, localError);
                            }
                        }

                        return ReturnCode.Ok;
                    }
                    else
                    {
                        //
                        // NOTE: Transfer error message to caller.
                        //
                        error = result;
                    }
                }
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Alias Support
#if NATIVE && TCL
        internal ReturnCode GetTclAliasTarget(
            ref IExecute target,
            ref Result error
            )
        {
            ICommand command = null;

            if (GetCommand(
                    typeof(_Commands.Tcl), LookupFlags.Default,
                    ref command, ref error) == ReturnCode.Ok)
            {
                target = command;

                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode AddTclAlias(string name, ref Result error)
        {
            IExecute target = null;

            if (GetTclAliasTarget(ref target, ref error) == ReturnCode.Ok)
            {
                ArgumentList arguments = null;

                if (RuntimeOps.GetTclAliasArguments(
                        null, ref arguments, ref error) == ReturnCode.Ok)
                {
                    Result result = null;

                    if (AddAlias(
                            name, CommandFlags.None, AliasFlags.TclWrapper,
                            ClientData.Empty, this, target, arguments, null,
                            2 /* tcl eval */, ref result) == ReturnCode.Ok)
                    {
                        return ReturnCode.Ok;
                    }
                    else
                    {
                        //
                        // NOTE: Transfer error message to caller.
                        //
                        error = result;
                    }
                }
            }

            return ReturnCode.Error;
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Slave Interpreter Support
        internal ReturnCode GetInterpreterPath(
            Interpreter interpreter,
            ref Result result
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (Object.ReferenceEquals(interpreter, this))
            {
                result = String.Empty;
                return ReturnCode.Ok;
            }

            Interpreter otherInterpreter = interpreter;
            StringList list = new StringList();

            while (!Object.ReferenceEquals(otherInterpreter, this))
            {
                string slaveName = otherInterpreter.SlaveName;

                if (slaveName == null)
                    slaveName = otherInterpreter.ToString();

                //
                // NOTE: Keep track of the names going up the chain.
                //
                list.Add(slaveName);

                //
                // NOTE: Traverse to our master interpreter.
                //
                otherInterpreter = otherInterpreter.MasterInterpreter;

                //
                // NOTE: Make sure the interpreter is still valid
                //       because we still haven't found this
                //       interpreter yet.
                //
                if (otherInterpreter == null)
                {
                    //
                    // NOTE: This should not really happen.  If so,
                    //       it is an error.
                    //
                    result = "invalid master interpreter";
                    return ReturnCode.Error;
                }
            }

            list.Reverse();
            result = list;

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetNestedSlaveInterpreter(
            string path,
            LookupFlags lookupFlags,
            bool create,
            ref Interpreter interpreter, /* NOTE: Only set upon success. */
            ref Result error             /* NOTE: Only set upon failure. */
            )
        {
            string name = null;

            return GetNestedSlaveInterpreter(path, lookupFlags, create,
                ref interpreter, ref name, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetNestedSlaveInterpreter(
            string path,                 /* in */
            LookupFlags lookupFlags,     /* in */
            bool create,                 /* in */
            ref Interpreter interpreter, /* out */
            ref string name,             /* out */
            ref Result error             /* out */
            )
        {
            StringList list = null;

            if (Parser.SplitList(
                    this, path, 0, Length.Invalid, true,
                    ref list, ref error) == ReturnCode.Ok)
            {
                Interpreter otherInterpreter = this;

                if (list.Count > 0)
                {
                    for (int index = 0; index < list.Count - 1; index++)
                    {
                        if (otherInterpreter.GetSlaveInterpreter(
                                list[index], lookupFlags, ref otherInterpreter,
                                ref error) != ReturnCode.Ok)
                        {
                            return ReturnCode.Error;
                        }
                    }

                    //
                    // NOTE: This will be the name of the new interpreter
                    //       to be created in the target interpreter if the
                    //       "create" flag is true; otherwise, it will simply
                    //       be the name of the innertmost nested interpreter.
                    //
                    name = list[list.Count - 1];

                    if (!create)
                        //
                        // NOTE: Return the last interpreter in the "chain";
                        //       this one will be validated (i.e. checked for
                        //       null) only if the caller has requested it.
                        //
                        return otherInterpreter.GetSlaveInterpreter(
                            name, lookupFlags, ref interpreter, ref error);
                }

                interpreter = otherInterpreter;
                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CreateSlaveInterpreter(
            string path,
            IClientData clientData,
            CreateFlags createFlags,
            bool isolated,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;
            Interpreter interpreter = null;
            string name = null;

            if (path != null)
            {
                code = GetNestedSlaveInterpreter(
                    path, LookupFlags.Interpreter, true, ref interpreter,
                    ref name, ref result);
            }
            else
            {
                interpreter = this;
            }

            if (code == ReturnCode.Ok)
            {
#if APPDOMAINS && ISOLATED_INTERPRETERS
                string otherAppDomainName = null;
                AppDomain otherAppDomain = null;
                InterpreterHelper otherInterpreterHelper = null;
#endif
                Interpreter otherInterpreter = null;

                try
                {
                    if (isolated)
                    {
#if APPDOMAINS && ISOLATED_INTERPRETERS
                        otherAppDomainName = FormatOps.Id("slaveInterpreter", null, NextId());

                        code = AddAppDomain(otherAppDomainName, null,
#if CAS_POLICY
                            null,
#endif
                            clientData, true, ref otherAppDomain, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            otherInterpreterHelper = InterpreterHelper.Create(
                                otherAppDomain, null, createFlags & ~CreateFlags.ThrowOnError,
                                ScriptFlags.Default, null, null, null, ref result);

                            if (otherInterpreterHelper != null)
                            {
                                otherInterpreter = otherInterpreterHelper.Interpreter;

                                if (otherInterpreter == null)
                                    code = ReturnCode.Error;
                            }
                            else
                            {
                                code = ReturnCode.Error;
                            }
                        }
#else
                        result = "not implemented";
                        code = ReturnCode.Error;
#endif
                    }
                    else
                    {
                        otherInterpreter = Create(null,
                            createFlags & ~CreateFlags.ThrowOnError, ref result);

                        if (otherInterpreter == null)
                            code = ReturnCode.Error;
                    }
                }
                catch (Exception e)
                {
                    result = e;
                    code = ReturnCode.Error;
                }
                finally
                {
                    if (code == ReturnCode.Ok)
                    {
                        string otherId = isolated ?
                            GlobalState.NextInterpreterId().ToString() :
                            otherInterpreter.ToString();

                        if (name == null)
                            name = otherId;

                        code = interpreter.AddSlaveInterpreter(
                            name, otherInterpreter, clientData, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            //
                            // NOTE: Set the master interpreter for the newly
                            //       created interpreter.
                            //
                            otherInterpreter.MasterInterpreter = interpreter;

                            //
                            // NOTE: We need a way to find this new interpreter
                            //       by the arbitrary name assigned to it by the
                            //       caller, not just the automatic Id; therefore,
                            //       store that now.
                            //
                            if (String.Compare(name, otherId,
                                    StringOps.SystemStringComparisonType) != 0)
                            {
                                otherInterpreter.SlaveName = name;
                            }

#if APPDOMAINS && ISOLATED_INTERPRETERS
                            //
                            // NOTE: Set the application domain name for the newly
                            //       created interpreter (in isolated mode only).
                            //
                            if (otherAppDomainName != null)
                                otherInterpreter.SlaveAppDomainName = otherAppDomainName;
#endif

                            //
                            // NOTE: Return the interpreter path if it is valid;
                            //       otherwise, return the generated interpreter
                            //       name.
                            //
                            result = (path != null) ? path : name;
                        }
                    }
                    else
                    {
                        if (otherInterpreter != null)
                        {
                            ReturnCode disposeCode;
                            Result disposeError = null;

                            disposeCode = ObjectOps.TryDispose(
                                otherInterpreter, ref disposeError);

                            if (disposeCode != ReturnCode.Ok)
                                DebugOps.Complain(interpreter, disposeCode, disposeError);
                        }

                        ///////////////////////////////////////////////////////////////////////////////

#if APPDOMAINS && ISOLATED_INTERPRETERS
                        if (otherInterpreterHelper != null)
                        {
                            ReturnCode disposeCode;
                            Result disposeError = null;

                            disposeCode = ObjectOps.TryDispose(
                                otherInterpreterHelper, ref disposeError);

                            if (disposeCode != ReturnCode.Ok)
                                DebugOps.Complain(interpreter, disposeCode, disposeError);
                        }

                        if (otherAppDomainName != null)
                        {
                            ReturnCode removeCode;
                            Result removeError = null;

                            removeCode = RemoveAppDomain(
                                otherAppDomainName, clientData, ref removeError);

                            if (removeCode != ReturnCode.Ok)
                                DebugOps.Complain(interpreter, removeCode, removeError);
                        }
#endif
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DeleteSlaveInterpreter(
            string path,
            IClientData clientData,
            bool synchronous,
            ref Result error
            )
        {
            Interpreter interpreter = null;
            string name = null;

            if (GetNestedSlaveInterpreter(
                    path, LookupFlags.Interpreter, true,
                    ref interpreter, ref name,
                    ref error) == ReturnCode.Ok)
            {
                return interpreter.RemoveSlaveInterpreter(
                    name, clientData, synchronous, ref error);
            }

            return ReturnCode.Error;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Context Manager Support
        private int CountThreadInterpreters()
        {
#if THREADING
            try
            {
                if (contextManager != null)
                    return contextManager.GetInterpreterContextCount();
            }
            catch
            {
                // do nothing.
            }
#else
            InterpreterDictionary interpreters = GlobalState.GetInterpreters();

            if (interpreters != null)
            {
                int count = 0;

                foreach (KeyValuePair<string, Interpreter> pair in interpreters)
                    if ((pair.Value != null) && pair.Value.IsPrimaryThread())
                        count++;

                return count;
            }
#endif

            return 0;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if THREADING
        internal IContextManager InternalContextManager
        {
            get
            {
                // CheckDisposed();

                return contextManager;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Engine Context Members
        public int Levels /* WARNING: NOT GUARANTEED TO BE ACCURATE OR USEFUL. */
        {
            get
            {
                CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.Levels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return levels;
                }
#endif
            }
            private set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.Levels = value;
#else
                // lock (syncRoot)
                {
                    levels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int PreviousLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.PreviousLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return previousLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.PreviousLevels = value;
#else
                // lock (syncRoot)
                {
                    previousLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int ParserLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ParserLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return parserLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ParserLevels = value;
#else
                // lock (syncRoot)
                {
                    parserLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int ExpressionLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ExpressionLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return expressionLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ExpressionLevels = value;
#else
                // lock (syncRoot)
                {
                    expressionLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int UnknownLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.UnknownLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return unknownLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.UnknownLevels = value;
#else
                // lock (syncRoot)
                {
                    unknownLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int TraceLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.TraceLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return traceLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.TraceLevels = value;
#else
                // lock (syncRoot)
                {
                    traceLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER
        private int WatchpointLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.WatchpointLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return watchpointLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.WatchpointLevels = value;
#else
                // lock (syncRoot)
                {
                    watchpointLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IDebugger Debugger
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.Debugger;
                else
                    return null;
#else
                // lock (syncRoot)
                {
                    return debugger;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.Debugger = value;
#else
                // lock (syncRoot)
                {
                    debugger = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
        private int NotifyLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.NotifyLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return notifyLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.NotifyLevels = value;
#else
                // lock (syncRoot)
                {
                    notifyLevels = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int PolicyLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.PolicyLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return policyLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.PolicyLevels = value;
#else
                // lock (syncRoot)
                {
                    policyLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int TestLevels
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.TestLevels;
                else
                    return 0;
#else
                // lock (syncRoot)
                {
                    return testLevels;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.TestLevels = value;
#else
                // lock (syncRoot)
                {
                    testLevels = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool StackOverflow
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.StackOverflow;
                else
                    return false;
#else
                lock (syncRoot)
                {
                    return stackOverflow;
                }
#endif
            }
            set
            {
                // CheckDisposed();

                //
                // NOTE: This property "setter" is only supposed to be used during
                //       interpreter initialization.
                //
#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.StackOverflow = value;
#else
                lock (syncRoot)
                {
                    stackOverflow = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if PREVIOUS_RESULT
        private Result PreviousResult
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.PreviousResult;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return previousResult;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.PreviousResult = value;
#else
                lock (syncRoot)
                {
                    previousResult = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EngineFlags EngineFlags
        {
            get
            {
                // CheckDisposed();

                lock (syncRoot)
                {
#if THREADING
                    IEngineContext context = (contextManager != null) ?
                        contextManager.GetEngineContext(true) : null;

                    if (context != null)
                        return engineFlags | context.EngineFlags;
                    else
                        return engineFlags;
#else
                    return engineFlags;
#endif
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EngineFlags ContextEngineFlags
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.EngineFlags;
                else
                    return EngineFlags.None;
#else
                lock (syncRoot)
                {
                    return engineFlags;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.EngineFlags = value;
#else
                lock (syncRoot)
                {
                    engineFlags = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EngineFlags SharedEngineFlags
        {
            get
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    return engineFlags;
                }
            }
            set
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    engineFlags = value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IParseState ParseState
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ParseState;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return parseState;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ParseState = value;
#else
                lock (syncRoot)
                {
                    parseState = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode ReturnCode
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ReturnCode;
                else
                    return ReturnCode.Ok;
#else
                lock (syncRoot)
                {
                    return returnCode;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ReturnCode = value;
#else
                lock (syncRoot)
                {
                    returnCode = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string ErrorCode
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ErrorCode;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return errorCode;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ErrorCode = value;
#else
                lock (syncRoot)
                {
                    errorCode = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string ErrorInfo
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ErrorInfo;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return errorInfo;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ErrorInfo = value;
#else
                lock (syncRoot)
                {
                    errorInfo = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ErrorFrames
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ErrorFrames;
                else
                    return 0;
#else
                lock (syncRoot)
                {
                    return errorFrames;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ErrorFrames = value;
#else
                lock (syncRoot)
                {
                    errorFrames = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IScriptLocation ScriptLocation
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ScriptLocation;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return scriptLocation;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ScriptLocation = value;
#else
                lock (syncRoot)
                {
                    scriptLocation = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StackList<IScriptLocation> ScriptLocations
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ScriptLocations;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return scriptLocations;
                }
#endif
            }
            private set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ScriptLocations = value;
#else
                lock (syncRoot)
                {
                    scriptLocations = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int PreviousProcessId
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.PreviousProcessId;
                else
                    return 0;
#else
                lock (syncRoot)
                {
                    return previousProcessId;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.PreviousProcessId = value;
#else
                lock (syncRoot)
                {
                    previousProcessId = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ArraySearchDictionary ArraySearches
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.ArraySearches;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return arraySearches;
                }
#endif
            }
            private set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.ArraySearches = value;
#else
                lock (syncRoot)
                {
                    arraySearches = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if HISTORY
        private ClientDataList _History
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.History;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return _history;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.History = value;
#else
                lock (syncRoot)
                {
                    _history = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EngineFlags BeginExternalExecution()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return context.BeginExternalExecution();
            else
                return EngineFlags.None;
#else
            EnterLevel();

            engineFlags |= EngineFlags.ExternalExecution;
            return Engine.AddStackCheckFlags(ref engineFlags);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EndExternalExecution(
            EngineFlags savedEngineFlags
            )
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return context.EndExternalExecution(savedEngineFlags);
            else
                return 0;
#else
            Engine.RemoveStackCheckFlags(savedEngineFlags, ref engineFlags);
            engineFlags &= ~EngineFlags.ExternalExecution;

            return ExitLevel();
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EndAndCleanupExternalExecution(
            EngineFlags savedEngineFlags
            )
        {
            int levels = EndExternalExecution(savedEngineFlags);

            if (levels == 0)
                Engine.CleanupNamespacesOrComplain(this);

            return levels;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int BeginNestedExecution()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return context.BeginNestedExecution();
            else
                return 0;
#else
            int savedPreviousLevels;

            lock (syncRoot)
            {
                savedPreviousLevels = previousLevels;
                previousLevels = levels;
            }

            return savedPreviousLevels;
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void EndNestedExecution(
            int savedPreviousLevels
            )
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                context.EndNestedExecution(savedPreviousLevels);
#else
            lock (syncRoot)
            {
                previousLevels = savedPreviousLevels;
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if PREVIOUS_RESULT
        internal static Result GetPreviousResult(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return null;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return null;

                return interpreter.PreviousResult;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static void SetPreviousResult(
            Interpreter interpreter,
            Result previousResult
            )
        {
            if (interpreter == null)
                return;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return;

                interpreter.PreviousResult = previousResult;
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Support Methods
        #region Enter / Exit Context Levels
        internal int EnterLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.Levels;
            else
                return 0;
#else
            return Interlocked.Increment(ref levels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.Levels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref levels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterParserLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.ParserLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref parserLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitParserLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.ParserLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref parserLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterExpressionLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.ExpressionLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref expressionLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitExpressionLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.ExpressionLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref expressionLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterUnknownLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.UnknownLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref unknownLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitUnknownLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.UnknownLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref unknownLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterTraceLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.TraceLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref traceLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitTraceLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.TraceLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref traceLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER
        internal int EnterWatchpointLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.WatchpointLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref watchpointLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitWatchpointLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.WatchpointLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref watchpointLevels);
#endif
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
        internal int EnterNotifyLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.NotifyLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref notifyLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitNotifyLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.NotifyLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref notifyLevels);
#endif
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterPolicyLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.PolicyLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref policyLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitPolicyLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.PolicyLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref policyLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int EnterTestLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return ++context.TestLevels;
            else
                return 0;
#else
            return Interlocked.Increment(ref testLevels);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal int ExitTestLevel()
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true) : null;

            if (context != null)
                return --context.TestLevels;
            else
                return 0;
#else
            return Interlocked.Decrement(ref testLevels);
#endif
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interpreter Readiness
        private ReturnCode GetReadyLevels(
            ref int levels,
            ref int parserLevels,
            ref int expressionLevels,
            ref Result error
            )
        {
#if THREADING
            IEngineContext context = (contextManager != null) ?
                contextManager.GetEngineContext(true, ref error) : null;

            if (context != null)
            {
                levels = context.Levels;
                parserLevels = context.ParserLevels;
                expressionLevels = context.ExpressionLevels;

                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
#else
            levels = this.levels;
            parserLevels = this.parserLevels;
            expressionLevels = this.expressionLevels;

            return ReturnCode.Ok;
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode Ready( /* FOR EXTERNAL USE ONLY. */
            Interpreter interpreter,
            ref Result error
            ) /* THREAD-SAFE */
        {
            int timeout = DefaultReadyTimeout;
            ReadyFlags flags = ReadyFlags.ViaPublic;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode EventReady( /* FOR EventOps CLASS USE ONLY. */
            Interpreter interpreter,
            int timeout,
            ref Result error
            ) /* THREAD-SAFE */
        {
            ReadyFlags flags = ReadyFlags.ViaEventManager;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode TclReady( /* NOTE: FOR TclWrapper.DoOneEvent USE ONLY. */
            Interpreter interpreter,
            int timeout,
            ref Result error
            ) /* THREAD-SAFE */
        {
            ReadyFlags flags = ReadyFlags.ViaTclWrapper;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode EventReady( /* FOR Interpreter/EventManager CLASS USE ONLY. */
            Interpreter interpreter,
            bool noCancel,
            ref Result error
            ) /* THREAD-SAFE */
        {
            int timeout = DefaultReadyTimeout;
            ReadyFlags flags = ReadyFlags.ViaEventManager;

            if (noCancel)
                flags |= ReadyFlags.NoCancel;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode ParserReady( /* FOR Expression/Parser CLASS USE ONLY. */
            Interpreter interpreter,
            ref Result error
            ) /* THREAD-SAFE */
        {
            int timeout = DefaultReadyTimeout;
            ReadyFlags flags = ReadyFlags.ViaParser;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ReturnCode EngineReady( /* FOR Engine CLASS USE ONLY. */
            Interpreter interpreter,
            ReadyFlags flags,
            ref Result error
            ) /* THREAD-SAFE */
        {
            int timeout = DefaultReadyTimeout;

            flags |= ReadyFlags.ViaEngine;

            if (!FlagOps.HasFlags(flags, ReadyFlags.Disabled, true) &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoFlags, true))
            {
                flags |= TryGetReadyFlags(interpreter, timeout);
            }

            return Ready(interpreter, timeout, flags, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode Ready( /* FOR "*Ready" METHOD USE ONLY. */
            Interpreter interpreter,
            int timeout,
            ReadyFlags flags,
            ref Result error
            ) /* THREAD-SAFE */
        {
            //
            // TODO: Insert any library-wide readiness checks here.
            //
            if (interpreter == null)
            {
                error = "invalid interpreter";
                return ReturnCode.Error;
            }

            ///////////////////////////////////////////////////////////////////
            //
            // NOTE: Is readiness checking completely disabled?
            //
            if (FlagOps.HasFlags(flags, ReadyFlags.Disabled, true))
                return ReturnCode.Ok;

            int readyCount = interpreter.PrivateReadyCount++;

            ///////////////////////////////////////////////////////////////////
            //
            // NOTE: Skip all checks except for native stack space?
            //
            bool stackOnly = FlagOps.HasFlags(
                flags, ReadyFlags.StackOnly, true);

            //
            // NOTE: The return code from various methods.  This variable is
            //       reused several times.
            //
            ReturnCode code;

            ///////////////////////////////////////////////////////////////////
            //
            // BUGFIX: Do not use the public SyncRoot property here (in case we
            //         have been disposed), use the internal property instead.
            //
            bool locked = false;
            object syncRoot = interpreter.InternalSyncRoot;

            if (syncRoot == null)
            {
                error = "invalid interpreter synchronization object";
                return ReturnCode.Error;
            }

            try
            {
                //
                // BUGFIX: *THREADING* Allow the callers to specify a timeout
                //         to avoid potential deadlocks here in some cases.
                //
                locked = Monitor.TryEnter(syncRoot, timeout);

                if (!locked)
                {
                    //
                    // NOTE: We cannot check if the interpreter is actually
                    //       ready; therefore, return failure.
                    //
                    error = String.Format(
                        "interpreter readiness timeout of {0} milliseconds",
                        timeout);

                    return ReturnCode.Error;
                }

                //
                // NOTE: We absoutely cannot continue if the interpreter has
                //       been disposed because that means there will be no
                //       engine context, which is required for checking the
                //       native stack space, among other things.  This is
                //       always checked because using a disposed interpreter
                //       is considered to be a serious programming error.
                //
                if (interpreter.PrivateDisposed)
                {
                    error = "attempt to call eval in disposed interpreter";
                    return ReturnCode.Error;
                }

                ///////////////////////////////////////////////////////////////
                //
                // NOTE: Currently, the [exit] command (and the exit flag)
                //       in Eagle are more of a "suggestion" than anything
                //       else.  In fact, the exit flag may be unset via
                //       the IInterpreter property.
                //
                // FIXME: We may need to rethink this code.  If the exit
                //        flag has been set in the interpreter, does that
                //        mean cleanup code (e.g. finally blocks, etc)
                //        should also be skipped?
                //
                // NOTE: *COMPAT* This is one place where we do NOT follow
                //       (nor will we ever follow) native Tcl "standard"
                //       default behavior of unceremoniously exiting the
                //       entire process upon a script executing the [exit]
                //       command.
                //
                if (!stackOnly)
                {
                    //
                    // NOTE: Are we limiting the number of [full] readiness
                    //       checks?
                    //
                    if (FlagOps.HasFlags(flags, ReadyFlags.Limited, true))
                    {
                        //
                        // NOTE: In this context, the return code of Ok
                        //       means that we should continue checking
                        //       the readiness as normal [and not exit
                        //       prematurely].
                        //
                        code = ReturnCode.Ok;

                        //
                        // NOTE: Grab the ready limit for the interpreter.
                        //
                        int readyLimit = interpreter.PrivateReadyLimit;

                        //
                        // NOTE: If it is less than zero, assume that the
                        //       interpreter is always "ready".
                        //
                        if (readyLimit < 0)
                        {
                            code = ReturnCode.Error;
                            goto done;
                        }

                        //
                        // NOTE: Otherwise, if it is greater than zero, check
                        //       to see if the readiness count is a multiple
                        //       of the readiness limit.  If so, it is time
                        //       for a periodic [full] readiness check.
                        //
                        if (readyLimit > 0)
                        {
                            if ((readyCount % readyLimit) != 0)
                            {
                                code = ReturnCode.Error;
                                goto done;
                            }
                        }

                    done:

                        //
                        // NOTE: If the return code is not Ok, we need
                        //       to exit prematurely now because we are
                        //       assuming that the interpreter is always
                        //       "ready".
                        //
                        if (code != ReturnCode.Ok)
                        {
                            //
                            // BUGBUG: Unfortunately, we must reset the script
                            //         cancellation flag here; otherwise, the
                            //         next readiness check may fail due to a
                            //         "stale" script cancellation request.
                            //         It should be noted that the unwind flag
                            //         is purposely *NOT* being reset here
                            //         because it must be semantically "sticky"
                            //         until the evaluation stack for the
                            //         interpreter is completely unwound.
                            //
                            interpreter.ResetCancel(false);
                            return ReturnCode.Ok;
                        }
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: If the interpreter is marked as "exited", it is
                    //       technically [from the perspective of resource
                    //       disposal] still in a usable state.
                    //
                    if (interpreter.PrivateExit &&
                        !FlagOps.HasFlags(flags, ReadyFlags.ExitedOk, true))
                    {
                        error = "attempt to call eval in exited interpreter";
                        return ReturnCode.Error;
                    }

                    ///////////////////////////////////////////////////////////
                    //
                    // NOTE: If the interpreter is marked as "deleted", it is
                    //       technically [from the perspective of resource
                    //       disposal] still in a usable state.  This flag is
                    //       currently only used while the interpreter is
                    //       actively being disposed.
                    //
                    if (interpreter.PrivateDeleted &&
                        !FlagOps.HasFlags(flags, ReadyFlags.DeletedOk, true))
                    {
                        /* COMPAT: Tcl. */
                        error = "attempt to call eval in deleted interpreter";
                        return ReturnCode.Error;
                    }
                }

                ///////////////////////////////////////////////////////////////
                //
                // NOTE: Fetch the current script, parser, and expression
                //       nesting levels.  If this call fails, bail out now.
                //
                int levels = 0;
                int parserLevels = 0;
                int expressionLevels = 0;

                code = interpreter.GetReadyLevels(
                    ref levels, ref parserLevels, ref expressionLevels,
                    ref error);

                if (code != ReturnCode.Ok)
                    return code;

#if NATIVE && WINDOWS
                ///////////////////////////////////////////////////////////////
                //
                // NOTE: Checking native stack space is relatively "expensive";
                //       therefore, only perform this check if there are actual
                //       evaluations or expressions active AND it was requested
                //       by the caller.
                //
                if (FlagOps.HasFlags(flags, ReadyFlags.CheckStack, true) &&
                    (FlagOps.HasFlags(flags, ReadyFlags.ForceStack, true) ||
                    (levels > NoStackLevels) ||
                    (parserLevels > NoStackParserLevels) ||
                    (expressionLevels > NoStackExpressionLevels)))
                {
                    //
                    // NOTE: Ok, make sure that we are not running out of
                    //       native stack space.  If we cannot check native
                    //       stack space, this will simply return "success".
                    //
                    code = RuntimeOps.CheckForStackSpace(
                        interpreter, Engine.GetExtraStackSpace());

                    if (code != ReturnCode.Ok)
                    {
                        //
                        // HACK: Set the stack overflow flag so that the
                        //       engine can "quickly" unwind the evaluation
                        //       stack.
                        //
                        interpreter.StackOverflow = true;

                        TraceOps.DebugTrace(String.Format(
                            "{0}: Ready: out of stack space, flags = {1}, " +
                            "levels = {2}, parserLevels = {3}, " +
                            "expressionLevels = {4}{5}",
                            GlobalState.GetCurrentThreadId(), flags, levels,
                            parserLevels, expressionLevels,
                            Environment.NewLine), typeof(Interpreter).Name);

                        /* COMPAT: Tcl. */
                        error = "out of stack space (infinite loop?)";
                        return code;
                    }
                }
#endif

                ///////////////////////////////////////////////////////////////
                //
                // NOTE: If we only care about native stack checking, skip
                //       recursion limit checking.
                //
                if (!stackOnly)
                {
                    //
                    // NOTE: Make sure that we have not exceeded the
                    //       recursion limit.
                    //
                    int recursionLimit = interpreter.PrivateRecursionLimit;

                    if ((recursionLimit > 0) && (levels > recursionLimit))
                    {
                        //
                        // HACK: Set the stack overflow flag so that the
                        //       engine can "quickly" unwind the evaluation
                        //       stack.
                        //
                        interpreter.StackOverflow = true;

                        TraceOps.DebugTrace(String.Format(
                            "{0}: Ready: too many nested evaluations, " +
                            "flags = {1}, levels = {2}, parserLevels = {3}, " +
                            "expressionLevels = {4}{5}",
                            GlobalState.GetCurrentThreadId(), flags, levels,
                            parserLevels, expressionLevels,
                            Environment.NewLine), typeof(Interpreter).Name);

                        /* COMPAT: Tcl. */
                        error = "too many nested evaluations (infinite loop?)";
                        return ReturnCode.Error;
                    }
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);

                error = e;
                return ReturnCode.Error;
            }
            finally
            {
                if (locked)
                    Monitor.Exit(syncRoot);
            }

            ///////////////////////////////////////////////////////////////////
            //
            // NOTE: If we only care about native stack checking, skip script
            //       cancellation checking.  Also skip it if requested to do
            //       so by our caller.
            //
            if (!stackOnly &&
                !FlagOps.HasFlags(flags, ReadyFlags.NoCancel, true))
            {
                //
                // NOTE: These may need to be treated as totally separate
                //       checks at some point, depending on where calls to
                //       ResetCancel and ResetHalt are present.
                //
                // BUGFIX: Do *NOT* do this while holding the interpreter
                //         synchronization lock.
                //
                code = Engine.IsCanceled(interpreter, true, ref error);

                if (code != ReturnCode.Ok)
                    return code;

                code = Engine.IsHalted(interpreter, true, ref error);

                if (code != ReturnCode.Ok)
                    return code;
            }

            ///////////////////////////////////////////////////////////////////
            //
            // NOTE: If we get this far, everything we checked is considered
            //       to be "ready".
            //
            return ReturnCode.Ok;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Script Location Support
        private bool ShouldPushScriptLocation(
            bool viaSource
            )
        {
            if (FlagOps.HasFlags(interpreterFlags, /* NOTE: Track all? */
                    InterpreterFlags.ScriptLocation, true))
            {
                return true;
            }

            return viaSource;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool ShouldPopScriptLocation(
            bool viaSource
            )
        {
            if (FlagOps.HasFlags(interpreterFlags, /* NOTE: Track all? */
                    InterpreterFlags.ScriptLocation, true))
            {
                return true;
            }

            return viaSource;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushScriptLocation(
            string fileName,
            bool viaSource
            )
        {
            PushScriptLocation(fileName,
                Parser.StartLine, Parser.UnknownLine, viaSource);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void PushScriptLocation(
            string fileName,
            int startLine,
            int endLine,
            bool viaSource
            )
        {
            //
            // HACK: Avoid allocating a ScriptLocation object that we will just
            //       end up throwing away.
            //
            if (!ShouldPushScriptLocation(viaSource))
                return;

            PushScriptLocation(_Public.ScriptLocation.Create(this,
                fileName, startLine, endLine, viaSource));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void PushScriptLocation(
            IScriptLocation location
            )
        {
            bool viaSource = EntityOps.IsViaSource(location);

            if (!ShouldPushScriptLocation(viaSource))
                return;

            //
            // NOTE: This lock is not necessary when we are compiled with
            //       the THREADING option enabled because ScriptLocation
            //       and ScriptLocations are per-thread values in that
            //       case.
            //
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Undo any previous manual override.
                //
                ScriptLocation = null;
                ScriptLocations.Push(location);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PopScriptLocation(
            IScriptLocation location
            )
        {
            PopScriptLocation(EntityOps.IsViaSource(location));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PopScriptLocation(
            bool viaSource
            )
        {
            //
            // BUGFIX: Skip popping the script location if the interpreter
            //         has been disposed (i.e. no more engine context).
            //
            if (disposed || !ShouldPopScriptLocation(viaSource))
                return;

            //
            // NOTE: This lock is not necessary when we are compiled with
            //       the THREADING option enabled because ScriptLocations
            //       is a per-thread value in that case.
            //
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                ScriptLocations.Pop();
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool HasErrorInProgress()
        {
            //
            // WARNING: Possibly per-thread engine flags used here,
            //          MUST use property, not field.
            //
            return Engine.HasErrorInProgress(EngineFlags);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool CleanupArraySearches(IVariable variable)
        {
            int removed = 0;

            return CleanupArraySearches(variable, ref removed);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool CleanupArraySearches(
            IVariable variable,
            ref int removed
            )
        {
            if (variable != null)
            {
                ArraySearchDictionary arraySearches = ArraySearches;

                if (arraySearches != null)
                {
                    //
                    // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
                    //       from the objects collection in the containing interpreter.
                    //
                    StringList keys = new StringList();

                    foreach (KeyValuePair<string, ArraySearch> pair in arraySearches)
                        if (pair.Value != null)
                            if (Object.ReferenceEquals(pair.Value.Variable, variable))
                                keys.Add(pair.Key);

                    //
                    // NOTE: Cleanup, PASS #2, remove all the objects we found from PASS
                    //       #1 (above).
                    //
                    foreach (string key in keys)
                        LogicOps.Y(arraySearches.Remove(key), removed++);

                    return true;
                }
            }

            return false;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Interactive Context Members
        internal int InteractiveLoops
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    return context.InteractiveLoops;
                else
                    return 0;
#else
                lock (syncRoot)
                {
                    return interactiveLoops;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IInteractiveContext context = (contextManager != null) ?
                    contextManager.GetInteractiveContext(true) : null;

                if (context != null)
                    context.InteractiveLoops = value;
#else
                lock (syncRoot)
                {
                    interactiveLoops = value;
                }
#endif

                if (IsPrimaryThread())
                {
                    //
                    // NOTE: Do not create the variable if we have been prohibited
                    //       from doing so.
                    //
                    VariableFlags flags = VariableFlags.ViaProperty;

                    if (FlagOps.HasFlags(createFlags, CreateFlags.Safe, true) ||
                        FlagOps.HasFlags(createFlags, CreateFlags.NoVariables, true))
                    {
                        flags |= VariableFlags.NoCreate;
                    }

                    //
                    // NOTE: Update script-level informational variable.
                    //
                    SetLibraryVariableValue(
                        flags, TclVars.InteractiveLoops, value.ToString());
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Test Context Members
        internal int[] TestStatistics
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Statistics;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testStatistics;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Statistics = value;
#else
                lock (syncRoot)
                {
                    testStatistics = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList TestConstraints
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Constraints;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testConstraints;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Constraints = value;
#else
                lock (syncRoot)
                {
                    testConstraints = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList TestSkipped
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Skipped;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testSkipped;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Skipped = value;
#else
                lock (syncRoot)
                {
                    testSkipped = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList TestFailures
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Failures;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testFailures;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Failures = value;
#else
                lock (syncRoot)
                {
                    testFailures = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal IntDictionary TestCounts
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Counts;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testCounts;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Counts = value;
#else
                lock (syncRoot)
                {
                    testCounts = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList TestMatch
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Match;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testMatch;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Match = value;
#else
                lock (syncRoot)
                {
                    testMatch = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringList TestSkip
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Skip;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testSkip;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Skip = value;
#else
                lock (syncRoot)
                {
                    testSkip = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCodeDictionary TestReturnCodeMessages
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.ReturnCodeMessages;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testReturnCodeMessages;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.ReturnCodeMessages = value;
#else
                lock (syncRoot)
                {
                    testReturnCodeMessages = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER
        internal StringDictionary TestBreakpoints
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Breakpoints;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testBreakpoints;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Breakpoints = value;
#else
                lock (syncRoot)
                {
                    testBreakpoints = value;
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal string TestPath
        {
            get
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    return context.Path;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return testPath;
                }
#endif
            }
            set
            {
#if THREADING
                ITestContext context = (contextManager != null) ?
                    contextManager.GetTestContext(true) : null;

                if (context != null)
                    context.Path = value;
#else
                lock (syncRoot)
                {
                    testPath = value;
                }
#endif
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Variable Context Members
        internal CallStack CallStack /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.CallStack;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return callStack;
                }
#endif
            }
            private set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.CallStack = value;
#else
                lock (syncRoot)
                {
                    callStack = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame GlobalFrame /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.GlobalFrame;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return globalFrame;
                }
#endif
            }
            private set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.GlobalFrame = value;
#else
                lock (syncRoot)
                {
                    globalFrame = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame CurrentFrame /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.CurrentFrame;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return currentFrame;
                }
#endif
            }
            private set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.CurrentFrame = value;
#else
                lock (syncRoot)
                {
                    currentFrame = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame ProcedureFrame /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.ProcedureFrame;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return procedureFrame;
                }
#endif
            }
            /* internal */
            set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.ProcedureFrame = value;
#else
                lock (syncRoot)
                {
                    procedureFrame = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame UplevelFrame /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.UplevelFrame;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return uplevelFrame;
                }
#endif
            }
            /* internal */
            set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.UplevelFrame = value;
#else
                lock (syncRoot)
                {
                    uplevelFrame = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ITraceInfo TraceInfo /* THREAD-SAFE */
        {
            get
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    return context.TraceInfo;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return traceInfo;
                }
#endif
            }
            set
            {
#if THREADING
                IVariableContext context = (contextManager != null) ?
                    contextManager.GetVariableContext(true) : null;

                if (context != null)
                    context.TraceInfo = value;
#else
                lock (syncRoot)
                {
                    traceInfo = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private IClientData CurrentResolveData
        {
            get
            {
#if !THREADING
                lock (syncRoot)
#endif
                {
                    ICallFrame frame = CurrentFrame;

                    return (frame != null) ? frame.ResolveData : null;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: This property is always the global call frame; however,
        //          it is intended for use by the ContextManager class only.
        //          Please use the "GlobalFrame" property instead.  Assumes
        //          interpreter lock is held.
        //
        internal ICallFrame InternalGlobalFrame
        {
            get { return globalFrame; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // WARNING: Assumes interpreter lock is held.
        //
        internal bool CreateGlobalFrame(
            CallStack callStack
            )
        {
            if (globalFrame == null)
            {
                globalFrame = NewGlobalCallFrame(callStack);
                return false; /* NOTE: It was not already there. */
            }

            return true; /* NOTE: It was already there. */
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallFrame Management
        internal bool IsCallFrameInCallStack(ICallFrame frame)
        {
#if !THREADING
            lock (syncRoot)
#endif
            {
                if (CallStack != null)
                    return CallStack.Contains(frame);
                else
                    return false;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsVariableCallFrame(ICallFrame frame)
        {
            if (!CallFrameOps.IsVariable(frame))
                return false;

            ICallFrame variableFrame = frame;

            if (GetVariableFrameViaResolvers(
                    LookupFlags.Default,
                    ref variableFrame) != ReturnCode.Ok)
            {
                return false;
            }

            return CallFrameOps.IsSame(frame, variableFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsGlobalCallFrame(ICallFrame frame)
        {
            return CallFrameOps.IsSame(frame, GlobalFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsCurrentCallFrame(ICallFrame frame)
        {
            return CallFrameOps.IsSame(frame, CurrentFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsNamespaceCallFrame(ICallFrame frame)
        {
            return CallFrameOps.IsNamespace(frame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsProcedureCallFrame(ICallFrame frame)
        {
            return CallFrameOps.IsSame(frame, ProcedureFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsUplevelCallFrame(ICallFrame frame)
        {
            return CallFrameOps.IsSame(frame, UplevelFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame GetProcedureFrame() /* CANNOT RETURN NULL */
        {
#if !THREADING
            lock (syncRoot)
#endif
            {
                ICallFrame frame = ProcedureFrame;

                return (frame != null) ? frame : GlobalFrame;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame GetUplevelFrame() /* CANNOT RETURN NULL */
        {
#if !THREADING
            lock (syncRoot)
#endif
            {
                ICallFrame frame = UplevelFrame;

                return (frame != null) ? frame : CurrentFrame;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame GetVariableFrame(
            ICallFrame frame,
            ref string varName,
            ref VariableFlags flags
            ) /* CANNOT RETURN NULL */
        {
            EntityOps.GetFlags(ref varName, ref flags);

            return GetVariableFrame(frame, flags);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame GetVariableFrame( // TODO: Replace uses of me.
            ICallFrame frame,
            VariableFlags flags
            ) /* CANNOT RETURN NULL */
        {
            ICallFrame variableFrame;

#if !THREADING
            lock (syncRoot)
#endif
            {
                if (FlagOps.HasFlags(flags, VariableFlags.GlobalOnly, true))
                {
                    variableFrame = GlobalFrame;
                }
                else
                {
                    if (frame != null)
                        variableFrame = CallFrameOps.FollowNext(frame);
                    else
                        variableFrame = CallFrameOps.FollowNext(CurrentFrame);

                    if (variableFrame == null)
                        variableFrame = GlobalFrame;
                }
            }

            return variableFrame;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void GetInfoLevelFlagsAndFrame(
            string subCommand,
            ref CallFrameFlags flags,
            ref ICallFrame frame
            ) /* HACK */
        {
            flags |= CallFrameFlags.Invisible;
            frame = CurrentFrame;

            //
            // NOTE: If we are not performing work for the generic
            //       "level" sub-command then always allow invisible
            //       call frames to be seen; otherwise, only allow
            //       invisible call frames to be seen if we are within
            //       a call frame that has the appropriate flag set.
            //
            if ((subCommand != null) && !String.Equals(
                    subCommand, CallFrameOps.InfoLevelSubCommand,
                    StringOps.SystemStringComparisonType) ||
                CallFrameOps.Find(CallStack, frame, false, 0,
                    CallFrameFlags.NoInvisible, CallFrameFlags.None,
                    false, false) == ReturnCode.Ok)
            {
                flags &= ~CallFrameFlags.Invisible;
                frame = CallFrameOps.FollowNext(frame);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal CallFrameFlags GetInfoLevelCallFrameFlags()
        {
            CallFrameFlags result = CallFrameFlags.InfoLevel;

            if (!AreNamespacesEnabled())
                result &= ~CallFrameFlags.Namespace;

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetInfoLevel(
            string subCommand,
            ref int level,
            ref Result error
            )
        {
            //
            // HACK: Allow, through the usage of "##<integer>" notation,
            //       traversal of all call frames, including invisible
            //       ones.  This feature is not supported by Tcl.
            //
            CallFrameFlags notHasFlags = CallFrameFlags.None;
            ICallFrame currentFrame = null;

            GetInfoLevelFlagsAndFrame(
                subCommand, ref notHasFlags, ref currentFrame);

            if ((currentFrame != null) &&
                currentFrame.HasFlags(CallFrameFlags.Downlevel, true))
            {
                level = (int)currentFrame.FrameLevel;
                return ReturnCode.Ok;
            }

            return CallFrameOps.Count(CallStack, currentFrame,
                GetInfoLevelCallFrameFlags(), notHasFlags, false,
                false, ref level, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetInfoLevelArguments(
            string subCommand,
            string text,
            int level,
            ref Result result
            )
        {
            //
            // HACK: Allow, through the usage of "##<integer>" notation,
            //       traversal of all call frames, including invisible
            //       ones.  This feature is not supported by Tcl.
            //
            CallFrameFlags notHasFlags = CallFrameFlags.NoVariables;
            ICallFrame currentFrame = null;

            GetInfoLevelFlagsAndFrame(
                subCommand, ref notHasFlags, ref currentFrame);

            if ((currentFrame != null) &&
                currentFrame.HasFlags(CallFrameFlags.Downlevel, true))
            {
                ICallFrame uplevelFrame = GetUplevelFrame();

                if ((uplevelFrame != null) && (uplevelFrame.Arguments != null))
                {
                    result = uplevelFrame.Arguments.ToString();
                    return ReturnCode.Ok;
                }
            }

            ReturnCode code;
            ICallFrame frame = null;

            code = CallFrameOps.GetOrFind(
                CallStack, GlobalFrame, currentFrame, (level > 0),
                Math.Abs(level), CallFrameFlags.Variables, notHasFlags,
                false, false, ref frame, ref result);

            if ((code == ReturnCode.Ok) &&
                (frame != null) && (frame.Arguments != null))
            {
                result = frame.Arguments.ToString();
            }
            else
            {
                result = String.Format("bad level \"{0}\"", text);
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Peek / Push / Pop
        #region Peek
        internal bool CanPeekCallFrame()
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                CallStack callStack = CallStack;
                return ((callStack != null) && (callStack.Count > 0));
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PeekCallFrame()
        {
#if !THREADING
            lock (syncRoot)
#endif
            {
                return CallFrameOps.Peek(CallStack);
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Push
        internal void PushCallFrame(
            ICallFrame newFrame
            )
        {
            PushCallFrame(newFrame, false);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushAutomaticCallFrame(
            ICallFrame newFrame
            )
        {
            PushCallFrame(newFrame, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void PushCallFrame(
            ICallFrame newFrame,
            bool automatic
            )
        {
            ICallFrame frame = null;

#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Push the call frame.
                //
                CallFrameOps.Push(CallStack, newFrame, ref frame);

                //
                // NOTE: Flag the call frame as 'automatic', if necessary.
                //
                if (automatic && (frame != null))
                    frame.Flags |= CallFrameFlags.Automatic;

                //
                // NOTE: Set the current call frame to the one we just pushed.
                //
                CurrentFrame = frame;
            }

#if NOTIFY
            /* IGNORED */
            CheckNotifications(
                NotifyType.CallFrame, NotifyFlags.Pushed,
                newFrame, this,
                null, null, null);
#endif
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Pop
        internal ICallFrame PopCallFrame()
        {
            ICallFrame popFrame = null;
            ICallFrame frame = null;

#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Pop the call frame.
                //
                popFrame = CallFrameOps.Pop(CallStack, ref frame);

                //
                // NOTE: Set the current call frame to the one we just popped.
                //
                CurrentFrame = frame;
            }

#if NOTIFY || NOTIFY_OBJECT
            /* IGNORED */
            CheckNotifications(
                NotifyType.CallFrame, NotifyFlags.Popped,
                popFrame, this,
                null, null, null);
#endif

            return popFrame;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PopCallFrame(
            CallFrameFlags hasFlags,
            bool all
            )
        {
            ICallFrame newFrame = PopCallFrames(hasFlags, 0, all);

            if (newFrame != null)
                newFrame = PopCallFrame();

            return newFrame;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PopCallFrames(
            CallFrameFlags hasFlags,
            int limit,
            bool all
            )
        {
            ICallFrame newFrame = null;

#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                int count = 0;
                bool done = false;

                do
                {
                    //
                    // NOTE: Examine the current call frame without popping it.
                    //       Upon returning from this method, returning a valid
                    //       call frame will cause that call frame to be popped.
                    //
                    newFrame = PeekCallFrame();

                    if ((newFrame != null) &&
                        FlagOps.HasFlags(newFrame.Flags, hasFlags, all))
                    {
                        //
                        // NOTE: The current call frame does match the flags
                        //       provided by the caller, pop it now.
                        //
                        /* IGNORED */
                        PopCallFrame(); count++;

                        //
                        // NOTE: Have we reached the limit for the number of
                        //       matching call frames to pop?  If the limit is
                        //       zero or negative, there is no limit.
                        //
                        if ((limit > 0) && (count >= limit))
                            done = true;
                    }
                    else
                    {
                        done = true;
                    }
                }
                while (!done);
            }

            return newFrame;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Global (Engine)
        internal void PushGlobalCallFrame(
            bool mark
            )
        {
            PushGlobalCallFrame(mark, false);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushGlobalCallFrame(
            bool mark,
            bool automatic
            )
        {
            if (mark)
            {
                //
                // BUGFIX: When pushing the global call frame from the engine we
                //         must make sure this is treated just like [uplevel #0]
                //         (i.e. the other call frames must be marked as invisible
                //         for [info level], etc to work properly).
                //
                ReturnCode code;
                Result error = null;

                code = CallFrameOps.MarkMatching(
                    CallStack, CurrentFrame, true, 0, CallFrameFlags.Variables,
                    CallFrameFlags.Invisible | CallFrameFlags.NoVariables,
                    CallFrameFlags.Invisible, false, false, true, ref error);

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error); // BUGBUG: Panic!

                ICallFrame frame = NewLinkedCallFrame(
                    "global (engine)", 0, CallFrameFlags.Uplevel,
                    CurrentResolveData, null, null, GlobalFrame);

                PushCallFrame(frame, automatic);

                // PushCallFrame(GlobalFrame, automatic);
            }
            else
            {
                PushCallFrame(GlobalFrame, automatic);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PopGlobalCallFrame(
            bool mark
            )
        {
            /* IGNORED */
            PopCallFrame(CallFrameFlags.Scope, true);

            if (mark)
            {
                ReturnCode code;
                Result error = null;

                code = CallFrameOps.MarkMatching(
                    CallStack, CurrentFrame, true, 0, CallFrameFlags.Variables,
                    CallFrameFlags.NoVariables, CallFrameFlags.Invisible, false,
                    false, false, ref error);

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error); // BUGBUG: Panic!
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace (Core)
        #region Dead Code
#if DEAD_CODE
        internal void PushCurrentNamespace(
            INamespace @namespace,
            ref INamespace savedNamespace
            )
        {
            savedNamespace = NamespaceOps.GetCurrent(this, null);
            NamespaceOps.SetCurrent(this, null, @namespace);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal INamespace PopCurrentNamespace(
            ref INamespace savedNamespace
            )
        {
            INamespace @namespace = NamespaceOps.GetCurrent(this, null);
            NamespaceOps.SetCurrent(this, null, savedNamespace);
            savedNamespace = null;
            return @namespace;
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void EnterNamespaceCallFrame(
            ICallFrame newFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Increase the reference count for the namespace that
                //       is associated with the call frame.
                //
                if (newFrame != null)
                {
                    INamespace @namespace = NamespaceOps.GetCurrent(
                        this, newFrame);

                    if (@namespace != null)
                    {
                        /* IGNORED */
                        @namespace.Enter(true);
                    }
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void ExitNamespaceCallFrame(
            ICallFrame newFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Decrease the reference count for the namespace that
                //       is associated with the call frame.
                //
                if (newFrame != null)
                {
                    INamespace @namespace = NamespaceOps.GetCurrent(
                        this, newFrame);

                    if (@namespace != null)
                    {
                        /* IGNORED */
                        @namespace.Exit(true);

                        if (@namespace.Deleted &&
                            CanDeleteNamespace(@namespace) &&
                            !IsGlobalNamespace(@namespace))
                        {
                            ReturnCode deleteCode;
                            Result deleteResult = null;

                            deleteCode = DeleteNamespace(
                                VariableFlags.None, @namespace, false,
                                ref deleteResult);

                            if (deleteCode != ReturnCode.Ok)
                                DebugOps.Complain(this, deleteCode, deleteResult);
                        }
                    }
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushNamespaceCallFrame(
            ICallFrame newFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: For now, just push the call frame as 'automatic'.
                //
                PushAutomaticCallFrame(newFrame);

                //
                // NOTE: Increase the reference count for the namespace that
                //       is associated with the call frame.
                //
                EnterNamespaceCallFrame(newFrame);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PopNamespaceCallFrame(
            ICallFrame newFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Decrease the reference count for the namespace that
                //       is associated with the call frame.
                //
                ExitNamespaceCallFrame(newFrame);

                //
                // NOTE: Cleanup any leftover open scopes from the procedure.
                //       We MUST do this here because otherwise the pop below
                //       will fail to pop the procedure call frame from the
                //       stack, thereby permanently unbalancing it.
                //
                return PopCallFrame(CallFrameFlags.Scope, true);
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Procedure (Core)
        internal void EnterProcedureCallFrame(
            ICallFrame newFrame,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                savedFrame = ProcedureFrame; // save the current procedure call frame.
                ProcedureFrame = newFrame;   // set the new procecure call frame.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void ExitProcedureCallFrame(
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                ProcedureFrame = savedFrame; // restore the saved procedure call frame.
                savedFrame = null;           // reset the saved procedure call frame.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushProcedureCallFrame(
            ICallFrame newFrame,
            bool automatic,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Push the new procedure call frame, thereby making it
                //       the current call frame.
                //
                PushCallFrame(newFrame, automatic);

                //
                // NOTE: If necessary, enter the namespace context.
                //
                if (AreNamespacesEnabled())
                    EnterNamespaceCallFrame(newFrame);

                //
                // NOTE: Save the current procedure call frame and enter the
                //       new procedure call frame.
                //
                EnterProcedureCallFrame(newFrame, ref savedFrame);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PopProcedureCallFrame(
            ICallFrame newFrame,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Cleanup any leftover open scopes from the procedure.
                //       We MUST do this here because otherwise the pop below
                //       will fail to pop the procedure call frame from the
                //       stack, thereby permanently unbalancing it.
                //
                /* IGNORED */
                PopCallFrames(CallFrameFlags.Scope, 0, true);

                //
                // NOTE: Exit the current procedure call frame and restore
                //       the procedure call frame saved earlier.
                //
                ExitProcedureCallFrame(ref savedFrame);

                //
                // NOTE: If necessary, exit the namespace context.
                //
                if (AreNamespacesEnabled())
                    ExitNamespaceCallFrame(newFrame);

                //
                // NOTE: Grab the current call frame so that we can clean it
                //       up (i.e. remove undefined variables).
                //
                ICallFrame currentFrame = CurrentFrame;

                //
                // NOTE: Cleanup the current call frame (i.e. the procedure
                //       call frame).
                //
                /* IGNORED */
                CallFrameOps.Cleanup(currentFrame, newFrame, false);

                //
                // NOTE: Now pop the top call frame, which should be the
                //       procedure call frame.
                //
                ICallFrame popFrame = PopCallFrame();

                //
                // NOTE: Cleanup the call frame and mark it as undefined.
                //
                /* IGNORED */
                CallFrameOps.Cleanup(currentFrame, popFrame, true);

                //
                // NOTE: Return the call frame we just popped.
                //
                return popFrame;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Uplevel (Core)
        internal void EnterUplevelCallFrame(
            ICallFrame newFrame,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                savedFrame = UplevelFrame; // save the current uplevel call frame.
                UplevelFrame = newFrame;   // set the new uplevel call frame.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void ExitUplevelCallFrame(
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                UplevelFrame = savedFrame; // restore the saved uplevel call frame.
                savedFrame = null;           // reset the saved uplevel call frame.
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void PushUplevelCallFrame(
            ICallFrame oldFrame,
            ICallFrame newFrame,
            bool automatic,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Push the new uplevel call frame, thereby making it
                //       the current call frame.
                //
                PushCallFrame(newFrame, automatic);

                //
                // NOTE: Link the newly created [uplevel] call frame to the
                //       current frame provided by the caller.  This will help
                //       later when the [info level] sub-command is used from
                //       a [downlevel] call frame.
                //
                if (oldFrame != null)
                    oldFrame.Other = newFrame;

                //
                // NOTE: Save the current uplevel call frame and enter the
                //       new uplevel call frame.
                //
                EnterUplevelCallFrame(oldFrame, ref savedFrame);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame PopUplevelCallFrame(
            ICallFrame oldFrame,
            ICallFrame newFrame,
            ref ICallFrame savedFrame
            )
        {
#if !THREADING
            lock (syncRoot) /* TRANSACTIONAL */
#endif
            {
                //
                // NOTE: Cleanup any leftover open scopes from the uplevel.
                //       We MUST do this here because otherwise the pop below
                //       will fail to pop the uplevel call frame from the
                //       stack, thereby permanently unbalancing it.
                //
                /* IGNORED */
                PopCallFrames(CallFrameFlags.Scope, 0, true);

                //
                // NOTE: Exit the current uplevel call frame and restore
                //       the uplevel call frame saved earlier.
                //
                ExitUplevelCallFrame(ref savedFrame);

                //
                // NOTE: Now unlink the [uplevel] call frame from the old call
                //       frame (i.e. the one that was the current call frame
                //       prior to the [uplevel] call frame being pushed).
                //
                if (oldFrame != null)
                    oldFrame.Other = null;

                //
                // NOTE: Now pop the top call frame, which should be the
                //       uplevel call frame.
                //
                ICallFrame popFrame = PopCallFrame();

                //
                // NOTE: Return the call frame we just popped.
                //
                return popFrame;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Automatic (Engine)
        internal static bool ShouldPopAutomaticCallFrame(
            Interpreter interpreter,
            ICallFrame oldFrame
            )
        {
            if (interpreter == null)
                return false;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return false;

                if (oldFrame == null)
                    return false;

                if (!interpreter.CanPeekCallFrame())
                    return false;

                return !Object.ReferenceEquals(oldFrame, interpreter.PeekCallFrame());
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static ICallFrame PopAutomaticCallFrame(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return null;

            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                if (interpreter.PrivateDisposed)
                    return null;

                //
                // NOTE: Cleanup any leftover open scopes from the procedure.  We
                //       MUST do this here because otherwise the pop below will
                //       fail to pop the procedure call frame from the stack,
                //       thereby permanently unbalancing it.
                //
                /* IGNORED */
                interpreter.PopCallFrames(CallFrameFlags.Scope, 0, true);

                //
                // NOTE: If the top of the call stack is an automatic call frame,
                //       that means it was not cleaned up by the code associated
                //       with originally pushing it.  In that case, pop it now;
                //       however, make sure that a maximum of one such call frame
                //       is popped.
                //
                ICallFrame popFrame = interpreter.PopCallFrames(
                    CallFrameFlags.Automatic, 1, true);

                //
                // NOTE: If the current procedure call frame was just popped, then
                //       it must be reset it as well.
                //
                if (Object.ReferenceEquals(popFrame, interpreter.ProcedureFrame))
                    interpreter.ProcedureFrame = null;

                //
                // NOTE: If the current uplevel call frame was just popped, then
                //       it must be reset it as well.
                //
                if (Object.ReferenceEquals(popFrame, interpreter.UplevelFrame))
                    interpreter.UplevelFrame = null;

                //
                // NOTE: Always return the call frame that was just popped, if any.
                //
                return popFrame;
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallFrame (Scope)
        internal ReturnCode GetScopeCallFrame(
            string name,
            LookupFlags lookupFlags,
            bool pop,
            bool remove,
            ref ICallFrame frame
            )
        {
            Result error = null;

            return GetScopeCallFrame(name, lookupFlags, pop, remove, ref frame, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetScopeCallFrame(
            string name,
            LookupFlags lookupFlags,
            bool pop,
            bool remove,
            ref ICallFrame frame,
            ref Result error
            )
        {
            lock (syncRoot)
            {
                if (!HasScopes(ref error))
                    return ReturnCode.Error;

                //
                // NOTE: Grab the current call frame without popping it.
                //
                ICallFrame newFrame = PeekCallFrame();

                //
                // NOTE: We cannot follow linked call frames if we
                //       intend to pop the innermost scope call frame.
                //
                if (!pop)
                    newFrame = CallFrameOps.FollowNext(newFrame);

                //
                // NOTE: Is the current call frame valid?
                //
                if (newFrame == null)
                {
                    error = "invalid call frame";
                    return ReturnCode.Error;
                }

                //
                // NOTE: Is this a [scope] created persistent call frame (i.e.
                //       one that was created by [scope], but not by [scope
                //       eval]).
                //
                CallFrameFlags frameFlags = newFrame.Flags;

                if (!FlagOps.HasFlags(frameFlags, CallFrameFlags.Scope, true) ||
                    FlagOps.HasFlags(frameFlags, CallFrameFlags.Evaluate, true))
                {
                    error = "no scopes are open";
                    return ReturnCode.Error;
                }

                //
                // NOTE: Does the provided scope name, if any, match?
                //
                if ((name == null) || (String.Compare(newFrame.Name,
                        name, StringOps.SystemStringComparisonType) == 0))
                {
                    //
                    // NOTE: Pop the call frame from the call stack?
                    //
                    if (pop)
                        //
                        // NOTE: We know the call stack has not changed here
                        //       because we are holding the interpreter lock.
                        //
                        frame = PopCallFrame(); // return and remove it.
                    else
                        frame = newFrame; // just return it.

                    //
                    // NOTE: Remove the call frame from the interpreter?
                    //
                    if (remove)
                        scopes.Remove(newFrame.Name);

                    return ReturnCode.Ok;
                }
                else
                {
                    error = FlagOps.HasFlags(
                        lookupFlags, LookupFlags.Verbose, true) ?
                        String.Format(
                            "scope \"{0}\" is not innermost",
                            name) :
                        "scope is not innermost";

                    return ReturnCode.Error;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CopyProcedureArgumentsToFrame(
            ICallFrame frame,
            bool force,
            ref Result error
            )
        {
            ArgumentList frameArguments = null;

            lock (syncRoot)
            {
                ICallFrame procedureFrame = ProcedureFrame;

                //
                // NOTE: Steal the arguments from the containing procedure;
                //       otherwise, we cannot access them from the [scope].
                //
                if ((procedureFrame != null) &&
                    (procedureFrame.ProcedureArguments != null))
                {
                    frameArguments = new ArgumentList(
                        procedureFrame.ProcedureArguments);
                }
            }

            ReturnCode code = ReturnCode.Ok;

            if ((frame != null) && (frameArguments != null))
            {
                //
                // NOTE: Create variables for each of the formal arguments
                //       to the enclosing procedure.  Start the counting at
                //       one to skip the procedure name itself.
                //
                VariableDictionary variables = frame.Variables;

                for (int argumentIndex = 1;
                        argumentIndex < frameArguments.Count; argumentIndex++)
                {
                    string varName = frameArguments[argumentIndex].Name;

                    if (force || !variables.ContainsKey(varName))
                    {
                        string varValue = null;

                        if (frameArguments[argumentIndex].Value != null)
                            varValue = frameArguments[argumentIndex].Value.ToString();

                        code = SetVariableValue2(VariableFlags.Argument, frame,
                            varName, null, varValue, null, ref error);

                        if (code != ReturnCode.Ok)
                            break;
                    }
                }

                //
                // NOTE: Finally, update the arguments for the call frame so
                //       that things like [info level] will work properly.
                //
                if (code == ReturnCode.Ok)
                    frame.Arguments = frameArguments;
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ICallFrame (Factory)
        internal ICallFrame NewProcedureCallFrame(
            string name,
            CallFrameFlags flags,
            IExecute execute,
            ArgumentList arguments
            )
        {
            INamespace @namespace = null;

            if (AreNamespacesEnabled())
                @namespace = NamespaceOps.LookupParent(this, name, false, true, false);

            return NewProcedureCallFrame(name, flags, execute, arguments, @namespace);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ICallFrame NewProcedureCallFrame(
            string name,
            CallFrameFlags flags,
            IExecute execute,
            ArgumentList arguments,
            INamespace @namespace
            )
        {
            return new CallFrame(
                NextId(), 0, name, null, CallStack.Count + 1, Levels,
                flags, (@namespace != null) ? new ResolverClientData(
                @namespace) : CurrentResolveData, execute, arguments);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewNamespaceCallFrame(
            string name,
            CallFrameFlags flags,
            ArgumentList arguments
            )
        {
            return NewNamespaceCallFrame(name, flags, arguments, null, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewNamespaceCallFrame(
            string name,
            CallFrameFlags flags,
            ArgumentList arguments,
            INamespace @namespace,
            bool newVariables
            )
        {
            return new CallFrame(
                NextId(), 0, name, null, CallStack.Count + 1, Levels,
                flags | CallFrameFlags.Namespace, (@namespace != null) ?
                new ResolverClientData(@namespace) : CurrentResolveData,
                null, null, arguments, newVariables);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewNamespaceCallFrame(
            string name,
            CallFrameFlags flags,
            IExecute execute,
            ArgumentList arguments
            )
        {
            return new CallFrame(
                NextId(), 0, name, null, CallStack.Count + 1, Levels,
                flags | CallFrameFlags.Namespace, (globalNamespace != null) ?
                new ResolverClientData(globalNamespace) : CurrentResolveData,
                null, execute, arguments, false);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewTrackingCallFrame(
            string name,
            CallFrameFlags flags
            )
        {
            return NewTrackingCallFrame(name, flags, CurrentResolveData);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewTrackingCallFrame(
            string name,
            CallFrameFlags flags,
            IClientData resolveData
            )
        {
            return NewLinkedCallFrame(
                name, 0, flags | CallFrameFlags.Tracking, resolveData,
                null, null, CurrentFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewDownlevelCallFrame(
            string name
            )
        {
            long frameLevel = 0;
            ICallFrame nextFrame = GetUplevelFrame();

            if (nextFrame != null)
            {
                ICallFrame otherFrame = nextFrame.Other;

                if (otherFrame != null)
                    frameLevel = otherFrame.FrameLevel;
            }

            return NewLinkedCallFrame(
                name, frameLevel, CallFrameFlags.Downlevel,
                CurrentResolveData, null, CurrentFrame,
                nextFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewUplevelCallFrame(
            string name,
            long frameLevel,
            bool mark,
            ICallFrame previousFrame,
            ICallFrame nextFrame
            )
        {
            //
            // HACK: If we are not marking call frames as "invisible" then
            //       we must be in "view everything" mode; therefore, set
            //       the NoInvisible flag on this call frame so that it
            //       will be found by [info level], etc.
            //
            return NewLinkedCallFrame(
                name, frameLevel, CallFrameFlags.Uplevel | (mark ?
                CallFrameFlags.None : CallFrameFlags.NoInvisible),
                CurrentResolveData, null, previousFrame, nextFrame);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ICallFrame NewScopeCallFrame(
            string name,
            CallFrameFlags flags,
            VariableDictionary variables,
            ArgumentList arguments
            )
        {
            return new CallFrame(
                NextId(), 0, name, null, CallStack.Count + 1, Levels,
                flags, CurrentResolveData, variables, arguments);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ICallFrame NewGlobalCallFrame(
            CallStack callStack
            )
        {
            return new CallFrame(
                NextId(), 0, "global", null, callStack.Count + 1,
                Levels, CallFrameFlags.NoFree | CallFrameFlags.Global,
                null /* NOTE: DO NOT USE CurrentResolveData HERE. */,
                null, null, null, true);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ICallFrame NewLinkedCallFrame(
            string name,
            long frameLevel,
            CallFrameFlags flags,
            IClientData resolveData,
            ICallFrame otherFrame,
            ICallFrame previousFrame,
            ICallFrame nextFrame
            )
        {
            return new CallFrame(
                NextId(), frameLevel, name, null, CallStack.Count + 1,
                Levels, flags, resolveData, otherFrame, previousFrame,
                nextFrame);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Flags Management
        internal EventFlags AfterEventFlags /* FOR [after] USE ONLY */
        {
            get { lock (syncRoot) { return afterEventFlags; } }
            set { lock (syncRoot) { afterEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal CreateFlags CreateFlags
        {
            get { lock (syncRoot) { return createFlags; } }
            set { lock (syncRoot) { createFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EventFlags EngineEventFlags
        {
            get { lock (syncRoot) { return engineEventFlags; } }
            set { lock (syncRoot) { engineEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER || SHELL
        internal HeaderFlags HeaderFlags
        {
            get { lock (syncRoot) { return headerFlags; } }
            set { lock (syncRoot) { headerFlags = value; } }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL && INTERACTIVE_COMMANDS
        internal EngineFlags InteractiveEngineFlags
        {
            get { lock (syncRoot) { return interactiveEngineFlags; } }
            set { lock (syncRoot) { interactiveEngineFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EventFlags InteractiveEventFlags
        {
            get { lock (syncRoot) { return interactiveEventFlags; } }
            set { lock (syncRoot) { interactiveEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ExpressionFlags InteractiveExpressionFlags
        {
            get { lock (syncRoot) { return interactiveExpressionFlags; } }
            set { lock (syncRoot) { interactiveExpressionFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal SubstitutionFlags InteractiveSubstitutionFlags
        {
            get { lock (syncRoot) { return interactiveSubstitutionFlags; } }
            set { lock (syncRoot) { interactiveSubstitutionFlags = value; } }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal InterpreterFlags InterpreterFlags
        {
            get { lock (syncRoot) { return interpreterFlags; } }
            set { lock (syncRoot) { interpreterFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && NATIVE_UTILITY
        internal CreateFlags CreateFlagsNoLock
        {
            get { return createFlags; }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private InterpreterFlags PrivateInterpreterFlags
        {
            get { /* NO-LOCK */ return interpreterFlags; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReadyFlags PrivateReadyFlags
        {
            get { /* NO-LOCK */ return readyFlags; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ProcedureFlags ProcedureFlags /* FOR [proc] USE ONLY */
        {
            get { lock (syncRoot) { return procedureFlags; } }
            set { lock (syncRoot) { procedureFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal PluginFlags PluginFlags
        {
            get { lock (syncRoot) { return pluginFlags; } }
            set { lock (syncRoot) { pluginFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EventFlags QueueEventFlags
        {
            get { lock (syncRoot) { return queueEventFlags; } }
            private set { lock (syncRoot) { queueEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal SubstitutionFlags SubstitutionFlags
        {
            get { lock (syncRoot) { return substitutionFlags; } }
            set { lock (syncRoot) { substitutionFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ExpressionFlags ExpressionFlags
        {
            get { lock (syncRoot) { return expressionFlags; } }
            set { lock (syncRoot) { expressionFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal EventFlags UpdateEventFlags
        {
            get { lock (syncRoot) { return updateEventFlags; } }
            private set { lock (syncRoot) { updateEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Dead Code
#if DEAD_CODE
        internal EventFlags WaitEventFlags /* NOT USED */
        {
            get { lock (syncRoot) { return waitEventFlags; } }
            private set { lock (syncRoot) { waitEventFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal VariableFlags NewGlobalVariableFlags
        {
            get { lock (syncRoot) { return newGlobalVariableFlags; } }
            set { lock (syncRoot) { newGlobalVariableFlags = value; } }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal VariableFlags NewLocalVariableFlags
        {
            get { lock (syncRoot) { return newLocalVariableFlags; } }
            set { lock (syncRoot) { newLocalVariableFlags = value; } }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Ready Flags
        private static ReadyFlags TryGetReadyFlags(
            Interpreter interpreter,
            int timeout
            )
        {
            return TryGetReadyFlags(interpreter, timeout, ReadyFlags.Unknown);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReadyFlags TryGetReadyFlags(
            Interpreter interpreter,
            int timeout,
            ReadyFlags @default
            )
        {
            if (interpreter == null)
                return @default;

            ///////////////////////////////////////////////////////////////////
            //
            // BUGFIX: Do not use the public SyncRoot property here (in case we
            //         have been disposed), use the internal property instead.
            //
            bool locked = false;
            object syncRoot = interpreter.InternalSyncRoot;

            if (syncRoot == null)
                return @default;

            try
            {
                //
                // BUGFIX: *THREADING* Allow the callers to specify a timeout
                //         to avoid potential deadlocks here in some cases.
                //
                locked = Monitor.TryEnter(syncRoot, timeout);

                //
                // NOTE: We cannot check if the interpreter is actually ready;
                //       therefore, return failure.
                //
                if (!locked)
                    return @default;

                //
                // NOTE: We absoutely cannot continue if the interpreter has
                //       been disposed because that means there will be no
                //       engine context, which is required for checking the
                //       native stack space, among other things.  This is
                //       always checked because using a disposed interpreter
                //       is considered to be a serious programming error.
                //
                if (interpreter.PrivateDisposed)
                    return @default;

                //
                // NOTE: Return the ready flags for the interpreter.
                //
                return interpreter.PrivateReadyFlags;
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
            finally
            {
                if (locked)
                    Monitor.Exit(syncRoot);
            }

            return @default;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: This method assumes the interpreter lock is
        //       already held.
        //
        internal VariableFlags GetNewVariableFlags(
            bool isGlobalCallFrame
            )
        {
            // lock (syncRoot)
            // {
                return isGlobalCallFrame ?
                    newGlobalVariableFlags : newLocalVariableFlags;
            // }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Host Introspection (Default Host Only)
#if HISTORY
        private void GetHostHistoryInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            ClientDataList _history = _History; /* NOTE: Context only. */

            if (empty || history)
                list.Add("History", FormatOps.EnabledAndValue(history,
                    (_history != null) ? _history.Count.ToString() :
                    FormatOps.DisplayNull));

            IHistoryData historyLoadData = HistoryLoadData; /* NOTE: Context only. */

            if (empty || (historyLoadData != null))
                list.Add("HistoryLoadData", (historyLoadData != null) ?
                    historyLoadData.ToString() : FormatOps.DisplayNull);

            IHistoryData historySaveData = HistorySaveData; /* NOTE: Context only. */

            if (empty || (historySaveData != null))
                list.Add("HistorySaveData", (historySaveData != null) ?
                    historySaveData.ToString() : FormatOps.DisplayNull);

            IHistoryFilter historyEngineFilter = HistoryEngineFilter; /* NOTE: Context only. */

            if (empty || (historyEngineFilter != null))
                list.Add("HistoryEngineFilter", (historyEngineFilter != null) ?
                    historyEngineFilter.ToString() : FormatOps.DisplayNull);

            IHistoryFilter historyInfoFilter = HistoryInfoFilter; /* NOTE: Context only. */

            if (empty || (historyInfoFilter != null))
                list.Add("HistoryInfoFilter", (historyInfoFilter != null) ?
                    historyInfoFilter.ToString() : FormatOps.DisplayNull);

            IHistoryFilter historyLoadFilter = HistoryLoadFilter; /* NOTE: Context only. */

            if (empty || (historyLoadFilter != null))
                list.Add("HistoryLoadFilter", (historyLoadFilter != null) ?
                    historyLoadFilter.ToString() : FormatOps.DisplayNull);

            IHistoryFilter historySaveFilter = HistorySaveFilter; /* NOTE: Context only. */

            if (empty || (historySaveFilter != null))
                list.Add("HistorySaveFilter", (historySaveFilter != null) ?
                    historySaveFilter.ToString() : FormatOps.DisplayNull);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostHistoryItemInfo(
            StringPairList list,
            IHistoryFilter historyFilter,
            int headerCount,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                if (HasHistory())
                {
                    ClientDataList history = _History;

                    if (history != null)
                    {
                        foreach (IClientData clientData in history)
                        {
                            if ((clientData != null) &&
                                HistoryOps.MatchData(clientData, historyFilter))
                            {
                                StringPair pair = FormatOps.HistoryItem(
                                    list.Count - headerCount + 1, clientData, false,
                                    false);

                                if (pair != null)
                                {
                                    list.Add(pair);

                                    if ((list.Count - headerCount) == historyLimit)
                                        break;
                                }
                            }
                        }
                    }
                }
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostControlInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                list.Add("NativeThread", threadId.ToString());

                list.Add("ManagedThread", (thread != null) ?
                    thread.ManagedThreadId.ToString() : FormatOps.DisplayNull);

                list.Add("VariableEvent", (variableEvent != null) ?
                    variableEvent.Handle.ToString() : FormatOps.DisplayNull);

                bool interactive = Interactive; /* NOTE: Context only. */

                if (empty || interactive)
                    list.Add("Interactive", interactive.ToString());

                bool debug = Debug; /* NOTE: CreateFlags only. */

                if (empty || debug)
                    list.Add("Debug", debug.ToString());

                if (empty || quiet)
                    list.Add("Quiet", quiet.ToString());

                bool defaultQuiet = DefaultQuiet;

                if (empty || defaultQuiet)
                    list.Add("DefaultQuiet", defaultQuiet.ToString());

                bool getDefaultQuiet = DebugOps.GetDefaultQuiet(defaultQuiet);

                if (empty || getDefaultQuiet)
                    list.Add("GetDefaultQuiet", getDefaultQuiet.ToString());

                bool shouldBeQuiet = ShouldBeQuiet(defaultQuiet);

                if (empty || shouldBeQuiet)
                    list.Add("ShouldBeQuiet", shouldBeQuiet.ToString());

                if (empty || readOnly)
                    list.Add("ReadOnly", readOnly.ToString());

                if (empty || immutable)
                    list.Add("Immutable", immutable.ToString());

                if (empty || (readyCount > 0))
                    list.Add("ReadyCount", readyCount.ToString());

                if (empty || (readyLimit > 0))
                    list.Add("ReadyLimit", readyLimit.ToString());

                if (empty || (recursionLimit > 0))
                    list.Add("RecursionLimit", recursionLimit.ToString());

                if (empty || (EventOps.ManagerIsOk(eventManager) && eventManager.Enabled))
                    list.Add("EventManager", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.Enabled.ToString() : FormatOps.DisplayNull);

                if (empty || (waitCount > 0))
                    list.Add("WaitCount", waitCount.ToString());

                if (empty || (waitSpinCount > 0))
                    list.Add("WaitSpinCount", waitSpinCount.ToString());

#if NETWORK
                if (empty || (serverSockets > 0))
                    list.Add("ServerSockets", serverSockets.ToString());
#endif

                if (empty || (timeout != _Timeout.Infinite))
                    list.Add("Timeout", timeout.ToString());

                if (empty || (finallyTimeout != _Timeout.Infinite))
                    list.Add("FinallyTimeout", finallyTimeout.ToString());

                if (empty || (sleepTime != 0))
                    list.Add("SleepTime", sleepTime.ToString());

                if (empty || cancel)
                    list.Add("Cancel", cancel.ToString());

                if (empty || unwind)
                    list.Add("Unwind", unwind.ToString());

                if (empty || (cancelResult != null))
                    list.Add("CancelResult", (cancelResult != null) ?
                        FormatOps.DisplayString(cancelResult.String) :
                        FormatOps.DisplayNull);

                if (empty || halt)
                    list.Add("Halt", halt.ToString());

                if (empty || (haltResult != null))
                    list.Add("HaltResult", (haltResult != null) ?
                        FormatOps.DisplayString(haltResult.String) :
                        FormatOps.DisplayNull);

                if (empty || deleted)
                    list.Add("Deleted", deleted.ToString());

                if (empty || exit)
                    list.Add("Exit", exit.ToString());

                list.Add("ExitCode", exitCode.ToString());

#if HISTORY
                GetHostHistoryInfo(list, empty);
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostDebuggerInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                list.Add("Interpreter", ToString());

                if (empty || (host != null))
                    list.Add("Host", (host != null) ?
                        host.ToString() : FormatOps.DisplayNull);

                list.Add("NativeThread", threadId.ToString());

                if (empty || (thread != null))
                    list.Add("ManagedThread", (thread != null) ?
                        thread.ManagedThreadId.ToString() : FormatOps.DisplayNull);

                if (empty || (variableEvent != null))
                    list.Add("VariableEvent", (variableEvent != null) ?
                        variableEvent.Handle.ToString() : FormatOps.DisplayNull);

#if HISTORY
                GetHostHistoryInfo(list, empty);
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostEngineInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
#if SHELL
                if (empty || (interactiveThread != null))
                    list.Add("InteractiveThread", (interactiveThread != null) ?
                        interactiveThread.ManagedThreadId.ToString() : FormatOps.DisplayNull);
#endif

                if (empty || (threadStackSize != 0))
                    list.Add("ThreadStackSize", threadStackSize.ToString());

                if (empty || (extraStackSpace != 0))
                    list.Add("ExtraStackSpace", extraStackSpace.ToString());

                int interactiveLoops = InteractiveLoops; /* NOTE: Context only. */

                if (empty || (interactiveLoops > 0))
                    list.Add("InteractiveLoops", interactiveLoops.ToString());

                if (empty || (operationCount > 0))
                    list.Add("OperationCount", operationCount.ToString());

                if (empty || (commandCount > 0))
                    list.Add("CommandCount", commandCount.ToString());

                if (empty || (commandDecision != PolicyDecision.None))
                    list.Add("CommandDecision", commandDecision.ToString());

                if (empty || (scriptDecision != PolicyDecision.None))
                    list.Add("ScriptDecision", scriptDecision.ToString());

                if (empty || (fileDecision != PolicyDecision.None))
                    list.Add("FileDecision", fileDecision.ToString());

                if (empty || (streamDecision != PolicyDecision.None))
                    list.Add("StreamDecision", streamDecision.ToString());

#if POLICY_TRACE
                if (empty || policyTrace)
                    list.Add("PolicyTrace", policyTrace.ToString());
#endif

                if (empty || ((trustedPaths != null) && (trustedPaths.Count > 0)))
                    list.Add("TrustedPaths", FormatOps.DisplayList(trustedPaths));

                if (empty || ((trustedTypes != null) && (trustedTypes.Count > 0)))
                    list.Add("TrustedTypes", FormatOps.DisplayKeys(trustedTypes));

                ReturnCode returnCode = ReturnCode; /* NOTE: Context only. */

                if (empty || (returnCode != ReturnCode.Ok))
                    list.Add("ReturnCode", returnCode.ToString());

                int errorLine = ErrorLine; /* NOTE: Context only. */ /* EXEMPT */

                if (empty || (errorLine != 0))
                    list.Add("ErrorLine", errorLine.ToString());

                string errorCode = ErrorCode; /* NOTE: Context only. */

                if (empty || (errorCode != null))
                    list.Add("ErrorCode", (errorCode != null) ?
                        errorCode : FormatOps.DisplayNull);

                string errorInfo = ErrorInfo; /* NOTE: Context only. */

                if (empty || (errorInfo != null))
                    list.Add("ErrorInfo", FormatOps.DisplayString(
                        FormatOps.ReplaceNewLines(FormatOps.NormalizeNewLines(
                            errorInfo))));

                int errorFrames = ErrorFrames; /* NOTE: Context only. */

                if (empty || (errorFrames != 0))
                    list.Add("ErrorFrames", errorFrames.ToString());

                bool stackOverflow = StackOverflow; /* NOTE: Context only. */

                if (empty || stackOverflow)
                    list.Add("StackOverflow", stackOverflow.ToString());

                int levels = Levels; /* NOTE: Context only. */

                if (empty || (levels > 0))
                    list.Add("Levels", levels.ToString());

                int previousLevels = PreviousLevels; /* NOTE: Context only. */

                if (empty || (previousLevels > 0))
                    list.Add("PreviousLevels", previousLevels.ToString());

                int parserLevels = ParserLevels; /* NOTE: Context only. */

                if (empty || (parserLevels > 0))
                    list.Add("ParserLevels", parserLevels.ToString());

                int expressionLevels = ExpressionLevels; /* NOTE: Context only. */

                if (empty || (expressionLevels > 0))
                    list.Add("ExpressionLevels", expressionLevels.ToString());

                int unknownLevels = UnknownLevels; /* NOTE: Context only. */

                if (empty || (unknownLevels > 0))
                    list.Add("UnknownLevels", unknownLevels.ToString());

                int policyLevels = PolicyLevels; /* NOTE: Context only. */

                if (empty || (policyLevels > 0))
                    list.Add("PolicyLevels", policyLevels.ToString());

                int traceLevels = TraceLevels; /* NOTE: Context only. */

                if (empty || (traceLevels > 0))
                    list.Add("TraceLevels", traceLevels.ToString());

#if DEBUGGER
                int watchpointLevels = WatchpointLevels; /* NOTE: Context only. */

                if (empty || (watchpointLevels > 0))
                    list.Add("WatchpointLevels", watchpointLevels.ToString());
#endif

#if NOTIFY || NOTIFY_OBJECT
                int notifyLevels = NotifyLevels; /* NOTE: Context only. */

                if (empty || (notifyLevels > 0))
                    list.Add("NotifyLevels", notifyLevels.ToString());
#endif

                if (empty || (precision != TclVars.PrecisionValue))
                    list.Add("Precision", precision.ToString());

#if XML
                if (empty || allXml)
                    list.Add("AllXml", allXml.ToString());

                if (empty || validateXml)
                    list.Add("ValidateXml", validateXml.ToString());
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostEntityInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                if (empty || ((slaveInterpreters != null) && (slaveInterpreters.Count > 0)))
                    list.Add("SlaveInterpreters", (slaveInterpreters != null) ?
                        slaveInterpreters.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((packages != null) && (packages.Count > 0)))
                    list.Add("Packages", (packages != null) ?
                        packages.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((packageIndexes != null) && (packageIndexes.Count > 0)))
                    list.Add("PackageIndexes", (packageIndexes != null) ?
                        packageIndexes.Count.ToString() : FormatOps.DisplayNull);

#if APPDOMAINS
                if (empty || ((appDomains != null) && (appDomains.Count > 0)))
                    list.Add("AppDomains", (appDomains != null) ?
                        appDomains.Count.ToString() : FormatOps.DisplayNull);
#endif

                if (empty || ((pluginArguments != null) && (pluginArguments.Count > 0)))
                    list.Add("PluginArguments", (pluginArguments != null) ?
                        pluginArguments.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((plugins != null) && (plugins.Count > 0)))
                    list.Add("Plugins", (plugins != null) ?
                        plugins.Count.ToString() : FormatOps.DisplayNull);

                if (empty || (globalNamespace != null))
                    list.Add("GlobalNamespace", FormatOps.DisplayNamespace(globalNamespace));

                if (empty || ((pendingNamespaces != null) && (pendingNamespaces.Count > 0)))
                    list.Add("PendingNamespaces", (pendingNamespaces != null) ?
                        pendingNamespaces.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((commands != null) && (commands.Count > 0)))
                    list.Add("Commands", (commands != null) ?
                        commands.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((hiddenCommands != null) && (hiddenCommands.Count > 0)))
                    list.Add("HiddenCommands", (hiddenCommands != null) ?
                        hiddenCommands.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((aliases != null) && (aliases.Count > 0)))
                    list.Add("Aliases", (aliases != null) ?
                        aliases.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((procedures != null) && (procedures.Count > 0)))
                    list.Add("Procedures", (procedures != null) ?
                        procedures.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((hiddenProcedures != null) && (hiddenProcedures.Count > 0)))
                    list.Add("HiddenProcedures", (hiddenProcedures != null) ?
                        hiddenProcedures.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((executes != null) && (executes.Count > 0)))
                    list.Add("Executes", (executes != null) ?
                        executes.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((hiddenExecutes != null) && (hiddenExecutes.Count > 0)))
                    list.Add("HiddenExecutes", (hiddenExecutes != null) ?
                        hiddenExecutes.Count.ToString() : FormatOps.DisplayNull);

                #region Dead Code
#if DEAD_CODE
                if (empty || ((lambdas != null) && (lambdas.Count > 0)))
                    list.Add("Lambdas", (lambdas != null) ?
                        lambdas.Count.ToString() : FormatOps.DisplayNull);
#endif
                #endregion

                if (empty || ((functions != null) && (functions.Count > 0)))
                    list.Add("Functions", (functions != null) ?
                        functions.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((operators != null) && (operators.Count > 0)))
                    list.Add("Operators", (operators != null) ?
                        operators.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((policies != null) && (policies.Count > 0)))
                    list.Add("Policies", (policies != null) ?
                        policies.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((scopes != null) && (scopes.Count > 0)))
                    list.Add("Scopes", (scopes != null) ?
                        scopes.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((traces != null) && (traces.Count > 0)))
                    list.Add("Traces", (traces != null) ?
                        traces.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((channels != null) && (channels.Count > 0)))
                    list.Add("Channels", (channels != null) ?
                        channels.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((encodings != null) && (encodings.Count > 0)))
                    list.Add("Encodings", (encodings != null) ?
                        encodings.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((objects != null) && (objects.Count > 0)))
                    list.Add("Objects", (objects != null) ?
                        objects.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((objectTypes != null) && (objectTypes.Count > 0)))
                    list.Add("ObjectTypes", (objectTypes != null) ?
                        objectTypes.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((objectNamespaces != null) && (objectNamespaces.Count > 0)))
                    list.Add("ObjectNamespaces", (objectNamespaces != null) ?
                        objectNamespaces.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((objectInterfaces != null) && (objectInterfaces.Count > 0)))
                    list.Add("ObjectInterfaces", (objectInterfaces != null) ?
                        objectInterfaces.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((objectAliasNamespaces != null) && (objectAliasNamespaces.Count > 0)))
                    list.Add("ObjectAliasNamespaces", (objectAliasNamespaces != null) ?
                        objectAliasNamespaces.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((callbacks != null) && (callbacks.Count > 0)))
                    list.Add("Callbacks", (callbacks != null) ?
                        callbacks.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((resolvers != null) && (resolvers.Count > 0)))
                    list.Add("Resolvers", (resolvers != null) ?
                        resolvers.Count.ToString() : FormatOps.DisplayNull);

                ArraySearchDictionary arraySearches = ArraySearches; /* NOTE: Context only. */

                if (empty || ((arraySearches != null) && (arraySearches.Count > 0)))
                    list.Add("ArraySearches", (arraySearches != null) ?
                        arraySearches.Count.ToString() : FormatOps.DisplayNull);

#if CALLBACK_QUEUE
                if (empty || ((callbackQueue != null) && (callbackQueue.Count > 0)))
                    list.Add("CallbackQueue", (callbackQueue != null) ?
                        callbackQueue.Count.ToString() : FormatOps.DisplayNull);
#endif

                if (empty || (EventOps.ManagerIsOk(eventManager) && (eventManager.EventCount > 0)))
                    list.Add("Events", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.EventCount.ToString() : FormatOps.DisplayNull);

                if (empty || (EventOps.ManagerIsOk(eventManager) && (eventManager.IdleEventCount > 0)))
                    list.Add("IdleEvents", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.IdleEventCount.ToString() : FormatOps.DisplayNull);

                if (empty || (EventOps.ManagerIsOk(eventManager) && (eventManager.TotalEventCount > 0)))
                    list.Add("TotalEvents", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.TotalEventCount.ToString() : FormatOps.DisplayNull);

                if (empty || (EventOps.ManagerIsOk(eventManager) && (eventManager.MaximumEventCount > 0)))
                    list.Add("MaximumEvents", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.MaximumEventCount.ToString() : FormatOps.DisplayNull);

                if (empty || (EventOps.ManagerIsOk(eventManager) && (eventManager.MaximumIdleEventCount > 0)))
                    list.Add("MaximumIdleEvents", EventOps.ManagerIsOk(eventManager) ?
                        eventManager.MaximumIdleEventCount.ToString() : FormatOps.DisplayNull);

#if DATA
                if (empty || ((connections != null) && (connections.Count > 0)))
                    list.Add("DbConnections", (connections != null) ?
                        connections.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((transactions != null) && (transactions.Count > 0)))
                    list.Add("DbTransactions", (transactions != null) ?
                        transactions.Count.ToString() : FormatOps.DisplayNull);
#endif

#if NATIVE && LIBRARY
                if (empty || ((modules != null) && (modules.Count > 0)))
                    list.Add("Modules", (modules != null) ?
                        modules.Count.ToString() : FormatOps.DisplayNull);

                if (empty || ((delegates != null) && (delegates.Count > 0)))
                    list.Add("Delegates", (delegates != null) ?
                        delegates.Count.ToString() : FormatOps.DisplayNull);
#endif
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && TCL
            lock (tclSyncRoot)
            {
                bool needSeparator = false;

                if (empty || (tclApi != null))
                {
                    if (tclApi != null)
                    {
                        list.Add((IPair<string>)null);
                        list.Add("TclApi");
                        list.Add((IPair<string>)null);
                        list.Add(tclApi.ToList(false));

                        TclBuild tclBuild = tclApi.Build;

                        if (tclBuild != null)
                        {
                            list.Add((IPair<string>)null);
                            list.Add("TclBuild");
                            list.Add((IPair<string>)null);
                            list.Add(tclBuild.ToList());
                        }

                        needSeparator = true;
                    }
                    else
                    {
                        list.Add("TclApi", FormatOps.DisplayNull);
                    }
                }

                if (empty || ((tclInterps != null) && (tclInterps.Count > 0)))
                {
                    if (needSeparator)
                    {
                        list.Add((IPair<string>)null);
                        needSeparator = false;
                    }

                    list.Add("TclInterps", (tclInterps != null) ?
                        tclInterps.Count.ToString() : FormatOps.DisplayNull);
                }

#if TCL_THREADS
                if (empty || ((tclThreads != null) && (tclThreads.Count > 0)))
                {
                    if (needSeparator)
                    {
                        list.Add((IPair<string>)null);
                        needSeparator = false;
                    }

                    list.Add("TclThreads", (tclThreads != null) ?
                        tclThreads.Count.ToString() : FormatOps.DisplayNull);
                }
#endif

                if (empty || ((tclBridges != null) && (tclBridges.Count > 0)))
                {
                    if (needSeparator)
                    {
                        list.Add((IPair<string>)null);
                        needSeparator = false;
                    }

                    list.Add("TclBridges", (tclBridges != null) ?
                        tclBridges.Count.ToString() : FormatOps.DisplayNull);
                }
            }
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostFlagInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                if (empty || (createFlags != CreateFlags.None))
                    list.Add("iCreateFlags", createFlags.ToString());

                if (empty || ((scriptFlags != ScriptFlags.None)))
                    list.Add("iScriptFlags", scriptFlags.ToString());

                if (empty || ((interpreterFlags != InterpreterFlags.None)))
                    list.Add("iInterpreterFlags", interpreterFlags.ToString());

                if (empty || ((readyFlags != ReadyFlags.None)))
                    list.Add("iReadyFlags", readyFlags.ToString());

                if (empty || ((engineFlags != EngineFlags.None)))
                    list.Add("iEngineFlags", engineFlags.ToString());

                EngineFlags contextEngineFlags = ContextEngineFlags; /* NOTE: Context only. */

                if (empty || ((contextEngineFlags != EngineFlags.None)))
                    list.Add("iContextEngineFlags", contextEngineFlags.ToString());

                if (empty || ((substitutionFlags != SubstitutionFlags.None)))
                    list.Add("iSubstitutionFlags", substitutionFlags.ToString());

                if (empty || ((expressionFlags != ExpressionFlags.None)))
                    list.Add("iExpressionFlags", expressionFlags.ToString());

#if DEBUGGER || SHELL
                if (empty || ((headerFlags != HeaderFlags.None)))
                    list.Add("iHeaderFlags", headerFlags.ToString());
#endif

                if (empty || ((afterEventFlags != EventFlags.None)))
                    list.Add("iAfterEventFlags", afterEventFlags.ToString());

                if (empty || ((engineEventFlags != EventFlags.None)))
                    list.Add("iEngineEventFlags", engineEventFlags.ToString());

                if (empty || ((queueEventFlags != EventFlags.None)))
                    list.Add("iQueueEventFlags", queueEventFlags.ToString());

                if (empty || ((serviceEventFlags != EventFlags.None)))
                    list.Add("iServiceEventFlags", serviceEventFlags.ToString());

                if (empty || ((updateEventFlags != EventFlags.None)))
                    list.Add("iUpdateEventFlags", updateEventFlags.ToString());

                if (empty || ((waitEventFlags != EventFlags.None)))
                    list.Add("iWaitEventFlags", waitEventFlags.ToString());

                if (empty || ((newGlobalVariableFlags != VariableFlags.None)))
                    list.Add("iNewGlobalVariableFlags", newGlobalVariableFlags.ToString());

                if (empty || ((newLocalVariableFlags != VariableFlags.None)))
                    list.Add("iNewLocalVariableFlags", newLocalVariableFlags.ToString());

                if (empty || ((procedureFlags != ProcedureFlags.None)))
                    list.Add("iProcedureFlags", procedureFlags.ToString());

                if (empty || ((pluginFlags != PluginFlags.None)))
                    list.Add("iPluginFlags", pluginFlags.ToString());

#if SHELL && INTERACTIVE_COMMANDS
                if (empty || ((interactiveEngineFlags != EngineFlags.None)))
                    list.Add("idEngineFlags", interactiveEngineFlags.ToString());

                if (empty || ((interactiveSubstitutionFlags != SubstitutionFlags.None)))
                    list.Add("idSubstitutionFlags", interactiveSubstitutionFlags.ToString());

                if (empty || ((interactiveEventFlags != EventFlags.None)))
                    list.Add("idEventFlags", interactiveEventFlags.ToString());

                if (empty || ((interactiveExpressionFlags != ExpressionFlags.None)))
                    list.Add("idExpressionFlags", interactiveExpressionFlags.ToString());
#endif

#if NOTIFY || NOTIFY_OBJECT
                if (empty || ((notifyTypes != NotifyType.None)))
                    list.Add("iNotifyTypes", notifyTypes.ToString());

                NotifyType threadNotifyTypes = NotifyTypes; /* NOTE: Context only. */

                if (empty || ((threadNotifyTypes != NotifyType.None)))
                    list.Add("iThreadNotifyTypes", threadNotifyTypes.ToString());

                if (empty || ((notifyFlags != NotifyFlags.None)))
                    list.Add("iNotifyFlags", notifyFlags.ToString());

                NotifyFlags threadNotifyFlags = NotifyFlags; /* NOTE: Context only. */

                if (empty || ((threadNotifyFlags != NotifyFlags.None)))
                    list.Add("iThreadNotifyFlags", threadNotifyFlags.ToString());
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostInterpreterInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
                list.Add("Id", ToString()); // NOTE: Also in engine info.

                if (empty || disposed)
                    list.Add("Disposed", disposed.ToString());

                if (empty || throwOnFeatureNotSupported)
                    list.Add("ThrowOnFeatureNotSupported",
                        throwOnFeatureNotSupported.ToString());

                if (empty || AreNamespacesEnabled())
                    list.Add("AreNamespacesEnabled",
                        AreNamespacesEnabled().ToString());

                if (empty || (traceTextWriter != null))
                    list.Add("TraceTextWriter", (traceTextWriter != null) ?
                        traceTextWriter.ToString() : FormatOps.DisplayNull);

                if (empty || (debugTextWriter != null))
                    list.Add("DebugTextWriter", (debugTextWriter != null) ?
                        debugTextWriter.ToString() : FormatOps.DisplayNull);

                if (empty || (applicationObject != null))
                    list.Add("ApplicationObject", (applicationObject != null) ?
                        applicationObject.ToString() : FormatOps.DisplayNull);

                if (empty || (policyObject != null))
                    list.Add("PolicyObject", (policyObject != null) ?
                        policyObject.ToString() : FormatOps.DisplayNull);

                if (empty || (resolverObject != null))
                    list.Add("ResolverObject", (resolverObject != null) ?
                        resolverObject.ToString() : FormatOps.DisplayNull);

                if (empty || (userObject != null))
                    list.Add("UserObject", (userObject != null) ?
                        userObject.ToString() : FormatOps.DisplayNull);

                if (empty || (runtimeOptions != null))
                    list.Add("RuntimeOptions", FormatOps.DisplayKeys(runtimeOptions));

#if SHELL
                ArgumentCallback argumentCallback = ArgumentCallback;

                if (empty || (argumentCallback != null))
                {
                    list.Add("ArgumentCallback",
                        (argumentCallback != null) ?
                            FormatOps.DelegateMethodName(
                                argumentCallback.Method, false, true) :
                            FormatOps.DisplayNull);
                }

                EvaluateScriptCallback evaluateScriptCallback = EvaluateScriptCallback;

                if (empty || (evaluateScriptCallback != null))
                {
                    list.Add("EvaluateScriptCallback",
                        (evaluateScriptCallback != null) ?
                            FormatOps.DelegateMethodName(
                                evaluateScriptCallback.Method, false, true) :
                            FormatOps.DisplayNull);
                }

                EvaluateFileCallback evaluateFileCallback = EvaluateFileCallback;

                if (empty || (evaluateFileCallback != null))
                {
                    list.Add("EvaluateFileCallback",
                        (evaluateFileCallback != null) ?
                            FormatOps.DelegateMethodName(
                                evaluateFileCallback.Method, false, true) :
                            FormatOps.DisplayNull);
                }

                EvaluateEncodedFileCallback evaluateEncodedFileCallback = EvaluateEncodedFileCallback;

                if (empty || (evaluateEncodedFileCallback != null))
                {
                    list.Add("EvaluateEncodedFileCallback",
                        (evaluateEncodedFileCallback != null) ?
                            FormatOps.DelegateMethodName(
                                evaluateEncodedFileCallback.Method, false, true) :
                            FormatOps.DisplayNull);
                }
#endif

#if DEBUGGER
                InteractiveLoopCallback interactiveLoopCallback = InteractiveLoopCallback;

                if (empty || (interactiveLoopCallback != null))
                {
                    list.Add("InteractiveLoopCallback",
                        (interactiveLoopCallback != null) ?
                            FormatOps.DelegateMethodName(
                                interactiveLoopCallback.Method, false, true) :
                            FormatOps.DisplayNull);
                }
#endif

                if (empty || (masterInterpreter != null))
                    list.Add("MasterInterpreter", (masterInterpreter != null) ?
                        masterInterpreter.ToString() : FormatOps.DisplayNull);

                if (empty || !String.IsNullOrEmpty(slaveName))
                    list.Add("SlaveName", FormatOps.DisplayString(slaveName));

#if APPDOMAINS && ISOLATED_INTERPRETERS
                if (empty || !String.IsNullOrEmpty(slaveAppDomainName))
                    list.Add("SlaveAppDomainName",
                        FormatOps.DisplayString(slaveAppDomainName));
#endif

                if (empty || preSetup)
                    list.Add("PreSetup", preSetup.ToString());

                if (empty || setup)
                    list.Add("Setup", setup.ToString());

                if (empty || preInitialized)
                    list.Add("PreInitialized", preInitialized.ToString());

                if (empty || !String.IsNullOrEmpty(preInitializeText))
                    list.Add("PreInitializeText",
                        FormatOps.DisplayString(FormatOps.ReplaceNewLines(
                            FormatOps.NormalizeNewLines(preInitializeText))));

                if (empty || initialized)
                    list.Add("Initialized", initialized.ToString());

                if (empty || !String.IsNullOrEmpty(initializedPath))
                    list.Add("InitializedPath",
                        FormatOps.DisplayString(initializedPath));

                if (empty || initializedShell)
                    list.Add("InitializedShell", initializedShell.ToString());

                if (empty || !String.IsNullOrEmpty(initializedShellPath))
                    list.Add("InitializedShellPath",
                        FormatOps.DisplayString(initializedShellPath));

                if (empty || !String.IsNullOrEmpty(libraryPath))
                    list.Add("LibraryPath", FormatOps.DisplayString(libraryPath));

                if (empty || ((autoPathList != null) && (autoPathList.Count > 0)))
                    list.Add("AutoPathList", FormatOps.DisplayList(autoPathList));

                if (empty || !String.IsNullOrEmpty(unknown))
                    list.Add("Unknown", FormatOps.DisplayString(unknown));

                string namespaceUnknown = NamespaceUnknown;

                if (empty || !String.IsNullOrEmpty(namespaceUnknown))
                    list.Add("NamespaceUnknown", FormatOps.DisplayString(namespaceUnknown));

                if (empty || !String.IsNullOrEmpty(packageUnknown))
                    list.Add("PackageUnknown", FormatOps.DisplayString(packageUnknown));

                if (empty || !String.IsNullOrEmpty(backgroundError))
                    list.Add("BackgroundError", FormatOps.DisplayString(backgroundError));

                if (empty || !String.IsNullOrEmpty(initializedPath))
                    list.Add("InitializedPath", FormatOps.DisplayString(initializedPath));

                string testPath = TestPath; /* NOTE: Context only. */

                if (empty || !String.IsNullOrEmpty(testPath))
                    list.Add("TestPath", FormatOps.DisplayString(testPath));

                if (empty || (binder != null))
                    list.Add("Binder", (binder != null) ?
                        binder.ToString() : FormatOps.DisplayNull);

                if (empty || (cultureInfo != null))
                    list.Add("CultureInfo", (cultureInfo != null) ?
                        FormatOps.CultureName(cultureInfo, true) : FormatOps.DisplayNull);

                string interactiveInput = InteractiveInput; /* NOTE: Context only. */

                if (empty || !String.IsNullOrEmpty(interactiveInput))
                    list.Add("InteractiveInput",
                        FormatOps.DisplayString(FormatOps.ReplaceNewLines(
                            FormatOps.NormalizeNewLines(interactiveInput))));

                string previousInteractiveInput = PreviousInteractiveInput; /* NOTE: Context only. */

                if (empty || !String.IsNullOrEmpty(previousInteractiveInput))
                    list.Add("PreviousInteractiveInput",
                        FormatOps.DisplayString(FormatOps.ReplaceNewLines(
                            FormatOps.NormalizeNewLines(previousInteractiveInput))));

                string interactiveMode = InteractiveMode; /* NOTE: Context only. */

                if (empty || !String.IsNullOrEmpty(interactiveMode))
                    list.Add("InteractiveMode", FormatOps.DisplayString(interactiveMode));

                IScriptLocation scriptLocation = ScriptLocation; /* NOTE: Context only. */

                if (empty || (scriptLocation != null))
                    list.Add("ScriptLocation (Override)", (scriptLocation != null) ?
                        scriptLocation.ToString() : FormatOps.DisplayNull);

                StackList<IScriptLocation> scriptLocations = ScriptLocations; /* NOTE: Context only. */

                if (empty || (!scriptLocations.IsEmpty && (scriptLocations.Peek() != null)))
                {
                    list.Add("ScriptLocation (Actual)",
                        !scriptLocations.IsEmpty ? scriptLocations.Peek().ToString() :
                        FormatOps.DisplayNull);
                }

                int previousProcessId = PreviousProcessId; /* NOTE: Context only. */

                if (empty || (previousProcessId != 0))
                    list.Add("PreviousProcessId", previousProcessId.ToString());

                ///////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
                GetHostListCacheInfo(list, empty);
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if (CACHE_ARGUMENTLIST_TOSTRING || CACHE_STRINGLIST_TOSTRING) && CACHE_STATISTICS
                GetHostStringCacheInfo(list, empty);
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        private void GetHostListCacheInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
#if PARSE_CACHE || LIST_CACHE || TYPE_CACHE || COM_TYPE_CACHE
                if (empty || (MaximumCacheSize > 0))
                    list.Add("MaximumCacheSize",
                        MaximumCacheSize.ToString());
#endif

#if PARSE_CACHE || LIST_CACHE
                if (empty || (MaximumCacheItemSize > 0))
                    list.Add("MaximumCacheItemSize",
                        MaximumCacheItemSize.ToString());
#endif

#if EXECUTE_CACHE
#if CACHE_STATISTICS
                if (empty || ((executeCache != null) && executeCache.HaveCacheCounts()))
#else
                if (empty || ((executeCache != null) && (executeCache.Count > 0)))
#endif
                {
                    list.Add("ExecuteCache", (executeCache != null) ?
#if CACHE_STATISTICS
                        executeCache.CacheToString() : FormatOps.DisplayNull);
#else
                        executeCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }

                ///////////////////////////////////////////////////////////////////////////////////////

#if CACHE_STATISTICS
                if (empty || ((hiddenExecuteCache != null) && hiddenExecuteCache.HaveCacheCounts()))
#else
                if (empty || ((hiddenExecuteCache != null) && (hiddenExecuteCache.Count > 0)))
#endif
                {
                    list.Add("HiddenExecuteCache", (hiddenExecuteCache != null) ?
#if CACHE_STATISTICS
                        hiddenExecuteCache.CacheToString() : FormatOps.DisplayNull);
#else
                        hiddenExecuteCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE
#if CACHE_STATISTICS
                if (empty || ((stringListCache != null) && stringListCache.HaveCacheCounts()))
#else
                if (empty || ((stringListCache != null) && (stringListCache.Count > 0)))
#endif
                {
                    list.Add("StringListCache", (stringListCache != null) ?
#if CACHE_STATISTICS
                        stringListCache.CacheToString() : FormatOps.DisplayNull);
#else
                        stringListCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if PARSE_CACHE
#if CACHE_STATISTICS
                if (empty || ((parseStateCache != null) && parseStateCache.HaveCacheCounts()))
#else
                if (empty || ((parseStateCache != null) && (parseStateCache.Count > 0)))
#endif
                {
                    list.Add("ParseStateCache", (parseStateCache != null) ?
#if CACHE_STATISTICS
                        parseStateCache.CacheToString() : FormatOps.DisplayNull);
#else
                        parseStateCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

                #region Dead Code
#if DEAD_CODE
#if CACHE_STATISTICS
                if (empty || ((expressionStateCache != null) && expressionStateCache.HaveCacheCounts()))
#else
                if (empty || ((expressionStateCache != null) && (expressionStateCache.Count > 0)))
#endif
                {
                    list.Add("ExpressionStateCache", (expressionStateCache != null) ?
#if CACHE_STATISTICS
                        expressionStateCache.CacheToString() : FormatOps.DisplayNull);
#else
                        expressionStateCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif
                #endregion

                ///////////////////////////////////////////////////////////////////////////////////////

#if TYPE_CACHE
#if CACHE_STATISTICS
                if (empty || ((typeCache != null) && typeCache.HaveCacheCounts()))
#else
                if (empty || ((typeCache != null) && (typeCache.Count > 0)))
#endif
                {
                    list.Add("TypeCache", (typeCache != null) ?
#if CACHE_STATISTICS
                        typeCache.CacheToString() : FormatOps.DisplayNull);
#else
                        typeCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if COM_TYPE_CACHE
#if CACHE_STATISTICS
                if (empty || ((comTypeListCache != null) && comTypeListCache.HaveCacheCounts()))
#else
                if (empty || ((comTypeListCache != null) && (comTypeListCache.Count > 0)))
#endif
                {
                    list.Add("ComTypeListCache", (comTypeListCache != null) ?
#if CACHE_STATISTICS
                        comTypeListCache.CacheToString() : FormatOps.DisplayNull);
#else
                        comTypeListCache.Count.ToString() : FormatOps.DisplayNull);
#endif
                }
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if (CACHE_ARGUMENTLIST_TOSTRING || CACHE_STRINGLIST_TOSTRING) && CACHE_STATISTICS
        private void GetHostStringCacheInfo(
            StringPairList list,
            bool empty
            )
        {
            if (list == null)
                return;

            lock (syncRoot)
            {
#if CACHE_ARGUMENTLIST_TOSTRING
                if (empty || ArgumentList.HaveCacheCounts())
                    list.Add("ArgumentListToStringCache", ArgumentList.CacheToString());
#endif

                ///////////////////////////////////////////////////////////////////////////////////////

#if CACHE_STRINGLIST_TOSTRING
                if (empty || StringList.HaveCacheCounts())
                    list.Add("StringListToStringCache", StringList.CacheToString());
#endif
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For use by the _Hosts.Default class only.
        //
        internal void GetHostTestInfo(
            StringPairList list,
            bool empty
            )
        {
            lock (syncRoot)
            {
                int[] testStatistics = TestStatistics; /* NOTE: Context only. */

                if ((testStatistics != null) &&
                    (testStatistics.Length >= (int)TestInformationType.SizeOf))
                {
                    if (empty || (testStatistics[(int)TestInformationType.Total] > 0))
                        list.Add("Total", testStatistics[(int)TestInformationType.Total].ToString());

                    if (empty || (testStatistics[(int)TestInformationType.Skipped] > 0))
                        list.Add("Skipped", testStatistics[(int)TestInformationType.Skipped].ToString());

                    if (empty || (testStatistics[(int)TestInformationType.Passed] > 0))
                        list.Add("Passed", testStatistics[(int)TestInformationType.Passed].ToString());

                    if (empty || (testStatistics[(int)TestInformationType.Failed] > 0))
                        list.Add("Failed", testStatistics[(int)TestInformationType.Failed].ToString());
                }

                StringList testMatch = TestMatch; /* NOTE: Context only. */

                if (empty || ((testMatch != null) && (testMatch.Count > 0)))
                    list.Add("Match", FormatOps.DisplayList(testMatch));

                StringList testSkip = TestSkip; /* NOTE: Context only. */

                if (empty || ((testSkip != null) && (testSkip.Count > 0)))
                    list.Add("Skip", FormatOps.DisplayList(testSkip));

#if DEBUGGER
                StringDictionary testBreakpoints = TestBreakpoints; /* NOTE: Context only. */

                if (empty || ((testBreakpoints != null) && (testBreakpoints.Count > 0)))
                    list.Add("Breakpoints", FormatOps.DisplayKeys(testBreakpoints));
#endif

                StringList testConstraints = TestConstraints; /* NOTE: Context only. */

                if (empty || ((testConstraints != null) && (testConstraints.Count > 0)))
                    list.Add("Constraints", FormatOps.DisplayList(testConstraints));

                StringList testFailures = TestFailures; /* NOTE: Context only. */

                if (empty || ((testFailures != null) && (testFailures.Count > 0)))
                    list.Add("Failures", FormatOps.DisplayList(testFailures));
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Cache Management
#if PARSE_CACHE
        #region ExpressionState Cache
        #region Dead Code
#if DEAD_CODE
        internal bool GetCachedExpressionState( /* NOT USED */
            string text,
            ref IExpressionState exprState
            )
        {
            //
            // NOTE: Part of the experimental expression parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ExpressionState, true))
                {
                    if ((text != null) && (expressionStateCache != null))
                    {
                        if ((MaximumCacheItemSize > 0) &&
                            (text.Length > MaximumCacheItemSize))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref expressionStateCache.cacheCounts[(int)CacheCountType.Miss]);
#endif

                            return false;
                        }

                        if (expressionStateCache.TryGetValue(text, out exprState))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref expressionStateCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                            return true;
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref expressionStateCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool AddCachedExpressionState( /* NOT USED */
            IExpressionState exprState
            )
        {
            //
            // NOTE: Part of the experimental expression parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ExpressionState, true))
                {
                    if ((exprState != null) && (exprState.ParseState != null))
                    {
                        string text = exprState.ParseState.Text;

                        if ((text != null) && (expressionStateCache != null))
                        {
                            if ((MaximumCacheSize > 0) &&
                                (expressionStateCache.Count > MaximumCacheSize))
                            {
#if CACHE_DICTIONARY
                                expressionStateCache.TrimExcess(
                                    MinimumCacheSize, MaximumCacheSize);

#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref expressionStateCache.cacheCounts[(int)CacheCountType.Trim]);
#endif
#else
                                expressionStateCache.Clear();

#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref expressionStateCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
#endif
                            }

                            if ((MaximumCacheItemSize > 0) &&
                                (text.Length > MaximumCacheItemSize))
                            {
                                return false;
                            }

                            TokenList tokens = exprState.ParseState.Tokens;

                            if ((MaximumCacheItemSize > 0) &&
                                (tokens != null) &&
                                (tokens.Count > MaximumCacheItemSize))
                            {
                                return false;
                            }

                            if (expressionStateCache.ContainsKey(text))
                                return false;

                            expressionStateCache.Add(text, exprState);

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref expressionStateCache.cacheCounts[(int)CacheCountType.Add]);
#endif

                            return true;
                        }
                    }
                }
            }

            return false;
        }
#endif
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region ParseState Cache
        internal bool GetCachedParseState(
            string text,
            ref IParseState parseState
            )
        {
            //
            // NOTE: Part of the experimental parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ParseState, true))
                {
                    if ((text != null) && (parseStateCache != null))
                    {
                        if ((MaximumCacheItemSize > 0) &&
                            (text.Length > MaximumCacheItemSize))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref parseStateCache.cacheCounts[(int)CacheCountType.Miss]);
#endif

                            return false;
                        }

                        if (parseStateCache.TryGetValue(text, out parseState))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref parseStateCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                            return true;
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref parseStateCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool AddCachedParseState(
            IParseState parseState
            )
        {
            //
            // NOTE: Part of the experimental parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ParseState, true))
                {
                    if (parseState != null)
                    {
                        string text = parseState.Text;

                        if ((text != null) && (parseStateCache != null))
                        {
                            if ((MaximumCacheSize > 0) &&
                                (parseStateCache.Count > MaximumCacheSize))
                            {
#if CACHE_DICTIONARY
                                parseStateCache.TrimExcess(
                                    MinimumCacheSize, MaximumCacheSize);

#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref parseStateCache.cacheCounts[(int)CacheCountType.Trim]);
#endif
#else
                                parseStateCache.Clear();

#if CACHE_STATISTICS
                                Interlocked.Increment(
                                    ref parseStateCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
#endif
                            }

                            if ((MaximumCacheItemSize > 0) &&
                                (text.Length > MaximumCacheItemSize))
                            {
                                return false;
                            }

                            TokenList tokens = parseState.Tokens;

                            if ((MaximumCacheItemSize > 0) &&
                                (tokens != null) &&
                                (tokens.Count > MaximumCacheItemSize))
                            {
                                return false;
                            }

                            if (parseStateCache.ContainsKey(text))
                                return false;

                            parseStateCache.Add(text, parseState);

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref parseStateCache.cacheCounts[(int)CacheCountType.Add]);
#endif

                            return true;
                        }
                    }
                }
            }

            return false;
        }
        #endregion
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if LIST_CACHE
        #region StringList Cache
        internal bool GetCachedStringList(
            string text,
            ref StringList list
            )
        {
            //
            // NOTE: Part of the experimental parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.StringList, true))
                {
                    if ((text != null) && (stringListCache != null))
                    {
                        if ((MaximumCacheItemSize > 0) &&
                            (text.Length > MaximumCacheItemSize))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref stringListCache.cacheCounts[(int)CacheCountType.Miss]);
#endif

                            return false;
                        }

                        if (stringListCache.TryGetValue(text, out list))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref stringListCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                            return true;
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref stringListCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool AddCachedStringList(
            string text,
            StringList list
            )
        {
            //
            // NOTE: Part of the experimental parser caching mechanism.
            //
            //       No speed improvement was observed; however, further analysis
            //       and profiling may be warranted.
            //
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.StringList, true))
                {
                    if ((text != null) && (stringListCache != null))
                    {
                        if ((MaximumCacheSize > 0) &&
                            (stringListCache.Count >= MaximumCacheSize))
                        {
#if CACHE_DICTIONARY
                            stringListCache.TrimExcess(
                                MinimumCacheSize, MaximumCacheSize);

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref stringListCache.cacheCounts[(int)CacheCountType.Trim]);
#endif
#else
                            stringListCache.Clear();

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref stringListCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
#endif
                        }

                        if ((MaximumCacheItemSize > 0) &&
                            (text.Length > MaximumCacheItemSize))
                        {
                            return false;
                        }

                        if ((MaximumCacheItemSize > 0) &&
                            (list != null) &&
                            (list.Count > MaximumCacheItemSize))
                        {
                            return false;
                        }

                        if (stringListCache.ContainsKey(text))
                            return false;

                        stringListCache.Add(text, list);

#if CACHE_STATISTICS
                        Interlocked.Increment(
                            ref stringListCache.cacheCounts[(int)CacheCountType.Add]);
#endif

                        return true;
                    }
                }
            }

            return false;
        }
        #endregion
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TYPE_CACHE
        #region Type Cache
        internal bool GetCachedType(
            string name,
            ref Type type
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.Type, true))
                {
                    if ((name != null) && (typeCache != null))
                    {
                        if ((MaximumCacheItemSize > 0) &&
                            (name.Length > MaximumCacheItemSize))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Miss]);
#endif

                            return false;
                        }

                        if (typeCache.TryGetValue(name, out type))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                            return true;
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool AddCachedType(
            string name,
            Type type
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.Type, true))
                {
                    if ((name != null) && (typeCache != null))
                    {
                        if ((MaximumCacheSize > 0) &&
                            (typeCache.Count >= MaximumCacheSize))
                        {
#if CACHE_DICTIONARY
                            typeCache.TrimExcess(
                                MinimumCacheSize, MaximumCacheSize);

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Trim]);
#endif
#else
                            typeCache.Clear();

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
#endif
                        }

                        if ((MaximumCacheItemSize > 0) &&
                            (name.Length > MaximumCacheItemSize))
                        {
                            return false;
                        }

                        if (typeCache.ContainsKey(name))
                            return false;

                        typeCache.Add(name, type);

#if CACHE_STATISTICS
                        Interlocked.Increment(
                            ref typeCache.cacheCounts[(int)CacheCountType.Add]);
#endif

                        return true;
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool RemoveCachedType(
            string name
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.Type, true))
                {
                    if ((name != null) && (typeCache != null))
                    {
                        if ((MaximumCacheItemSize > 0) &&
                            (name.Length > MaximumCacheItemSize))
                        {
                            return false;
                        }

                        bool result = typeCache.Remove(name);

#if CACHE_STATISTICS
                        if (result)
                        {
                            Interlocked.Increment(
                                ref typeCache.cacheCounts[(int)CacheCountType.Remove]);
                        }
#endif

                        return result;
                    }
                }
            }

            return false;
        }
        #endregion
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if COM_TYPE_CACHE
        #region ComTypeList Cache
        internal bool GetCachedComTypeList(
            IntPtr unknown,
            ref TypeList types
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ComTypeList, true))
                {
                    if ((unknown != IntPtr.Zero) && (comTypeListCache != null))
                    {
                        if (comTypeListCache.TryGetValue(unknown, out types))
                        {
#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref comTypeListCache.cacheCounts[(int)CacheCountType.Hit]);
#endif

                            return true;
                        }
#if CACHE_STATISTICS
                        else
                        {
                            Interlocked.Increment(
                                ref comTypeListCache.cacheCounts[(int)CacheCountType.Miss]);
                        }
#endif
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool AddCachedComTypeList(
            IntPtr unknown,
            TypeList types
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ComTypeList, true))
                {
                    if ((unknown != IntPtr.Zero) && (comTypeListCache != null))
                    {
                        if ((MaximumCacheSize > 0) &&
                            (comTypeListCache.Count >= MaximumCacheSize))
                        {
#if CACHE_DICTIONARY
                            comTypeListCache.TrimExcess(
                                MinimumCacheSize, MaximumCacheSize);

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref comTypeListCache.cacheCounts[(int)CacheCountType.Trim]);
#endif
#else
                            comTypeListCache.Clear();

#if CACHE_STATISTICS
                            Interlocked.Increment(
                                ref comTypeListCache.cacheCounts[(int)CacheCountType.Clear]);
#endif
#endif
                        }

                        if ((MaximumCacheItemSize > 0) &&
                            (types != null) &&
                            (types.Count > MaximumCacheItemSize))
                        {
                            return false;
                        }

                        if (comTypeListCache.ContainsKey(unknown))
                            return false;

                        comTypeListCache.Add(unknown, types);

#if CACHE_STATISTICS
                        Interlocked.Increment(
                            ref comTypeListCache.cacheCounts[(int)CacheCountType.Add]);
#endif

                        return true;
                    }
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool RemoveCachedComTypeList(
            IntPtr unknown
            )
        {
            lock (syncRoot)
            {
                if (FlagOps.HasFlags(cacheFlags, CacheFlags.ComTypeList, true))
                {
                    if ((unknown != IntPtr.Zero) && (comTypeListCache != null))
                    {
                        bool result = comTypeListCache.Remove(unknown);

#if CACHE_STATISTICS
                        if (result)
                        {
                            Interlocked.Increment(
                                ref comTypeListCache.cacheCounts[(int)CacheCountType.Remove]);
                        }
#endif

                        return result;
                    }
                }
            }

            return false;
        }
        #endregion
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Core Trace Callbacks
        #region Support Methods
        private static void SetTraceInfoForGetResult(
            ITraceInfo traceInfo,
            ReturnCode code,
            object oldValue
            )
        {
            if (traceInfo != null)
            {
                traceInfo.OldValue = oldValue;
                traceInfo.Cancel = true;
                traceInfo.ReturnCode = code;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void SetTraceInfoForGetResult(
            ITraceInfo traceInfo,
            ReturnCode code,
            Result result
            )
        {
            SetTraceInfoForGetResult(traceInfo, code,
                (object)StringOps.GetStringFromObject(result));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void SetTraceInfoForSetResult(
            ITraceInfo traceInfo,
            IVariable variable,
            object oldValue,
            object newValue,
            ReturnCode code,
            ref Result result
            )
        {
            //
            // HACK: This result is not 100% correct;
            //       however, we do not really care.
            //       Firstly, setting the overall
            //       result is entirely optional for
            //       trace callbacks that "succeed".
            //       Secondly, using FixupReturnValue
            //       (or similar) method here would
            //       potentially create opaque object
            //       handles which would then just be
            //       leaked because they would never
            //       actually even be seen by the
            //       calling script.  At some point,
            //       it might be worthwhile to use
            //       the FixupReturnValue method here
            //       with the value of the toString
            //       parameter hard-wired to true.
            //
            result = StringOps.GetStringFromObject(newValue);

            EntityOps.SetUndefined(variable, false);
            EntityOps.SetDirty(variable, true);

            if (traceInfo != null)
            {
                traceInfo.OldValue = oldValue;
                traceInfo.NewValue = newValue;
                traceInfo.Cancel = true;
                traceInfo.ReturnCode = code;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region AutoPath Trace Callback
        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode AutoPathTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            //
            // NOTE: Intercept writes to the variable "auto_path" and figure
            //       out if we need to rescan for package indexes.
            //
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: Make sure that an array element index was not specified.
            //
            //       *WARNING* Empty array element names are allowed,
            //       please do not change this to "!String.IsNullOrEmpty".
            //
            if (traceInfo.Index == null)
            {
                switch (breakpointType)
                {
                    case BreakpointType.BeforeVariableSet:
                        {
                            PackageIndexDictionary packageIndexes = interpreter.CopyPackageIndexes();

                            //
                            // BUGFIX: Save and restore the current [shared] traceInfo object [for
                            //         this thread] because we may evaluate an arbitrary number of
                            //         scripts during our package index scan and any variable
                            //         accesses will cause the [shared] traceInfo object for this
                            //         thread to change out from under us.
                            //
                            ITraceInfo oldTraceInfo = traceInfo.Copy();

                            try
                            {
                                //
                                // NOTE: We do not really want to force a refresh here; however,
                                //       since we have no easy way of actually knowing which
                                //       package index file and by logical extension, which
                                //       directory, provided the "ifneeded" commands for a given
                                //       package, we must refresh all directories to be accurate.
                                //
                                StringList list = null;

                                if ((Parser.SplitList(
                                        interpreter, StringOps.GetStringFromObject(
                                        traceInfo.NewValue), 0, Length.Invalid, true,
                                        ref list, ref result) == ReturnCode.Ok) &&
                                    (PackageOps.FindAll(
                                        interpreter, list, true, true, false, false,
                                        ref packageIndexes, ref result) == ReturnCode.Ok))
                                {
                                    interpreter.PackageIndexes = packageIndexes;
                                }
                                else
                                {
                                    return ReturnCode.Error;
                                }
                            }
                            finally
                            {
                                traceInfo.Update(oldTraceInfo);
                            }
                            break;
                        }
                    case BreakpointType.BeforeVariableUnset:
                        {
                            //
                            // NOTE: They want to unset the auto_path variable.  I guess
                            //       this should be allowed, it is in Tcl.  Also, make
                            //       sure it is purged from the call frame so that it
                            //       cannot be magically restored with this trace
                            //       callback in place.
                            //
                            traceInfo.Flags &= ~VariableFlags.NoRemove;

                            //
                            // BUGFIX: Yes, also make sure any waiters are cleared.
                            //
                            EntityOps.SetDirty(variable, true);

                            //
                            // NOTE: Ok, it appears that Tcl handles this by forgetting
                            //       all package index information; therefore, we will
                            //       emulate that behavior.
                            //
                            if (interpreter.ResetPkgIndexes(ref result) != ReturnCode.Ok)
                                return ReturnCode.Error;

                            break;
                        }
                }

                return ReturnCode.Ok;
            }
            else
            {
                //
                // NOTE: We expect "auto_path" to always be a scalar list variable.
                //
                result = String.Format("can't {0} {1}: variable isn't array",
                    FormatOps.Breakpoint(breakpointType),
                    FormatOps.ErrorVariableName(variable.Name, traceInfo.Index));
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Environment Trace Callback
        #region Support Methods
        private static bool HasEnvironmentTraceCallback(
            IVariable variable
            )
        {
            return (variable != null) &&
                (variable.Traces != null) &&
                variable.Traces.Contains(EnvironmentTraceCallback);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsEnvironmentVariable(IVariable variable)
        {
            return (variable != null) &&
                IsGlobalCallFrame(variable.Frame) &&
                (String.Compare(variable.Name, TclVars.Environment,
                    StringOps.SystemStringComparisonType) == 0) &&
                !HasNoTraces() && HasEnvironmentTraceCallback(variable);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode EnvironmentTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            //
            // NOTE: Intercept reads and writes to the variable "env" and redirect
            //       them to get and set environment variables.
            //
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: *SPECIAL* Ignore the index when we initially add the variable
            //       since we do not perform any trace actions during add anyhow.
            //
            //       *WARNING* Empty array element names are allowed,
            //       please do not change this to "!String.IsNullOrEmpty".
            //
            if ((breakpointType == BreakpointType.BeforeVariableAdd) ||
                (traceInfo.Index != null))
            {
                string oldValue = null;

                bool exists = (traceInfo.Index != null) ?
                    CommonOps.Environment.DoesVariableExist(
                        traceInfo.Index, ref oldValue) : false;

                switch (breakpointType)
                {
                    case BreakpointType.BeforeVariableGet:
                        {
                            if (exists)
                            {
                                try
                                {
                                    result = oldValue;

                                    traceInfo.OldValue = oldValue;
                                    traceInfo.Cancel = true;
                                    traceInfo.ReturnCode = ReturnCode.Ok;
                                }
                                catch (Exception e)
                                {
                                    result = e;
                                    traceInfo.ReturnCode = ReturnCode.Error;
                                }
                            }
                            else
                            {
                                result = String.Format(
                                    "can't read {0}: no such element in array",
                                    FormatOps.ErrorVariableName(variable.Name,
                                    traceInfo.Index));
                            }
                            break;
                        }
                    case BreakpointType.BeforeVariableSet:
                        {
                            try
                            {
                                string newValue = StringOps.GetStringFromObject(traceInfo.NewValue);

                                CommonOps.Environment.SetVariable(traceInfo.Index, newValue);

                                result = newValue;

                                EntityOps.SetUndefined(variable, false);
                                EntityOps.SetDirty(variable, true);

                                //
                                // BUGFIX: Must set the old and new values in case they
                                //         are opaque object handles.
                                //
                                traceInfo.OldValue = oldValue;
                                traceInfo.NewValue = newValue;
                                traceInfo.Cancel = true;
                                traceInfo.ReturnCode = ReturnCode.Ok;
                            }
                            catch (Exception e)
                            {
                                result = e;
                                traceInfo.ReturnCode = ReturnCode.Error;
                            }
                            break;
                        }
                    case BreakpointType.BeforeVariableUnset:
                        {
                            if (exists)
                            {
                                try
                                {
                                    CommonOps.Environment.SetVariable(traceInfo.Index, null);

                                    result = String.Empty;

                                    EntityOps.SetDirty(variable, true);

                                    //
                                    // BUGFIX: Must set the old value in case it was an
                                    //         opaque object handle.
                                    //
                                    traceInfo.OldValue = oldValue;
                                    traceInfo.Cancel = true;
                                    traceInfo.ReturnCode = ReturnCode.Ok;
                                }
                                catch (Exception e)
                                {
                                    result = e;
                                    traceInfo.ReturnCode = ReturnCode.Error;
                                }
                            }
                            else if (!FlagOps.HasFlags(
                                    traceInfo.Flags, VariableFlags.NoComplain, true))
                            {
                                result = String.Format(
                                    "can't unset {0}: no such element in array",
                                    FormatOps.ErrorVariableName(variable.Name,
                                    traceInfo.Index));
                            }
                            else
                            {
                                //
                                // BUGFIX: Do not return an error if the "NoComplain"
                                //         flag has been set by the caller.
                                //
                                // NOTE: The default handling sets an error message
                                //       into the result for this case and we do not
                                //       want that; therefore, cancel the default
                                //       action.
                                //
                                traceInfo.Cancel = true;
                                traceInfo.ReturnCode = ReturnCode.Ok;
                            }
                            break;
                        }
                }

                return traceInfo.ReturnCode;
            }
            else if (breakpointType == BreakpointType.BeforeVariableUnset)
            {
                //
                // NOTE: They want to unset the entire env array.  I guess
                //       this should be allowed, it is in Tcl.  Also, make
                //       sure it is purged from the call frame so that it
                //       cannot be magically restored with this trace
                //       callback in place.
                //
                traceInfo.Flags &= ~VariableFlags.NoRemove;

                //
                // BUGFIX: Must make the entire array "concrete" now just
                //         in case there are any opaque object handles
                //         that need to be picked up by later traces (e.g.
                //         ObjectTraceCallback).
                //
                if (EntityOps.IsArray2(variable))
                {
                    variable.ArrayValue = new ElementDictionary(
                        interpreter.PrivateVariableEvent,
                        Environment.GetEnvironmentVariables());
                }

                return ReturnCode.Ok;
            }
            else
            {
                //
                // NOTE: We (this trace procedure) expect the "env" variable
                //       to always be an array.
                //
                result = String.Format(
                    "can't {0} {1}: variable is array",
                    FormatOps.Breakpoint(breakpointType),
                    FormatOps.ErrorVariableName(variable.Name, null));
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Object Trace Callback
        #region Support Methods
        internal ReturnCode AddObjectReference(
            ReturnCode code,
            Result result,
            ref Result error
            )
        {
            bool added = false;

            return AddObjectReference(code, result, ref added, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode AddObjectReference(
            ReturnCode code,
            Result result,
            ref bool added,
            ref Result error /* NOT USED */
            )
        {
            //
            // NOTE: Declare a variable for the formal interface for the
            //       objects that we track.
            //
            IObject @object = null;

            //
            // NOTE: Check to see if the new variable value refers to a live
            //       object handle.
            //
            if ((result != null) && GetObject(
                    StringOps.GetStringFromObject(result),
                    LookupFlags.NoVerbose, ref @object) == ReturnCode.Ok)
            {
                //
                // NOTE: Attempt to cast the object to the proper wrapper
                //       type and then invalidate the object.
                //
                _Wrappers._Object newWrapper = @object as _Wrappers._Object;
                @object = null;

                //
                // NOTE: If the new wrapper object is valid, add a reference
                //       to it.
                //
                if (newWrapper != null)
                {
                    //
                    // NOTE: Do not attempt to manage reference counts for
                    //       locked objects.
                    //
                    if (!FlagOps.HasFlags(
                            newWrapper.Flags, ObjectFlags.Locked, true))
                    {
                        //
                        // NOTE: Add a reference to the new wrapper object.
                        //
                        newWrapper.ReferenceCount++;

                        //
                        // NOTE: We successfully added a reference to the
                        //       object.
                        //
                        added = true;
                    }

                    newWrapper = null;
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode RemoveObjectReference(
            ReturnCode code,
            Result result,
            bool alias,
            ref Result error
            )
        {
            bool removed = false;

            return RemoveObjectReference(code, result, alias, ref removed, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode RemoveObjectReference(
            ReturnCode code,
            Result result,
            bool alias,
            ref bool removed,
            ref Result error /* NOT USED */
            )
        {
            //
            // NOTE: Declare a variable for the formal interface for the
            //       objects that we track.
            //
            IObject @object = null;

            //
            // NOTE: Check to see if the new variable value refers to a live
            //       object handle.
            //
            if ((result != null) && GetObject(
                    StringOps.GetStringFromObject(result),
                    LookupFlags.NoVerbose, ref @object) == ReturnCode.Ok)
            {
                //
                // NOTE: Attempt to cast the object to the proper wrapper type
                //       and then invalidate the object.
                //
                _Wrappers._Object oldWrapper = @object as _Wrappers._Object;
                @object = null;

                //
                // NOTE: If the old wrapper object is valid, remove a reference
                //       from it.
                //
                if (oldWrapper != null)
                {
                    //
                    // NOTE: Do not attempt to manage reference counts for
                    //       locked objects.
                    //
                    if (!FlagOps.HasFlags(
                            oldWrapper.Flags, ObjectFlags.Locked, true))
                    {
                        //
                        // NOTE: Remove a reference from the old wrapper
                        //       object.  If there are no more outstanding
                        //       references to the underlying object, dipose
                        //       and remove it now.
                        //
                        if (--oldWrapper.ReferenceCount <= 0)
                        {
                            ReturnCode removeCode;
                            Result removeResult = null;

                            removeCode = RemoveObject(
                                EntityOps.GetToken(oldWrapper), null,
                                ObjectOps.GetDefaultSynchronous(), alias,
                                ref removeResult);

                            if (removeCode == ReturnCode.Ok)
                            {
                                //
                                // NOTE: We successfully removed the object
                                //       from the interpreter.
                                //
                                removed = true;
                            }
                            else
                            {
                                //
                                // NOTE: Complain loudly if we could not remove
                                //       the object because this indicates an
                                //       error probably occurred during the
                                //       disposal of the object.
                                //
                                DebugOps.Complain(
                                    this, removeCode, removeResult);

                                //
                                // NOTE: If any of the objects cannot be
                                //       removed, the overall result will be an
                                //       error (even if some of the objects are
                                //       successfully removed).
                                //
                                result = removeResult;
                                code = removeCode;
                            }
                        }
                    }

                    oldWrapper = null;
                }
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        internal static ReturnCode ObjectTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            //
            // NOTE: Only intercept attempted set and unset operations on
            //       variable values that could represent opaque object
            //       handles.
            //
            if (!ScriptOps.IsWriteValueTrace(breakpointType))
            {
                //
                // NOTE: We do not care about this type of variable trace;
                //       however, we cannot simply return the returnCode
                //       contained within the traceInfo object because the
                //       original result could have been an error (e.g. get
                //       access to the "env" array) and we do not want this
                //       trace to be considered a failure.  The traceInfo
                //       object itself is not being changed; therefore, the
                //       original returnCode within it is preserved for the
                //       caller(s) to use later.
                //
                return ReturnCode.Ok;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            if (FlagOps.HasFlags(traceInfo.Flags, VariableFlags.NoObject, true))
            {
                //
                // NOTE: Completely skip all processing of this variable trace.
                //       The caller certifies that none of the values contained
                //       within the trace require object reference counting.
                //
                return ReturnCode.Ok;
            }

            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: Declare a variable for the formal interface for
            //       the objects that we track.
            //
            IObject @object = null; /* RE-USED */

            //
            // NOTE: This is the list of old variable values to
            //       check for opaque object handles (i.e. to
            //       decrease the reference counts on).
            //
            StringList oldValues = null;

            //
            // NOTE: For the purposes of processing this trace, do
            //       we need the old [array related] values?
            //
            bool needOldArrayValueForTrace =
                ScriptOps.NeedArrayValueForTrace(breakpointType, true);

            //
            // BUGFIX: *SPECIAL CASE* If the variable is [already]
            //         undefined, we must skip adding any old values
            //         from it; otherwise, once a variable with an
            //         opaque object handle has been unset, the
            //         variable can never be used for that same
            //         object handle again.  This bug can only be
            //         seen by using exactly the same opaque object
            //         handle name for both the old and new values.
            //
            if (!EntityOps.IsUndefined(variable))
            {
                //
                // NOTE: Handle resetting or unsetting an entire
                //       array, if necessary.
                //
                ElementDictionary arrayValue = null;

                if (needOldArrayValueForTrace &&
                    (traceInfo.Index == null) &&
                    EntityOps.IsArray(variable, ref arrayValue))
                {
                    //
                    // HACK: Delve into the array dictionary directly
                    //       and extract all the keys and values that
                    //       are about to be reset or unset.
                    //
                    ScriptOps.GatherTraceValues(
                        null, null, arrayValue, ref oldValues);
                }
                else if (traceInfo.OldValue != null)
                {
                    //
                    // NOTE: Add the one and only old value to the
                    //       list of old values.
                    //
                    ScriptOps.GatherTraceValues(
                        null, traceInfo.OldValue, null,
                        ref oldValues);
                }
            }

            //
            // NOTE: Add any extra old values provided with the trace.
            //       Currently, this is only used by [array set].
            //
            ScriptOps.GatherTraceValues(
                needOldArrayValueForTrace ? traceInfo.Index : null,
                null, traceInfo.OldValues, ref oldValues);

            //
            // NOTE: This is the master list of new variable values to
            //       check for opaque object handles (i.e. to increase
            //       the reference counts on).
            //
            StringList newValues = null;

            //
            // NOTE: For the purposes of processing this trace, do
            //       we need the new [array related] values?
            //
            bool needNewArrayValueForTrace =
                ScriptOps.NeedArrayValueForTrace(breakpointType, false);

            //
            // NOTE: Add the new value to the list of new values.
            //       Also, add the extra new values (currently only
            //       used by [array set]) to the master list of new
            //       values.
            //
            ScriptOps.GatherTraceValues(
                needNewArrayValueForTrace ? traceInfo.Index : null,
                traceInfo.NewValue, traceInfo.NewValues,
                ref newValues);

            //
            // NOTE: For each new value (i.e. there are potentially
            //       multiple when handling an array).
            //
            if (newValues != null)
            {
                foreach (string newValue in newValues)
                {
                    //
                    // NOTE: Check to see if the old variable value
                    //       referred to a live object handle.
                    //
                    if ((newValue != null) &&
                        interpreter.GetObject(
                            newValue, LookupFlags.NoVerbose,
                            ref @object) == ReturnCode.Ok)
                    {
                        //
                        // NOTE: Attempt to cast the object to the proper
                        //       wrapper type and then invalidate the
                        //       object.
                        //
                        _Wrappers._Object newWrapper =
                            @object as _Wrappers._Object;

                        @object = null;

                        //
                        // NOTE: If the new wrapper object is valid, add
                        //       a reference to it.
                        //
                        if (newWrapper != null)
                        {
                            //
                            // NOTE: Do not attempt to manage reference
                            //       counts for locked objects.
                            //
                            if (!FlagOps.HasFlags(newWrapper.Flags,
                                    ObjectFlags.Locked, true))
                            {
                                newWrapper.ReferenceCount++;
                            }

                            newWrapper = null;
                        }
                    }
                }
            }

            //
            // NOTE: If there are no old values then we are done.
            //
            if (oldValues == null)
                return ReturnCode.Ok;

            //
            // NOTE: This return code is only used when removing
            //       objects (i.e. when they have no more outstanding
            //       references). If any of the objects to be removed
            //       return an error, this return code will reflect
            //       that.
            //
            ReturnCode code = ReturnCode.Ok;

            //
            // NOTE: For each old value (i.e. there are potentially
            //       multiple when handling an array).
            //
            foreach (string oldValue in oldValues)
            {
                //
                // NOTE: Check to see if the old variable value
                //       referred to a live object handle.
                //
                if ((oldValue != null) &&
                    interpreter.GetObject(
                        oldValue, LookupFlags.NoVerbose,
                        ref @object) == ReturnCode.Ok)
                {
                    //
                    // NOTE: Attempt to cast the object to the
                    //       proper wrapper type and then invalidate
                    //       the object.
                    //
                    _Wrappers._Object oldWrapper =
                        @object as _Wrappers._Object;

                    @object = null;

                    //
                    // NOTE: If the old wrapper object is valid,
                    //       release a reference from it.
                    //
                    if (oldWrapper != null)
                    {
                        //
                        // NOTE: Do not attempt to manage reference
                        //       counts for locked objects.
                        //
                        if (!FlagOps.HasFlags(oldWrapper.Flags,
                                ObjectFlags.Locked, true))
                        {
                            //
                            // NOTE: If there are no more outstanding
                            //       references to the underlying object,
                            //       dipose and remove it now.
                            //
                            if (--oldWrapper.ReferenceCount <= 0)
                            {
                                //
                                // NOTE: We know the opaque object handle
                                //       must be removed; however, if the
                                //       opaque object handle is flagged
                                //       as "no automatic disposal", we
                                //       must honor that and not dispose
                                //       the actual underlying object
                                //       instance.
                                //
                                if (FlagOps.HasFlags(oldWrapper.Flags,
                                        ObjectFlags.NoAutoDispose, true))
                                {
                                    //
                                    // HACK: Prevent the RemoveObject
                                    //       method from disposing the
                                    //       object.
                                    //
                                    oldWrapper.Flags |= ObjectFlags.NoDispose;
                                }

                                ReturnCode removeCode;
                                Result removeResult = null;

                                removeCode = interpreter.RemoveObject(
                                    EntityOps.GetToken(oldWrapper),
                                    null, ObjectOps.GetDefaultSynchronous(),
                                    ref removeResult);

                                if (removeCode != ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Complain loudly if we could
                                    //       not remove the object because
                                    //       this indicates an error probably
                                    //       occurred during the disposal of
                                    //       the object.
                                    //
                                    DebugOps.Complain(
                                        interpreter, removeCode, removeResult);

                                    //
                                    // NOTE: If any of the objects cannot be
                                    //       removed, the overall result will
                                    //       be an error (even if some of the
                                    //       objects are successfully removed).
                                    //
                                    result = removeResult;
                                    code = removeCode;
                                }
                            }
                        }

                        oldWrapper = null;
                    }
                }
            }

            return code;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Precision Trace Callback
        #region Support Methods
        internal int PrivatePrecision
        {
            set { lock (syncRoot) { precision = value; } }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode PrecisionTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            //
            // NOTE: Sync up our copy of the integer value with what the
            //       script-level knows about.
            //
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: Make sure that an array element index was not specified.
            //
            //       *WARNING* Empty array element names are allowed,
            //       please do not change this to "String.IsNullOrEmpty".
            //
            if (traceInfo.Index == null)
            {
                if (breakpointType == BreakpointType.BeforeVariableSet)
                {
                    int precision = 0;

                    traceInfo.ReturnCode = Value.GetInteger2(
                        StringOps.GetStringFromObject(traceInfo.NewValue),
                        ValueFlags.AnyInteger, interpreter.CultureInfo,
                        ref precision, ref result);

                    if (traceInfo.ReturnCode == ReturnCode.Ok)
                        interpreter.PrivatePrecision = precision;
                }
                else if (breakpointType == BreakpointType.BeforeVariableUnset)
                {
                    //
                    // NOTE: They want to unset the tcl_precision variable.  I
                    //       guess this should be allowed, it is in Tcl.  Also,
                    //       make sure it is purged from the call frame so that
                    //       it cannot be magically restored with this trace
                    //       callback in place.  For this variable, this
                    //       behavior is not 100% compatible with Tcl; however,
                    //       it is internally consistent with other traced
                    //       Eagle variables.
                    //
                    traceInfo.Flags &= ~VariableFlags.NoRemove;

                    //
                    // BUGFIX: Yes, also make sure any waiters are cleared.
                    //
                    EntityOps.SetDirty(variable, true);
                }

                return traceInfo.ReturnCode;
            }
            else
            {
                //
                // NOTE: We expect "tcl_precision" to always be a
                //       scalar variable.
                //
                result = String.Format(
                    "can't {0} {1}: variable isn't array",
                    FormatOps.Breakpoint(breakpointType),
                    FormatOps.ErrorVariableName(variable.Name,
                    traceInfo.Index));
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tests Trace Callback
        #region Support Methods
        private static bool HasTestsTraceCallback(IVariable variable)
        {
            return (variable != null) &&
                (variable.Traces != null) &&
                variable.Traces.Contains(TestsTraceCallback);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsTestsVariable(IVariable variable)
        {
            return (variable != null) &&
                IsGlobalCallFrame(variable.Frame) &&
                (String.Compare(variable.Name, Vars.Tests,
                    StringOps.SystemStringComparisonType) == 0) &&
                !HasNoTraces() && HasTestsTraceCallback(variable);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool DoesTestsVariableExist(string name)
        {
            object enumValue = EnumOps.TryParseEnum(
                typeof(TestInformationType), name, true);

            if (enumValue is TestInformationType)
            {
                Result result = null;

                if (GetTestInformation(
                        (TestInformationType)enumValue,
                        ref result) == ReturnCode.Ok)
                {
                    return true;
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetTestInformation(
            TestInformationType type,
            ref Result result
            )
        {
            switch (type)
            {
                case TestInformationType.Constraints:
                    {
                        result = TestConstraints;
                        return ReturnCode.Ok;
                    }
#if DEBUGGER
                case TestInformationType.Breakpoints:
                    {
                        result = TestBreakpoints.KeysAndValuesToString(null, false);
                        return ReturnCode.Ok;
                    }
#endif
                case TestInformationType.Counts:
                    {
                        result = TestCounts.KeysAndValuesToString(null, false);
                        return ReturnCode.Ok;
                    }
                case TestInformationType.SkippedNames:
                    {
                        result = TestSkipped;
                        return ReturnCode.Ok;
                    }
                case TestInformationType.FailedNames:
                    {
                        result = TestFailures;
                        return ReturnCode.Ok;
                    }
                case TestInformationType.SkipNames:
                    {
                        result = TestSkip;
                        return ReturnCode.Ok;
                    }
                case TestInformationType.MatchNames:
                    {
                        result = TestMatch;
                        return ReturnCode.Ok;
                    }
                case TestInformationType.Level:
                    {
                        result = TestLevels;
                        return ReturnCode.Ok;
                    }
                case TestInformationType.Total:
                case TestInformationType.Skipped:
                case TestInformationType.Passed:
                case TestInformationType.Failed:
                    {
                        result = TestStatistics[(int)type];
                        return ReturnCode.Ok;
                    }
                default:
                    {
                        result = ScriptOps.BadValue(
                            null, "test information type", type.ToString(),
                            Enum.GetNames(typeof(TestInformationType)),
                            null, null);

                        break;
                    }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal StringDictionary GetAllTestInformation(
            bool values,
            ref Result error
            )
        {
            StringDictionary tests = new StringDictionary();

            foreach (TestInformationType type in new TestInformationType[] {
                    TestInformationType.Constraints,
#if DEBUGGER
                    TestInformationType.Breakpoints,
#endif
                    TestInformationType.Counts, TestInformationType.SkippedNames,
                    TestInformationType.FailedNames, TestInformationType.SkipNames,
                    TestInformationType.MatchNames, TestInformationType.Level,
                    TestInformationType.Total, TestInformationType.Skipped,
                    TestInformationType.Passed, TestInformationType.Failed })
            {
                Result result = null;

                if (values &&
                    GetTestInformation(type, ref result) != ReturnCode.Ok)
                {
                    error = result;
                    return null;
                }

                tests.Add(type.ToString(), result);
            }

            return tests;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode TestsTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            //
            // NOTE: Intercept reads and writes to the variable "tests" and redirect
            //       them to get and set interpreter state variables.
            //
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: *SPECIAL* Ignore the index when we initially add the variable
            //       since we do not perform any trace actions during add anyhow.
            //
            //       *WARNING* Empty array element names are allowed,
            //       please do not change this to "!String.IsNullOrEmpty".
            //
            if (breakpointType != BreakpointType.BeforeVariableAdd)
            {
                if (traceInfo.Index != null)
                {
                    object enumValue = EnumOps.TryParseEnum(
                        typeof(TestInformationType), traceInfo.Index,
                        true, ref result);

                    if (enumValue is TestInformationType)
                    {
                        TestInformationType informationType = (TestInformationType)enumValue;

                        switch (breakpointType)
                        {
                            case BreakpointType.BeforeVariableGet:
                                {
                                    traceInfo.ReturnCode = interpreter.GetTestInformation(
                                        informationType, ref result);

                                    traceInfo.Cancel = true;
                                    break;
                                }
                            case BreakpointType.BeforeVariableSet:
                                {
                                    if (informationType == TestInformationType.Constraints)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestConstraints = list;
                                    }
#if DEBUGGER
                                    else if (informationType == TestInformationType.Breakpoints)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestBreakpoints = new StringDictionary(list, true, false);
                                    }
#endif
                                    else if (informationType == TestInformationType.Counts)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestCounts = new IntDictionary(
                                                list, interpreter.CultureInfo);
                                    }
                                    else if (informationType == TestInformationType.SkippedNames)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestSkipped = list;
                                    }
                                    else if (informationType == TestInformationType.FailedNames)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestFailures = list;
                                    }
                                    else if (informationType == TestInformationType.SkipNames)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestSkip = list;
                                    }
                                    else if (informationType == TestInformationType.MatchNames)
                                    {
                                        StringList list = null;

                                        //
                                        // WARNING: Cannot cache list representation here, the list
                                        //          may be modified via the public property in the
                                        //          future.
                                        //
                                        traceInfo.ReturnCode = Parser.SplitList(
                                            interpreter, StringOps.GetStringFromObject(
                                            traceInfo.NewValue), 0, Length.Invalid, false,
                                            ref list, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                            interpreter.TestMatch = list;
                                    }
                                    else if (informationType == TestInformationType.Level)
                                    {
                                        int newValue = 0;

                                        traceInfo.ReturnCode = Value.GetInteger2(
                                            StringOps.GetStringFromObject(traceInfo.NewValue),
                                            ValueFlags.AnyInteger, interpreter.CultureInfo,
                                            ref newValue, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                        {
                                            interpreter.TestLevels = newValue;
                                            result = newValue;
                                        }
                                    }
                                    else
                                    {
                                        int newValue = 0;

                                        traceInfo.ReturnCode = Value.GetInteger2(
                                            StringOps.GetStringFromObject(traceInfo.NewValue),
                                            ValueFlags.AnyInteger, interpreter.CultureInfo,
                                            ref newValue, ref result);

                                        if (traceInfo.ReturnCode == ReturnCode.Ok)
                                        {
                                            interpreter.TestStatistics[(int)informationType] = newValue;
                                            result = newValue;
                                        }
                                    }

                                    if (traceInfo.ReturnCode == ReturnCode.Ok)
                                    {
                                        EntityOps.SetUndefined(variable, false);
                                        EntityOps.SetDirty(variable, true);
                                    }

                                    traceInfo.Cancel = true;
                                    break;
                                }
                            case BreakpointType.BeforeVariableUnset:
                                {
                                    result = String.Format(
                                        "cannot unset \"{0}\", it is a linked variable",
                                        variable.Name);

                                    traceInfo.Cancel = true;
                                    traceInfo.ReturnCode = ReturnCode.Error;
                                    break;
                                }
                        }

                        return traceInfo.ReturnCode;
                    }
                }
                else if (breakpointType == BreakpointType.BeforeVariableUnset)
                {
                    //
                    // NOTE: They want to unset the entire tests array.  I guess
                    //       this should be allowed.  Also, make sure it is purged
                    //       from the call frame so that it cannot be magically
                    //       restored with this trace callback in place.
                    //
                    traceInfo.Flags &= ~VariableFlags.NoRemove;

                    return ReturnCode.Ok;
                }
                else
                {
                    //
                    // NOTE: We (this trace procedure) expect the "tests" variable
                    //       to always be an array.
                    //
                    result = String.Format(
                        "can't {0} {1}: variable is array",
                        FormatOps.Breakpoint(breakpointType),
                        FormatOps.ErrorVariableName(variable.Name, null));
                }
            }
            else
            {
                //
                // NOTE: Skip add operations altogether.
                //
                return ReturnCode.Ok;
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Linked Variable Trace Callback
        #region Support Methods
        private static bool HasLinkedVariableTraceCallback(
            IVariable variable
            )
        {
            return (variable != null) &&
                (variable.Traces != null) &&
                variable.Traces.Contains(LinkedVariableTraceCallback);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode ChangeType(
            string text,
            Type type,
            ref object value,
            ref Result error
            )
        {
            if (type == typeof(string))
            {
                value = text;
                return ReturnCode.Ok;
            }

            if (binder == null)
            {
                error = "invalid binder";
                return ReturnCode.Error;
            }

            lock (syncRoot)
            {
                try
                {
                    value = binder.ChangeType(text, type, cultureInfo);

                    return ReturnCode.Ok;
                }
                catch (Exception e)
                {
                    error = e;
                }
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode LinkedVariableTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            if ((breakpointType != BreakpointType.BeforeVariableGet) &&
                (breakpointType != BreakpointType.BeforeVariableSet) &&
                (breakpointType != BreakpointType.BeforeVariableUnset))
            {
                return ReturnCode.Ok;
            }

            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: If the variable link is still being initially setup,
            //       skip all other handling.
            //
            if ((breakpointType == BreakpointType.BeforeVariableSet) &&
                EntityOps.IsUndefined(variable))
            {
                return ReturnCode.Ok;
            }

            //
            // NOTE: Grab the trace information we will need.
            //
            string name = traceInfo.Name;
            string index = traceInfo.Index;
            ElementDictionary arrayValue = null;

            //
            // NOTE: Is the variable an array?  If so, also get the
            //       actual backing storage for it.
            //
            bool isArray = EntityOps.IsArray(variable, ref arrayValue);

            //
            // NOTE: If applicable, does the array element exist?
            //
            bool exists = isArray && (index != null) ?
                arrayValue.ContainsKey(index) : false;

            if (breakpointType == BreakpointType.BeforeVariableUnset)
            {
                if (index != null)
                {
                    if (isArray)
                    {
                        //
                        // NOTE: Unset one array element.
                        //
                        if (exists)
                        {
                            //
                            // NOTE: Must grab the "real" old value in case we
                            //       need to adjust the reference count for it.
                            //
                            object oldValue = null;

                            ScriptOps.GetLinkedVariableMemberValue(
                                interpreter, traceInfo.OldValue, ref oldValue);

                            if (oldValue != null)
                                traceInfo.OldValue = oldValue;

                            traceInfo.ReturnCode = ReturnCode.Ok;
                        }
                        else if (!FlagOps.HasFlags(
                            traceInfo.Flags, VariableFlags.NoComplain, true))
                        {
                            result = String.Format(
                                "can't unset {0}: no such element in array",
                                FormatOps.ErrorVariableName(
                                    variable, null, variable.Name, index));

                            traceInfo.ReturnCode = ReturnCode.Error;
                        }
                        else
                        {
                            //
                            // NOTE: The default handling sets an error message
                            //       into the result for this case and we do not
                            //       want that; therefore, cancel the default
                            //       action.
                            //
                            traceInfo.Cancel = true;
                            traceInfo.ReturnCode = ReturnCode.Ok;
                        }
                    }
                    else
                    {
                        //
                        // NOTE: Error, unset index with non-array?
                        //
                        result = String.Format(
                            "can't unset {0}: variable isn't array",
                            FormatOps.ErrorVariableName(
                                variable, null, variable.Name, index));

                        traceInfo.ReturnCode = ReturnCode.Error;
                    }
                }
                else
                {
                    //
                    // NOTE: They want to unset the entire array.  Also, make
                    //       sure it is purged from the call frame so that it
                    //       cannot be magically restored with this trace
                    //       callback in place.
                    //
                    traceInfo.Flags &= ~VariableFlags.NoRemove;

                    //
                    // NOTE: Must grab the "real" old value in case we need
                    //       to adjust the reference count for it.
                    //
                    object oldValue = traceInfo.OldValue;

                    if (oldValue != null)
                    {
                        ScriptOps.GetLinkedVariableMemberValue(
                            interpreter, oldValue, ref oldValue);

                        if (oldValue != null)
                            traceInfo.OldValue = oldValue;
                    }

                    //
                    // BUGFIX: Must make the entire array "concrete" now just
                    //         in case there are any opaque object handles
                    //         that need to be picked up by later traces (e.g.
                    //         ObjectTraceCallback).
                    //
                    if (arrayValue != null)
                    {
                        ElementDictionary oldValues = null;

                        ScriptOps.GetLinkedVariableArrayValues(
                            interpreter, arrayValue, ref oldValues);

                        ScriptOps.AddOldValuesToTraceInfo(
                            interpreter, traceInfo, oldValues);
                    }

                    //
                    // NOTE: If we get this far, everything went fine.
                    //
                    traceInfo.ReturnCode = ReturnCode.Ok;
                }
            }
            else if (isArray == (index != null))
            {
                ReturnCode code;
                MemberInfo memberInfo = null;
                Type type = null;
                object @object = null;
                object memberValue = null;

                code = ScriptOps.GetLinkedVariableMemberAndValue(
                    breakpointType, variable, name, index,
                    traceInfo.OldValue, ref memberInfo, ref type,
                    ref @object, ref memberValue, ref result);

                if (code == ReturnCode.Ok)
                {
                    switch (breakpointType)
                    {
                        case BreakpointType.BeforeVariableGet:
                            {
                                if (!isArray || exists)
                                {
                                    code = MarshalOps.GetVariableValueAsString(
                                        interpreter, memberValue, true, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        SetTraceInfoForGetResult(
                                            traceInfo, code, result);
                                    }
                                    else
                                    {
                                        traceInfo.ReturnCode = code;
                                    }
                                }
                                else
                                {
                                    result = String.Format(
                                        "can't read {0}: no such element in array",
                                        FormatOps.ErrorVariableName(
                                            variable, null, variable.Name, index));

                                    traceInfo.ReturnCode = ReturnCode.Error;
                                }
                                break;
                            }
                        case BreakpointType.BeforeVariableSet:
                            {
                                object newValue = traceInfo.NewValue;

                                if (newValue is string)
                                {
                                    //
                                    // HACK: We do not officially support
                                    //       any array types here (yet?);
                                    //       however, for one dimensional
                                    //       string arrays, just use a
                                    //       StringList.
                                    //
                                    if (type == typeof(string[]))
                                    {
                                        StringList list = null;

                                        code = Parser.SplitList(
                                            interpreter, (string)newValue,
                                            0, Length.Invalid, true, ref list,
                                            ref result);

                                        if (code == ReturnCode.Ok)
                                            newValue = list.ToArray();
                                    }
                                    else
                                    {
                                        code = interpreter.ChangeType(
                                            (string)newValue, type,
                                            ref newValue, ref result);
                                    }
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    code = ScriptOps.SetLinkedVariableMemberValue(
                                        breakpointType, variable, name,
                                        index, memberInfo, @object, newValue,
                                        ref result);
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    SetTraceInfoForSetResult(
                                        traceInfo, variable, memberValue, newValue,
                                        code, ref result);
                                }
                                else
                                {
                                    traceInfo.ReturnCode = code;
                                }
                                break;
                            }
                    }
                }
                else
                {
                    traceInfo.ReturnCode = code;
                }
            }
            else
            {
                result = String.Format(
                    "can't {0} {1}: variable {2} array",
                    FormatOps.Breakpoint(breakpointType),
                    FormatOps.ErrorVariableName(
                        variable, null, variable.Name, index),
                    isArray ? "is" : "isn't");

                traceInfo.ReturnCode = ReturnCode.Error;
            }

            return traceInfo.ReturnCode;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region System.Array Variable Trace Callback
        #region Support Methods
        private static bool HasSystemArrayTraceCallback(
            IVariable variable
            )
        {
            return (variable != null) &&
                (variable.Traces != null) &&
                variable.Traces.Contains(SystemArrayTraceCallback);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsSystemArrayVariable(
            IVariable variable
            )
        {
            return (variable != null) && !HasNoTraces() &&
                HasSystemArrayTraceCallback(variable);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        [MethodFlags(MethodFlags.VariableTrace | MethodFlags.NoAdd)]
        private static ReturnCode SystemArrayTraceCallback(
            BreakpointType breakpointType,
            Interpreter interpreter,
            ITraceInfo traceInfo,
            ref Result result
            )
        {
            if ((breakpointType != BreakpointType.BeforeVariableGet) &&
                (breakpointType != BreakpointType.BeforeVariableSet) &&
                (breakpointType != BreakpointType.BeforeVariableUnset))
            {
                return ReturnCode.Ok;
            }

            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (traceInfo == null)
            {
                result = "invalid trace";
                return ReturnCode.Error;
            }

            IVariable variable = traceInfo.Variable;

            if (variable == null)
            {
                result = "invalid variable";
                return ReturnCode.Error;
            }

            //
            // NOTE: If the variable link is still being initially setup,
            //       skip all other handling.
            //
            if ((breakpointType == BreakpointType.BeforeVariableSet) &&
                EntityOps.IsUndefined(variable))
            {
                return ReturnCode.Ok;
            }

            //
            // NOTE: Grab the trace information we will need.
            //
            string name = traceInfo.Name;
            string index = traceInfo.Index;

            //
            // NOTE: For 'unset' operations, the index is not required;
            //       however, it is required for both 'get' and 'set'
            //       operations.
            //
            int[] indexes = null;

            if ((index != null) && MarshalOps.GetArrayIndexes(
                    interpreter.CultureInfo, index, ref indexes,
                    ref result) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            //
            // NOTE: The 'unset' operation has various special cases within
            //       it; therefore, check for it first.
            //
            if (breakpointType == BreakpointType.BeforeVariableUnset)
            {
                if (indexes != null)
                {
                    result = String.Format(
                        "can't {0} {1}: operation not supported for {2}",
                        FormatOps.Breakpoint(breakpointType),
                        FormatOps.ErrorVariableName(
                            variable, null, name, index),
                            FormatOps.TypeName(typeof(Array)));

                    traceInfo.ReturnCode = ReturnCode.Error;
                }
                else
                {
                    //
                    // NOTE: They want to unset the entire array.  Also, make
                    //       sure it is purged from the call frame so that it
                    //       cannot be magically restored with this trace
                    //       callback in place.
                    //
                    traceInfo.Flags &= ~VariableFlags.NoRemove;

                    //
                    // BUGFIX: Yes, also make sure any waiters are cleared.
                    //
                    EntityOps.SetDirty(variable, true);

                    //
                    // NOTE: If we get this far, everything went fine.
                    //
                    traceInfo.ReturnCode = ReturnCode.Ok;
                }
            }
            else if (indexes != null)
            {
                //
                // NOTE: See if the old value represents a System.Array
                //       instance.  If not, this is an invalid linkage.
                //
                Array array = EntityOps.GetSystemArray(variable);

                if (array == null)
                {
                    result = String.Format(
                        "can't {0} {1}: not {2}",
                        FormatOps.Breakpoint(breakpointType),
                        FormatOps.ErrorVariableName(
                            variable, null, name, index),
                            FormatOps.TypeName(typeof(Array)));

                    return ReturnCode.Error;
                }

                ReturnCode code;

                switch (breakpointType)
                {
                    case BreakpointType.BeforeVariableGet:
                        {
                            object oldValue = null;

                            code = MarshalOps.GetArrayElementValue(
                                interpreter.Binder, interpreter.CultureInfo,
                                array, indexes, ref oldValue, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                code = MarshalOps.GetVariableValueAsString(
                                    interpreter, oldValue, true, ref result);

                                if (code == ReturnCode.Ok)
                                {
                                    oldValue = StringOps.GetStringFromObject(
                                        result);
                                }
                            }

                            if (code == ReturnCode.Ok)
                            {
                                SetTraceInfoForGetResult(
                                    traceInfo, code, oldValue);
                            }
                            else
                            {
                                traceInfo.ReturnCode = code;
                            }
                            break;
                        }
                    case BreakpointType.BeforeVariableSet:
                        {
                            object newValue = traceInfo.NewValue;

                            code = MarshalOps.SetArrayElementValue(
                                interpreter.Binder, interpreter.CultureInfo,
                                array, indexes, newValue, ref result);

                            if (code == ReturnCode.Ok)
                            {
                                object oldValue = traceInfo.OldValue;

                                SetTraceInfoForSetResult(
                                    traceInfo, variable, oldValue,
                                    newValue, code, ref result);
                            }
                            else
                            {
                                traceInfo.ReturnCode = code;
                            }
                            break;
                        }
                }
            }
            else
            {
                result = String.Format(
                    "can't {0} {1}: variable is array",
                    FormatOps.Breakpoint(breakpointType),
                    FormatOps.ErrorVariableName(
                        variable, null, variable.Name, index));

                traceInfo.ReturnCode = ReturnCode.Error;
            }

            return traceInfo.ReturnCode;
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Database Variable Support
#if DATA
        private static bool HasDatabaseTraceCallback(
            IVariable variable,
            ref DatabaseVariable databaseVariable
            )
        {
            if (variable == null)
                return false;

            TraceList traces = variable.Traces;

            if (traces == null)
                return false;

            foreach (ITrace trace in traces)
            {
                if (trace == null)
                    continue;

                TraceCallback callback = trace.Callback;

                if (callback == null)
                    continue;

                MethodInfo methodInfo = callback.Method;

                if (methodInfo == null)
                    continue;

                if (methodInfo.DeclaringType == typeof(DatabaseVariable))
                {
                    databaseVariable = callback.Target as DatabaseVariable;
                    return (databaseVariable != null);
                }
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsDatabaseVariable(
            IVariable variable
            )
        {
            DatabaseVariable databaseVariable = null;

            return IsDatabaseVariable(variable, ref databaseVariable);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal bool IsDatabaseVariable(
            IVariable variable,
            ref DatabaseVariable databaseVariable
            )
        {
            return (variable != null) && !HasNoTraces() &&
                HasDatabaseTraceCallback(variable, ref databaseVariable);
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region "Active" Interpreter Support
        public static Interpreter GetAny() /* THREAD-SAFE */
        {
            Interpreter interpreter = GetActive();

            if (interpreter == null)
            {
                ReturnCode code;
                Result error = null;

                code = GlobalState.GetInterpreter(
                    LookupFlags.Interpreter, ref interpreter, ref error);

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(interpreter, code, error);
            }

            return interpreter;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Interpreter GetActive() /* THREAD-SAFE */
        {
            IAnyPair<Interpreter, IClientData> pair = GetActivePair();
            return (pair != null) ? pair.X : null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private
        private static IAnyPair<Interpreter, IClientData> GetActivePair()
        {
            return GetActivePair(null);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static IAnyPair<Interpreter, IClientData> GetActivePair(
            Type type
            )
        {
            return GlobalState.GetActiveInterpreter(type);
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Server Socket Support
#if NETWORK
        internal int ServerSockets
        {
            get { return serverSockets; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int EnterSocketThread()
        {
            return Interlocked.Increment(ref serverSockets);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private int ExitSocketThread()
        {
            return Interlocked.Decrement(ref serverSockets);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode StartServerSocket(
            OptionDictionary options,
            int timeout,
            string address,
            string port,
            bool exclusive,
            string text, /* command */
            ref Result result)
        {
            ReturnCode code = ReturnCode.Error;
            Thread thread = null;

            try
            {
                EventWaitHandle @event = ThreadOps.CreateEvent(false);

                try
                {
                    SocketClientData clientData = new SocketClientData(
                        null, @event, this, options, address, port, exclusive,
                        text);

                    if (timeout == 0)
                        timeout = DefaultThreadStartTimeout;

                    thread = Engine.CreateThread(
                        this, ServerSocketThreadStart, 0, true, false);

                    if (thread != null)
                    {
                        thread.Name = FormatOps.Id(String.Format(
                            "serverSocketThread: {0}", this), port, 0);

                        thread.Start(clientData);

                        //
                        // HACK: For now, avoid ever using the new overload(s)
                        //       of this method; otherwise, Mono crashes.
                        //
                        if (ThreadOps.WaitEvent(@event, timeout))
                        {
                            result = clientData.Result;
                            code = clientData.ReturnCode;
                        }
                        else
                        {
                            result = "timed out starting server thread";
                        }
                    }
                    else
                    {
                        result = "could not create server thread";
                    }
                }
                finally
                {
                    ThreadOps.CloseEvent(ref @event);
                }
            }
            catch (Exception e)
            {
                result = e;
            }
            finally
            {
                //
                // NOTE: If we have failed for any reason and we
                //       created the thread, abort it now.
                //
                if ((code != ReturnCode.Ok) &&
                    (thread != null))
                {
                    try
                    {
                        thread.Abort(); /* BUGBUG: Leaks? */
                        thread = null;
                    }
                    catch (Exception e)
                    {
                        //
                        // NOTE: Nothing we can do here except log the failure.
                        //
                        TraceOps.DebugTrace(String.Format(
                            "{0}: {1}{2}",
                            GlobalState.GetCurrentThreadId(),
                            e, Environment.NewLine),
                            typeof(Interpreter).Name);
                    }
                }
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static void ServerSocketThreadStart(object obj)
        {
            try
            {
                SocketClientData clientData = obj as SocketClientData;

                if (clientData != null)
                {
                    Interpreter interpreter = clientData.Interpreter;

                    if (interpreter != null)
                    {
                        interpreter.EnterSocketThread();

                        try
                        {
                            bool setEvent = false;
                            CultureInfo cultureInfo = interpreter.CultureInfo;

                            Result result = null;

                            TcpListener listener = SocketOps.NewTcpListener(
                                clientData.Address, clientData.Port, cultureInfo,
                                ref result);

                            if (listener != null)
                            {
                                try
                                {
                                    try
                                    {
                                        //
                                        // NOTE: Mono does not support this feature on Unix.
                                        //
                                        if (PlatformOps.IsWindowsOperatingSystem())
                                            listener.ExclusiveAddressUse = clientData.Exclusive;
                                    }
                                    catch (Exception e)
                                    {
                                        //
                                        // NOTE: Mono 2.0/2.2 does not support this feature.
                                        //
                                        TraceOps.DebugTrace(String.Format(
                                            "{0}: {1}{2}",
                                            GlobalState.GetCurrentThreadId(),
                                            e, Environment.NewLine),
                                            typeof(Interpreter).Name);
                                    }

                                    string channelId = FormatOps.Id(
                                        "listenSocket", null, interpreter.NextId());

                                    //
                                    // NOTE: Add the "listener" channel to the interpreter.
                                    //
                                    clientData.ReturnCode = interpreter.AddTcpListenerChannel(
                                        channelId, ChannelType.None, listener, clientData,
                                        ref result);

                                    if (clientData.ReturnCode == ReturnCode.Ok)
                                        clientData.Result = channelId;
                                    else
                                        clientData.Result = result;

                                    setEvent = ThreadOps.SetEvent(clientData.Event);

                                    if (clientData.ReturnCode == ReturnCode.Ok)
                                    {
                                        //
                                        // NOTE: Success so far, start listening...
                                        //
                                        listener.Start();

                                        try
                                        {
                                            //
                                            // NOTE: Poll the listener for incoming connections.
                                            //       For an incoming connection, accept a TcpClient
                                            //       and evaluate the supplied command.
                                            //
                                            while (SocketOps.IsListenerActive(listener))
                                            {
                                                int milliseconds = interpreter.GetSleepTime();

                                                if (milliseconds < MinimumSocketPollTimeout)
                                                    milliseconds = MinimumSocketPollTimeout;

                                                while (true)
                                                {
                                                    //
                                                    // NOTE: Block until the timeout or a connection request
                                                    //       is ready.
                                                    //
                                                    Socket socket = listener.Server;

                                                    if (socket == null)
                                                        break;

                                                    if (!socket.Poll(milliseconds, SelectMode.SelectRead))
                                                        break;

                                                    //
                                                    // NOTE: If the listener is no longer active or the
                                                    //       underlying socket has been cleaned up (i.e. the
                                                    //       other thread called [close] on it), then bail
                                                    //       out now.
                                                    //
                                                    if (!SocketOps.IsListenerActive(listener) ||
                                                        SocketOps.IsCleanedUp(socket))
                                                    {
                                                        break;
                                                    }

                                                    //
                                                    // NOTE: Attempt to accept the connection.
                                                    //
                                                    TcpClient client = listener.AcceptTcpClient();

                                                    //
                                                    // NOTE: Create an Id for the new client channel.
                                                    //
                                                    channelId = FormatOps.Id("serverSocket", null,
                                                        interpreter.NextId());

                                                    //
                                                    // NOTE: Add the new channel for this client to the
                                                    //       interpreter.
                                                    //
                                                    clientData.ReturnCode = interpreter.AddFileOrSocketChannel(
                                                        channelId, client.GetStream(), clientData.Options,
                                                        StreamFlags.ServerSocket, false, false,
                                                        new ClientData(client), ref result);

                                                    clientData.Result = result;

                                                    if (clientData.ReturnCode == ReturnCode.Ok)
                                                    {
                                                        //
                                                        // NOTE: Evaluate the provided script when a
                                                        //       connection is accepted.
                                                        //
                                                        string text = null;

                                                        clientData.ReturnCode = SocketOps.GetServerScript(
                                                            client, channelId, clientData.Text, ref text,
                                                            ref result);

                                                        clientData.Result = result;

                                                        if (clientData.ReturnCode == ReturnCode.Ok)
                                                        {
                                                            clientData.ReturnCode = interpreter.QueueScript(
                                                                TimeOps.GetUtcNow(), text, ref result);

                                                            clientData.Result = result;
                                                        }
                                                    }

                                                    if (clientData.ReturnCode != ReturnCode.Ok)
                                                        _Public.EventManager.HandleBackgroundError(
                                                            interpreter, clientData.ReturnCode,
                                                            clientData.Result);
                                                }
                                            }
                                        }
                                        finally
                                        {
                                            //
                                            // NOTE: Stop listening for incoming connections, we are done.
                                            //       This call is probably pointless because the only real
                                            //       way we can exit the loop is by externally stopping the
                                            //       channel; however, this should be fairly harmless.
                                            //
                                            listener.Stop();
                                        }
                                    }
                                }
                                catch (Exception e)
                                {
                                    clientData.Result = e;
                                    clientData.ReturnCode = ReturnCode.Error;

                                    if (!setEvent)
                                        ThreadOps.SetEvent(clientData.Event);
                                }
                            }
                            else
                            {
                                clientData.Result = result;
                                clientData.ReturnCode = ReturnCode.Error;

                                if (!setEvent)
                                    ThreadOps.SetEvent(clientData.Event);
                            }
                        }
                        finally
                        {
                            interpreter.ExitSocketThread();
                        }
                    }
                    else
                    {
                        clientData.Result = "invalid interpreter";
                        clientData.ReturnCode = ReturnCode.Error;
                        ThreadOps.SetEvent(clientData.Event);
                    }
                }
            }
            catch (ThreadInterruptedException)
            {
                // do nothing.
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Host Integration Support
        internal string Complaint
        {
            get
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    return context.Complaint;
                else
                    return null;
#else
                lock (syncRoot)
                {
                    return complaint;
                }
#endif
            }
            set
            {
                // CheckDisposed();

#if THREADING
                IEngineContext context = (contextManager != null) ?
                    contextManager.GetEngineContext(true) : null;

                if (context != null)
                    context.Complaint = value;
#else
                lock (syncRoot)
                {
                    complaint = value;
                }
#endif
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode CanExit(
            ExitCode exitCode,
            bool force,
            bool fail,
            string message,
            ref Result error
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (host != null)
            {
                try
                {
                    if (FlagOps.HasFlags(host.GetFlags(), HostFlags.Exit, true))
                    {
                        if (host.Exiting)
                        {
                            error = "interpreter host is already exiting";
                            code = ReturnCode.Error;
                        }
                        else if (!host.CanExit)
                        {
                            error = "exit denied by interpreter host";
                            code = ReturnCode.Error;
                        }
                        else if (force && !host.CanForceExit)
                        {
                            error = "force exit denied by interpreter host";
                            code = ReturnCode.Error;
                        }
                    }
                }
                catch (Exception e)
                {
                    //
                    // TODO: Should this simply allow the exit to take place?
                    //
                    error = e;
                    code = ReturnCode.Error;
                }
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: CanExit: returning, exitCode = {1}, force = {2}, " +
                "fail = {3}, message = {4}, returning code {5}{6}{7}",
                GlobalState.GetCurrentThreadId(), exitCode, force, fail,
                FormatOps.WrapOrNull(true, true, message), code,
                (code == ReturnCode.Ok) ? String.Empty :
                    String.Format(" with error {0}",
                        FormatOps.WrapOrNull(true, true, error)),
                Environment.NewLine), typeof(Interpreter).Name);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetStream( /* FOR USE BY Engine.OpenScriptStream METHOD */
            string path,
            FileMode mode,
            FileAccess access,
            ref HostStreamFlags flags,
            ref string fullPath,
            ref Stream stream,
            ref Result error
            )
        {
            return GetStream(
                path, mode, access, FileShare.Read,
                Channel.DefaultBufferSize, FileOptions.None,
                true, ref flags, ref fullPath, ref stream,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode GetStream( /* FOR USE BY [open] COMMAND */
            string path,
            FileMode mode,
            FileAccess access,
            FileShare share,
            int bufferSize,
            FileOptions options,
            bool strict,
            ref HostStreamFlags flags,
            ref Stream stream,
            ref Result error
            )
        {
            string fullPath = null;

            return GetStream(
                path, mode, access, share, bufferSize, options,
                strict, ref flags, ref fullPath, ref stream,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private ReturnCode GetStream(
            string path,
            FileMode mode,
            FileAccess access,
            FileShare share,
            int bufferSize,
            FileOptions options,
            bool strict,
            ref HostStreamFlags flags,
            ref string fullPath,
            ref Stream stream,
            ref Result error
            )
        {
            return HostOps.GetStream(
                this, host, path, mode, access, share, bufferSize,
                options, strict, ref flags, ref fullPath, ref stream,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void GetHostColors(
            IHost host,
            string name,
            ref ConsoleColor foregroundColor,
            ref ConsoleColor backgroundColor
            )
        {
            ReturnCode code;
            Result error = null;

            code = HostOps.GetColors(host, name, true, true, true,
                ref foregroundColor, ref backgroundColor, ref error);

            if (code != ReturnCode.Ok)
            {
#if DEBUG && VERBOSE
                DebugOps.Complain(this, code, error);
#endif

                foregroundColor = defaultForegroundColor;
                backgroundColor = defaultBackgroundColor;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Disposal Helper Methods (Terminate/Dispose)
        #region Tcl Disposal
#if NATIVE && TCL
        private bool DoesTclNeedDispose(
            ref ResultList errors
            )
        {
            lock (tclSyncRoot)
            {
                if (tclApi != null)
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add("may leak Tcl API object");
                }

                if ((tclInterps != null) && (tclInterps.Count > 0))
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(String.Format(
                        "may leak {0} Tcl interpreters: {1}",
                        tclInterps.Count, tclInterps));
                }

#if TCL_THREADS
                if ((tclThreads != null) && (tclThreads.Count > 0))
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(String.Format(
                        "may leak {0} Tcl threads: {1}",
                        tclThreads.Count, tclThreads));
                }
#endif

                if ((tclBridges != null) && (tclBridges.Count > 0))
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Add(String.Format(
                        "may leak {0} Tcl bridges: {1}",
                        tclBridges.Count, tclBridges));
                }

                //
                // BUGFIX: Only generate this error message if the thread is
                //         actually wrong (i.e. not the primary thread for this
                //         interpreter).
                //
                if ((errors != null) && (errors.Count > 0) && !IsPrimaryThread())
                {
                    errors.Insert(0, String.Format(
                        "interpreter \"{0}\" from thread {1} is " +
                        "being disposed on [the wrong] thread {2}",
                        this, threadId, GlobalState.GetCurrentThreadId()));
                }
            }

            return ((errors != null) && (errors.Count > 0));
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeTcl(
            bool dispose,
            bool disposing,
            bool disconnect
            ) /* WARNING: For use by Dispose(bool) only. */
        {
            ResultList errors = null;

            if (DoesTclNeedDispose(ref errors))
            {
                ReturnCode code;
                Result error = null;

                //
                // NOTE: Attempt to dispose our Tcl related stuff now.
                //
                code = DisposeTcl(dispose, disposing, disconnect, ref error);

                //
                // NOTE: If we fail for any reason (including thread affinity)
                //       report the error message itself and the objects that
                //       may be leaked.  Also, see if we can transfer the now
                //       "dead" Tcl related objects that  require cleanup to
                //       the global (static) cache for later transfer to an
                //       interpreter created on the appropriate thread (which,
                //       at least in theory, has a greater than zero chance of
                //       properly calling Dispose on the correct thread?).
                //
                if (code != ReturnCode.Ok)
                {
                    if (errors == null)
                        errors = new ResultList();

                    errors.Insert(0, error);
                    error = errors;

                    DebugOps.Complain(this, code, error);

                    //
                    // NOTE: Now, check if we can add all the Tcl related
                    //       objects that would otherwise leak to the global
                    //       (static) cache for later disposal on the correct
                    //       thread.
                    //
                    #region Static Lock Held
                    lock (staticSyncRoot)
                    {
                        lock (tclSyncRoot)
                        {
                            if ((deadTclThreadId == 0) ||
                                IsPrimaryThread(deadTclThreadId))
                            {
                                if (deadTclThreadId == 0)
                                    deadTclThreadId = threadId;

                                ///////////////////////////////////////////////////////////////////////

                                if (tclApi != null)
                                {
                                    if (deadTclApi == null)
                                        deadTclApi = tclApi;

                                    tclApi = null;
                                }

                                ///////////////////////////////////////////////////////////////////////

                                if (tclInterps != null)
                                {
                                    if (deadTclInterps != null)
                                        deadTclInterps.Add(tclInterps);

                                    tclInterps.Clear();
                                    tclInterps = null;
                                }

                                ///////////////////////////////////////////////////////////////////////

#if TCL_THREADS
                                if (tclThreads != null)
                                {
                                    if (deadTclThreads != null)
                                        deadTclThreads.Add(tclThreads);

                                    tclThreads.Clear();
                                    tclThreads = null;
                                }
#endif

                                ///////////////////////////////////////////////////////////////////////

                                if (tclBridges != null)
                                {
                                    if (deadTclBridges != null)
                                        deadTclBridges.Add(tclBridges);

                                    tclBridges.Clear();
                                    tclBridges = null;
                                }
                            }
                        }
                    }
                    #endregion
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DisposeTcl(
            bool dispose,
            bool disposing, /* NOT USED */
            bool disconnect,
            ref Result error
            )
        {
            ReturnCode code;

            if (IsTclThread())
            {
                //
                // NOTE: Dispose of all TclBridge objects we own now.
                //
                code = DisposeTclBridges(
                    IntPtr.Zero, null, false, dispose, ref error);

                if (code != ReturnCode.Ok)
                {
                    if (dispose)
                    {
                        //
                        // NOTE: We are being called from dispose, not much we
                        //       can really do here.  Attempt to show the error
                        //       to the user.
                        //
                        DebugOps.Complain(this, code, error);

                        //
                        // NOTE: Next, reset the return code here so that we
                        //       can continue to dispose Tcl resources.
                        //
                        code = ReturnCode.Ok;
                    }
                    else
                    {
                        //
                        // NOTE: We are not being called from Dispose, bail out
                        //       now with the error.
                        //
                        return code;
                    }
                }

                ///////////////////////////////////////////////////////////////

#if TCL_THREADS
                code = DisposeTclThreads(
                    dispose, disposing, disconnect, ref error);

                if (code != ReturnCode.Ok)
                    return code;
#endif

                ///////////////////////////////////////////////////////////////

                lock (tclSyncRoot)
                {
                    GlobalState.PushActiveInterpreter(this);

                    try
                    {
                        //
                        // NOTE: Attempt to delete all the Tcl interps we own
                        //       now.
                        //
                        if (tclInterps != null)
                        {
                            StringList keys = new StringList(tclInterps.Keys);

                            foreach (string key in keys)
                            {
                                IntPtr interp = tclInterps[key];

                                if (interp == IntPtr.Zero)
                                    continue;

                                //
                                // BUGFIX: If we are being called by the exit
                                //         handler, "force" the deletion of the
                                //         interpreter.  Tcl should not actually
                                //         free the underlying memory until the
                                //         stack is unwound.
                                //
#if NATIVE_PACKAGE
                                if (NativePackage.ShouldDeleteTclInterpreter(key, interp))
#endif
                                    code = TclWrapper.DeleteInterpreter(tclApi, disconnect,
                                        ref interp, ref error);
#if NATIVE_PACKAGE
                                else
                                    code = ReturnCode.Ok;
#endif

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The Tcl interpreter has been
                                    //       deleted, remove it from our
                                    //       collection.
                                    //
                                    tclInterps.Remove(key);
                                }
                                else
                                {
                                    if (dispose)
                                    {
                                        //
                                        // NOTE: We are being called from
                                        //       dispose, not much we can
                                        //       really do here.  Attempt to
                                        //       show the error to the user.
                                        //
                                        DebugOps.Complain(this, code, error);

                                        //
                                        // NOTE: Next, reset the return code
                                        //       here so that we can continue
                                        //       to dispose Tcl resources.
                                        //
                                        code = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: We are not being called from
                                        //       Dispose, bail out now with the
                                        //       error.
                                        //
                                        return code;
                                    }
                                }
                            }

                            //
                            // NOTE: Upon dispose, destroy the collection itself
                            //       so that it cannot be used again.
                            //
                            // BUGBUG: This needs to be reworked at some point
                            //         when Dispose is modified to be capable
                            //         of "failing".
                            //
                            if (dispose)
                            {
                                tclInterps.Clear();
                                tclInterps = null;
                            }
                        }

                        ///////////////////////////////////////////////////////

                        //
                        // NOTE: Only mess with the Tcl API object if we are
                        //       being called by our Dispose or the Dispose of
                        //       the Tcl API object itself; otherwise, this
                        //       cleanup will be handled externally.
                        //
                        if (disconnect || dispose)
                        {
                            //
                            // NOTE: Terminate the link with the Tcl API now.
                            //
                            // BUGBUG: This needs to be reworked at some point
                            //         when Dispose is modified to be capable
                            //         of "failing".
                            //
                            if (tclApi != null)
                            {
                                try
                                {
                                    if (dispose
#if NATIVE_PACKAGE
                                        && !NativePackage.IsTclInterpreterActive()
#endif
                                        )
                                    {
                                        //
                                        // BUGFIX: If we are being explicitly
                                        //         disposed, we need to make
                                        //         sure the actual Tcl library
                                        //         gets unloaded (or at least
                                        //         has its internal reference
                                        //         count decreased in the event
                                        //         it is being used by other
                                        //         Eagle interpreters or random
                                        //         external code).
                                        //
                                        code = TclWrapper.Unload(
                                            this, UnloadFlags.Default,
                                            ref tclApi, ref error);
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: Just clear out our Tcl API
                                        //       object reference because we
                                        //       are [already] being called by
                                        //       its Dispose method.
                                        //
                                        tclApi = null;
                                    }
                                }
                                catch (Exception e)
                                {
                                    error = e;
                                    code = ReturnCode.Error;
                                }
                            }
                        }
                    }
                    finally
                    {
                        /* IGNORED */
                        GlobalState.PopActiveInterpreter();
                    }
                }
            }
            else
            {
                error = "cannot dispose Tcl, wrong thread";
                code = ReturnCode.Error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private StringList FilterTclBridges(
            IntPtr interp,
            IExecute execute,
            bool? fromThread
            )
        {
            StringList keys = new StringList();

            //
            // NOTE: Cleanup, PASS #1, collect the list of keys we need to remove
            //       from the TclBridges collection in the containing interpreter.
            //
            lock (tclSyncRoot)
            {
                if (tclBridges != null)
                {
                    foreach (KeyValuePair<string, TclBridge> pair in tclBridges)
                    {
                        TclBridge value = pair.Value;

                        if (value == null)
                            continue;

                        if ((interp != IntPtr.Zero) && !value.Match(interp))
                            continue;

                        if ((execute != null) && !value.Match(execute))
                            continue;

                        if ((fromThread != null) && !value.Match(fromThread))
                            continue;

                        keys.Add(pair.Key);
                    }
                }
            }

            return keys;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal TclBridgeDictionary GetTclBridges(
            IntPtr interp,
            IExecute execute,
            bool? fromThread
            )
        {
            TclBridgeDictionary result = null;

            lock (tclSyncRoot)
            {
                if (tclBridges != null)
                {
                    result = new TclBridgeDictionary();

                    foreach (string key in
                            FilterTclBridges(interp, execute, fromThread))
                    {
                        result.Add(key, tclBridges[key]);
                    }
                }
            }

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: Assumes the "tclSyncRoot" lock is already held by the caller.
        //
        private ReturnCode PrivateDisposeTclBridges(
            StringList keys,
            bool dispose,
            ref Result error
            )
        {
            //
            // NOTE: Cleanup, PASS #2, dispose and remove all the TclBridge
            //       objects we found from PASS #1 (above).
            //
            if (tclBridges != null)
            {
                foreach (string key in keys)
                {
                    TclBridge tclBridge = tclBridges[key];

                    if (tclBridge != null)
                    {
                        try
                        {
                            tclBridge.Dispose(); /* throw */
                            tclBridge = null;
                        }
                        catch (Exception e)
                        {
                            error = String.Format(
                                "caught exception while disposing Tcl bridge: {0}",
                                e);

                            return ReturnCode.Error;
                        }
                    }

                    tclBridges.Remove(key);
                }

                //
                // NOTE: Upon dispose, destroy the collection itself so that it
                //       cannot be used again.
                //
                if (dispose && (tclBridges.Count == 0))
                    tclBridges = null;
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal ReturnCode DisposeTclBridges(
            IntPtr interp,
            IExecute execute,
            bool? fromThread,
            bool dispose,
            ref Result error
            )
        {
            lock (tclSyncRoot)
            {
                GlobalState.PushActiveInterpreter(this);

                try
                {
                    if (tclBridges == null)
                        return ReturnCode.Ok;

                    return PrivateDisposeTclBridges(
                        FilterTclBridges(interp, execute, fromThread), dispose,
                        ref error);
                }
                catch (Exception e)
                {
                    error = e;

                    return ReturnCode.Error;
                }
                finally
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if TCL_THREADS
        private ReturnCode DisposeTclThreads(
            bool dispose,
            bool disposing,
            bool disconnect,
            ref Result error
            )
        {
            //
            // NOTE: Attempt to shutdown all the Tcl threads we own now.
            //
            TclThreadDictionary localTclThreads = null;

            //
            // BUGFIX: Avoid holding the Tcl state lock while shutting down
            //         the Tcl threads.
            //
            lock (tclSyncRoot)
            {
                if (tclThreads != null)
                    localTclThreads = new TclThreadDictionary(tclThreads);
            }

            if (localTclThreads != null)
            {
                GlobalState.PushActiveInterpreter(this);

                try
                {
                    foreach (KeyValuePair<string, TclThread> pair
                            in localTclThreads)
                    {
                        TclThread thread = pair.Value;

                        if (thread == null)
                            continue;

                        //
                        // NOTE: If we are being called by the exit handler,
                        //       "force" the shutdown of the thread.
                        //
                        ReturnCode code = thread.Shutdown(
                            GetTclBridges(thread.Interp, null, null),
                            true, disconnect, false, ref error);

                        if (code != ReturnCode.Ok)
                        {
                            if (dispose)
                            {
                                //
                                // NOTE: We are being called from dispose,
                                //       not much we can really do here.
                                //       Attempt to show the error to the
                                //       user.
                                //
                                DebugOps.Complain(this, code, error);
                            }
                            else
                            {
                                //
                                // NOTE: We are not being called from
                                //       Dispose, bail out now with the
                                //       error.
                                //
                                return code;
                            }
                        }
                    }
                }
                finally
                {
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();
                }

                //
                // NOTE: Re-sync the collections of Tcl bridges and threads
                //       now.
                //
                lock (tclSyncRoot)
                {
                    //
                    // NOTE: Remove all the Tcl bridges that have been
                    //       cleaned up because due to being associated
                    //       with the Tcl threads being disposed.
                    //
                    if (tclBridges != null)
                    {
                        StringList keys = new StringList(tclBridges.Keys);

                        foreach (string key in keys)
                        {
                            TclBridge tclBridge = tclBridges[key];

                            if ((tclBridge != null) && tclBridge.Match(true))
                                tclBridges.Remove(key);
                        }
                    }

                    //
                    // BUGBUG: This needs to be reworked at some point when
                    //         Dispose is modified to be capable of failing.
                    //
                    if (dispose)
                    {
                        //
                        // NOTE: Upon dispose, destroy the collection
                        //       itself so that it cannot be used again.
                        //
                        tclThreads.Clear();
                        tclThreads = null;
                    }
                    else
                    {
                        //
                        // NOTE: Remove all the Tcl threads that should
                        //       have been disposed by the loop above.
                        //
                        foreach (string key in localTclThreads.Keys)
                            tclThreads.Remove(key);
                    }
                }
            }

            return ReturnCode.Ok;
        }
#endif
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Callstack Disposal
#if !THREADING
        private void DisposeCallStack(
            ref CallStack callStack
            )
        {
            if (callStack != null)
            {
                ReturnCode code;
                Result error = null;

                try
                {
                    code = ObjectOps.TryDispose(callStack, ref error);
                }
                catch (Exception e)
                {
                    error = String.Format(
                        "caught exception while disposing call stack: {0}",
                        e);

                    code = ReturnCode.Error;
                }

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error);

                callStack = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeCallFrame(
            ref ICallFrame frame
            )
        {
            if (frame != null)
            {
                ReturnCode code;
                Result error = null;

                try
                {
                    code = ObjectOps.TryDispose(frame, ref error);
                }
                catch (Exception e)
                {
                    error = String.Format(
                        "caught exception while disposing call frame: {0}",
                        e);

                    code = ReturnCode.Error;
                }

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error);

                frame = null;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Thread Data Disposal
        internal bool MaybeDisposeThread()
        {
            bool nonPrimary = !IsPrimaryThread();
            bool isActive = GlobalState.IsActiveInterpreter(this);

#if THREADING
            int count = ContextManager.Purge(nonPrimary);
#endif

            if (!isActive && nonPrimary)
                DisposeThread(false, false);

#if THREADING
            return (!isActive && nonPrimary) || (count > 0);
#else
            return (!isActive && nonPrimary);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal void DisposeThread(
            bool dispose,
            bool disposing /* NOT USED */
            )
        {
#if (NATIVE && WINDOWS) || THREADING
            bool isFinalizingAppDomain = AppDomainOps.IsFinalizing();
#endif

            ///////////////////////////////////////////////////////////////////

#if NATIVE && WINDOWS
            //
            // NOTE: Skip finalizing the native stack checking if the entire
            //       application domain is being finalized.  This is necessary
            //       because the thread-local storage may have already been
            //       freed in that case.
            //
            // NOTE: Try to verify that we are the last interpreter for this
            //       thread prior to getting rid of our native stack related
            //       informmation.
            //
            if (!isFinalizingAppDomain &&
                (CountThreadInterpreters() == 1)) // BUGBUG: Maybe <= 1 here?
            {
                RuntimeOps.FinalizeStackChecking();
            }
#endif

            ///////////////////////////////////////////////////////////////////

#if THREADING
            //
            // NOTE: Dispose all per-interpreter data (for this thread only).
            //       Only "threading" enabled data is disposed here.  Normal
            //       per-interpreter data is disposed by Dispose (see below).
            //       This must be skipped if the entire application domain is
            //       being finalized because the thread-local storage may have
            //       already been freed in that case.
            //
            if (!isFinalizingAppDomain && (contextManager != null))
                contextManager.Free(dispose);
#else
            //
            // NOTE: Dispose all per-interpreter data (for all threads).  We do this
            //       here, rather than in Dispose, in order to centralize the logic
            //       that handles data that is per-thread in "threading" enabled
            //       builds.
            //
            if (dispose)
            {
                lock (syncRoot)
                {
                    #region Engine Context
                    levels = 0;
                    previousLevels = 0;
                    parserLevels = 0;
                    expressionLevels = 0;
                    unknownLevels = 0;
                    traceLevels = 0;

                    ///////////////////////////////////////////////////////////

#if SHELL
                    argumentCallback = null;
                    evaluateScriptCallback = null;
                    evaluateFileCallback = null;
                    evaluateEncodedFileCallback = null;
#endif

                    ///////////////////////////////////////////////////////////

#if DEBUGGER
                    interactiveLoopCallback = null;
#endif

                    ///////////////////////////////////////////////////////////

#if NOTIFY || NOTIFY_OBJECT
                    notifyLevels = 0;
                    notifyTypes = NotifyType.None;
                    notifyFlags = NotifyFlags.None;
#endif

                    ///////////////////////////////////////////////////////////

                    policyLevels = 0;
                    testLevels = 0;
                    stackOverflow = false;

                    ///////////////////////////////////////////////////////////

#if PREVIOUS_RESULT
                    previousResult = null;
#endif

                    ///////////////////////////////////////////////////////////

                    engineFlags = EngineFlags.None;
                    parseState = null;
                    returnCode = ReturnCode.Ok;
                    errorLine = 0;
                    errorCode = null;
                    errorInfo = null;
                    errorFrames = 0;
                    scriptLocation = null;

                    ///////////////////////////////////////////////////////////

                    if (scriptLocations != null)
                    {
                        scriptLocations.Clear();
                        scriptLocations = null;
                    }

                    ///////////////////////////////////////////////////////////

                    previousProcessId = 0;

                    ///////////////////////////////////////////////////////////

                    if (arraySearches != null)
                    {
                        arraySearches.Clear();
                        arraySearches = null;
                    }

                    ///////////////////////////////////////////////////////////

#if HISTORY
                    historyEngineFilter = null;

                    ///////////////////////////////////////////////////////////

                    if (_history != null)
                    {
                        _history.Clear();
                        _history = null;
                    }
#endif
                    #endregion

                    ///////////////////////////////////////////////////////////

            #region Interactive Context
                    interactive = false;
                    interactiveInput = null;
                    previousInteractiveInput = null;
                    interactiveMode = null;
                    interactiveLoops = 0;

                    ///////////////////////////////////////////////////////////

#if HISTORY
                    historyLoadData = null;
                    historySaveData = null;
                    historyInfoFilter = null;
                    historyLoadFilter = null;
                    historySaveFilter = null;
                    historyFileName = null;
#endif
                    #endregion

                    ///////////////////////////////////////////////////////////

            #region Test Context
                    testStatistics = null;

                    ///////////////////////////////////////////////////////////

                    if (testConstraints != null)
                    {
                        testConstraints.Clear();
                        testConstraints = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testSkipped != null)
                    {
                        testSkipped.Clear();
                        testSkipped = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testFailures != null)
                    {
                        testFailures.Clear();
                        testFailures = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testCounts != null)
                    {
                        testCounts.Clear();
                        testCounts = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testMatch != null)
                    {
                        testMatch.Clear();
                        testMatch = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testSkip != null)
                    {
                        testSkip.Clear();
                        testSkip = null;
                    }

                    ///////////////////////////////////////////////////////////

                    if (testReturnCodeMessages != null)
                    {
                        testReturnCodeMessages.Clear();
                        testReturnCodeMessages = null;
                    }

                    ///////////////////////////////////////////////////////////

#if DEBUGGER
                    if (testBreakpoints != null)
                    {
                        testBreakpoints.Clear();
                        testBreakpoints = null;
                    }
#endif

                    ///////////////////////////////////////////////////////////

                    testPath = null;
                    #endregion

                    ///////////////////////////////////////////////////////////

            #region Variable Context
                    //
                    // NOTE: Dispose of the call stack now.
                    //
                    DisposeCallStack(ref callStack);

                    //
                    // NOTE: Dispose of the current, procedure, and global call
                    //       frames now.
                    //
                    DisposeCallFrame(ref currentFrame);
                    DisposeCallFrame(ref procedureFrame);
                    DisposeCallFrame(ref uplevelFrame);
                    DisposeCallFrame(ref globalFrame);

                    ///////////////////////////////////////////////////////////

                    traceInfo = null;
                    #endregion
                }
            }
#endif
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Namespace Disposal
        private void DisposeNamespaces()
        {
            #region Pending Deletion List
            //
            // HACK: This code currently assumes that all namespaces pending
            //       deletion are also *still* present in the "logical tree"
            //       of namespaces starting from the global namespace.  If
            //       this assumption is not true, this code will likely not
            //       work correctly.  Therefore, we ignore pending namespace
            //       deletions during interpreter disposal because *ALL* of
            //       the namespaces should get disposed by this method.
            //
            if (pendingNamespaces != null)
            {
                pendingNamespaces.Clear();
                pendingNamespaces = null;
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Global Namespace
            if (globalNamespace != null)
            {
                ReturnCode code;
                Result error = null;

                code = NamespaceOps.Dispose(this, ref globalNamespace, ref error);

                if (code != ReturnCode.Ok)
                {
                    error = String.Format(
                        "caught exception while disposing namespace \"{0}\": {1}",
                        TclVars.GlobalNamespaceName, error);

                    DebugOps.Complain(this, code, error);

                    //
                    // HACK: Reset the global namespace instance even if we
                    //       could not successfully dispose it.
                    //
                    globalNamespace = null;
                }
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Plugin, Command, & Package Disposal
        private void DisposePlugins(
            bool all
            )
        {
            if (plugins != null)
            {
                StringList keys = new StringList(plugins.Keys);

                foreach (string key in keys)
                {
                    IPlugin plugin = plugins[key];

                    if (plugin != null)
                    {
                        bool nativeCode = FlagOps.HasFlags(plugin.Flags,
                            PluginFlags.NativeCode, true);

                        if (all || !nativeCode)
                        {
                            string pluginName = plugin.Name;

                            ReturnCode code;
                            Result result = null;

                            try
                            {
                                code = plugin.Terminate(this, null, ref result);

                                if (code == ReturnCode.Ok)
                                    //
                                    // NOTE: Plugin successfully terminated, remove it.
                                    //
                                    plugins.Remove(key);
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "caught exception while terminating {0} plugin \"{1}\": {2}",
                                    nativeCode ? "native" : "managed", pluginName, e);

                                code = ReturnCode.Error;
                            }

                            if (code != ReturnCode.Ok)
                                DebugOps.Complain(this, code, result);
                        }
                    }
                    else
                    {
                        plugins.Remove(key);
                    }
                }

                if (all || (plugins.Count == 0))
                    plugins = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeCommands(
            bool all
            )
        {
            if (commands != null)
            {
                StringList keys = new StringList(commands.Keys);

                foreach (string key in keys)
                {
                    ICommand command = commands[key];

                    if (command != null)
                    {
                        bool nativeCode = FlagOps.HasFlags(command.Flags, CommandFlags.NativeCode, true);

                        if (all || !nativeCode)
                        {
                            string commandName = command.Name;

                            ReturnCode code;
                            Result result = null;

                            try
                            {
                                code = command.Terminate(this, null, ref result);

                                if (code == ReturnCode.Ok)
                                    //
                                    // NOTE: Command successfully terminated, remove it.
                                    //
                                    commands.Remove(key);
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "caught exception while terminating {0} command \"{1}\": {2}",
                                    nativeCode ? "native" : "managed", commandName, e);

                                code = ReturnCode.Error;
                            }

                            if (code != ReturnCode.Ok)
                                DebugOps.Complain(this, code, result);
                        }
                    }
                    else
                    {
                        commands.Remove(key);
                    }
                }

                if (all || (commands.Count == 0))
                    commands = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeHiddenCommands(
            bool all
            )
        {
            if (hiddenCommands != null)
            {
                StringList keys = new StringList(hiddenCommands.Keys);

                foreach (string key in keys)
                {
                    ICommand command = hiddenCommands[key];

                    if (command != null)
                    {
                        bool nativeCode = FlagOps.HasFlags(command.Flags, CommandFlags.NativeCode, true);

                        if (all || !nativeCode)
                        {
                            string commandName = command.Name;

                            ReturnCode code;
                            Result result = null;

                            try
                            {
                                code = command.Terminate(this, null, ref result);

                                if (code == ReturnCode.Ok)
                                    //
                                    // NOTE: Command successfully terminated, remove it.
                                    //
                                    hiddenCommands.Remove(key);
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "caught exception while terminating {0} hidden command \"{1}\": {2}",
                                    nativeCode ? "native" : "managed", commandName, e);

                                code = ReturnCode.Error;
                            }

                            if (code != ReturnCode.Ok)
                                DebugOps.Complain(this, code, result);
                        }
                    }
                    else
                    {
                        hiddenCommands.Remove(key);
                    }
                }

                if (all || (hiddenCommands.Count == 0))
                    hiddenCommands = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposePackages()
        {
            if (packages != null)
            {
                foreach (KeyValuePair<string, _Wrappers.Package> pair in packages)
                {
                    if (pair.Value != null)
                    {
                        string packageName = pair.Value.Name;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = pair.Value.Terminate(this, null, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while terminating package \"{0}\": {1}",
                                packageName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                packages.Clear();
                packages = null;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Expression Entity Disposal
        private void DisposeFunctions()
        {
            if (functions != null)
            {
                foreach (KeyValuePair<string, _Wrappers.Function> pair in functions)
                {
                    if (pair.Value != null)
                    {
                        string functionName = pair.Value.Name;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = pair.Value.Terminate(this, null, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while terminating function \"{0}\": {1}",
                                functionName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                functions.Clear();
                functions = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeOperators()
        {
            if (operators != null)
            {
                foreach (KeyValuePair<string, _Wrappers.Operator> pair in operators)
                {
                    if (pair.Value != null)
                    {
                        string operatorName = pair.Value.Name;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = pair.Value.Terminate(this, null, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while terminating operator \"{0}\": {1}",
                                operatorName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                operators.Clear();
                operators = null;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Managed Entity Disposal
        private void DisposeObjects()
        {
            if (objects != null)
            {
                foreach (KeyValuePair<string, _Wrappers._Object> pair in objects)
                {
                    if (pair.Value != null)
                    {
                        if (pair.Value.Value != null)
                        {
                            //
                            // BUGFIX: Prevent accidental recursion.  Also, do NOT attempt to
                            //         dispose of objects that we do not own (i.e. the NoDispose
                            //         flag is set).
                            //
                            if (!Object.ReferenceEquals(pair.Value.Value, this) &&
                                !IsMasterOrSlaveInterpreter(pair.Value.Value) &&
                                !FlagOps.HasFlags(pair.Value.Flags, ObjectFlags.NoDispose, true))
                            {
                                string objectName = pair.Value.Name;

                                ReturnCode code;
                                Result result = null;

                                try
                                {
                                    //
                                    // NOTE: *SPECIAL CASE* The IObject interface uses the Value
                                    //       property to refer to the actual object, which is what
                                    //       we want to try and dispose of (i.e. and not the wrapper
                                    //       nor the underlying IObject implementation, which are
                                    //       usually just _Wrappers_Object and _Objects.Default,
                                    //       respectively).
                                    //
                                    code = ObjectOps.TryDispose(pair.Value.Value, ref result);
                                }
                                catch (Exception e)
                                {
                                    result = String.Format(
                                        "caught exception while disposing object \"{0}\": {1}",
                                        objectName, e);

                                    code = ReturnCode.Error;
                                }

                                if (code != ReturnCode.Ok)
                                    DebugOps.Complain(this, code, result);
                            }
                        }
                    }
                }

                objects.Clear();
                objects = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeChannels()
        {
            if (channels != null)
            {
                foreach (KeyValuePair<string, Channel> pair in channels)
                {
                    if (pair.Value != null)
                    {
                        string channelName = pair.Value.ToString();

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            pair.Value.Close(); /* throw */

                            code = ReturnCode.Ok;
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while closing channel \"{0}\": {1}",
                                channelName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                channels.Clear();
                channels = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if APPDOMAINS
        private void DisposeAppDomains()
        {
            if (appDomains != null)
            {
                foreach (KeyValuePair<string, AppDomain> pair in appDomains)
                {
                    if (pair.Value != null)
                    {
                        string appDomainName = pair.Value.FriendlyName;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = AppDomainOps.Unload(
                                pair.Value, null, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while unloading application domain \"{0}\": {1}",
                                appDomainName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                appDomains.Clear();
                appDomains = null;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Database Entity Disposal
#if DATA
        private void DisposeTransactions()
        {
            if (transactions != null)
            {
                foreach (KeyValuePair<string, IDbTransaction> pair in transactions)
                {
                    if (pair.Value != null)
                    {
                        string transactionName = pair.Value.ToString();

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = ObjectOps.TryDispose(pair.Value, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing transaction \"{0}\": {1}",
                                transactionName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                transactions.Clear();
                transactions = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeConnections()
        {
            if (connections != null)
            {
                foreach (KeyValuePair<string, IDbConnection> pair in connections)
                {
                    if (pair.Value != null)
                    {
                        string connectionName = pair.Value.ToString();

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = ObjectOps.TryDispose(pair.Value, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing connection \"{0}\": {1}",
                                connectionName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                connections.Clear();
                connections = null;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Native Entity Disposal
#if NATIVE && LIBRARY
        private void DisposeDelegates()
        {
            if (delegates != null)
            {
                foreach (KeyValuePair<string, _Wrappers.Delegate> pair in delegates)
                {
                    if (pair.Value != null)
                    {
                        string delegateName = pair.Value.Name;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = ObjectOps.TryDispose(pair.Value, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing delegate \"{0}\": {1}",
                                delegateName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                delegates.Clear();
                delegates = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeModules()
        {
            if (modules != null)
            {
                foreach (KeyValuePair<string, _Wrappers._Module> pair in modules)
                {
                    if (pair.Value != null)
                    {
                        string moduleName = pair.Value.Name;

                        ReturnCode code;
                        Result result = null;

                        try
                        {
                            code = ObjectOps.TryDispose(pair.Value, ref result);
                        }
                        catch (Exception e)
                        {
                            result = String.Format(
                                "caught exception while disposing module \"{0}\": {1}",
                                moduleName, e);

                            code = ReturnCode.Error;
                        }

                        if (code != ReturnCode.Ok)
                            DebugOps.Complain(this, code, result);
                    }
                }

                modules.Clear();
                modules = null;
            }
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Event Manager, Debugger, & Host Disposal
        private void DisposeEventManager()
        {
            if (eventManager != null) /* EXEMPT */
            {
                ReturnCode code;
                Result error = null;

                try
                {
                    code = ObjectOps.TryDispose(eventManager, ref error);
                }
                catch (Exception e)
                {
                    error = String.Format(
                        "caught exception while disposing event manager: {0}",
                        e);

                    code = ReturnCode.Error;
                }

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error);

                eventManager = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if DEBUGGER && !THREADING
        private void DisposeDebugger()
        {
            if (debugger != null)
            {
                ReturnCode code;
                Result error = null;

                try
                {
                    code = ObjectOps.TryDispose(debugger, ref error);
                }
                catch (Exception e)
                {
                    error = String.Format(
                        "caught exception while disposing debugger: {0}",
                        e);

                    code = ReturnCode.Error;
                }

                if (code != ReturnCode.Ok)
                    DebugOps.Complain(this, code, error);

                debugger = null;
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void DisposeHost()
        {
            #region Dispose Host
            if (host != null)
            {
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoDisposeHost, true))
                {
                    ReturnCode code;
                    Result error = null;

                    try
                    {
                        code = ObjectOps.TryDispose(host, ref error);
                    }
                    catch (Exception e)
                    {
                        error = String.Format(
                            "caught exception while disposing host: {0}",
                            e);

                        code = ReturnCode.Error;
                    }

                    if (code != ReturnCode.Ok)
                        DebugOps.Complain(this, code, error);
                }

                host = null;
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Dispose Core Host (ISOLATED_PLUGINS only)
#if ISOLATED_PLUGINS
            if (coreHost != null)
            {
                if (!FlagOps.HasFlags(createFlags, CreateFlags.NoDisposeHost, true))
                {
                    ReturnCode code;
                    Result error = null;

                    try
                    {
                        code = ObjectOps.TryDispose(coreHost, ref error);
                    }
                    catch (Exception e)
                    {
                        error = String.Format(
                            "caught exception while disposing core host: {0}",
                            e);

                        code = ReturnCode.Error;
                    }

                    if (code != ReturnCode.Ok)
                        DebugOps.Complain(this, code, error);
                }

                coreHost = null;
            }
#endif
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Slave Interpreter Disposal
        private void DisposeSlaveInterpreters()
        {
            if (slaveInterpreters != null)
            {
                foreach (KeyValuePair<string, Interpreter> pair in slaveInterpreters)
                {
                    if (pair.Value != null)
                    {
                        if (!Object.ReferenceEquals(pair.Value, this))
                        {
                            ReturnCode code;
                            Result result = null;

                            try
                            {
                                code = ObjectOps.TryDispose(pair.Value, ref result);
                            }
                            catch (Exception e)
                            {
                                result = String.Format(
                                    "caught exception while disposing slave interpreter \"{0}\": {1}",
                                    pair.Value, e);

                                code = ReturnCode.Error;
                            }

                            if (code != ReturnCode.Ok)
                                DebugOps.Complain(this, code, result);
                        }
                    }
                }

                slaveInterpreters.Clear();
                slaveInterpreters = null;
            }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Disposal Helper Methods (Reset/Clear)
#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
        private void ResetCaches()
        {
#if LIST_CACHE
            if (stringListCache != null)
            {
                stringListCache.Clear();
                stringListCache = null;
            }
#endif

#if PARSE_CACHE
            if (parseStateCache != null)
            {
                parseStateCache.Clear();
                parseStateCache = null;
            }

            #region Dead Code
#if DEAD_CODE
            if (expressionStateCache != null)
            {
                expressionStateCache.Clear();
                expressionStateCache = null;
            }
#endif
            #endregion
#endif

#if EXECUTE_CACHE
            if (hiddenExecuteCache != null)
            {
                hiddenExecuteCache.Clear();
                hiddenExecuteCache = null;
            }

            if (executeCache != null)
            {
                executeCache.Clear();
                executeCache = null;
            }
#endif

#if TYPE_CACHE
            if (typeCache != null)
            {
                typeCache.Clear();
                typeCache = null;
            }
#endif

#if COM_TYPE_CACHE
            if (comTypeListCache != null)
            {
                comTypeListCache.Clear();
                comTypeListCache = null;
            }
#endif
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void ResetEarlyPodObjects()
        {
            if (aliases != null)
            {
                aliases.Clear();
                aliases = null;
            }

            if (procedures != null)
            {
                procedures.Clear();
                procedures = null;
            }

            if (hiddenProcedures != null)
            {
                hiddenProcedures.Clear();
                hiddenProcedures = null;
            }

            if (executes != null)
            {
                executes.Clear();
                executes = null;
            }

            if (hiddenExecutes != null)
            {
                hiddenExecutes.Clear();
                hiddenExecutes = null;
            }

            #region Dead Code
#if DEAD_CODE
            if (lambdas != null)
            {
                lambdas.Clear();
                lambdas = null;
            }
#endif
            #endregion

            if (objectAliasNamespaces != null)
            {
                objectAliasNamespaces.Clear();
                objectAliasNamespaces = null;
            }

            if (objectInterfaces != null)
            {
                objectInterfaces.Clear();
                objectInterfaces = null;
            }

            if (objectNamespaces != null)
            {
                objectNamespaces.Clear();
                objectNamespaces = null;
            }

            if (objectTypes != null)
            {
                objectTypes.Clear();
                objectTypes = null;
            }

#if CALLBACK_QUEUE
            if (callbackQueue != null)
            {
                callbackQueue.Clear();
                callbackQueue = null;
            }
#endif

            if (callbacks != null)
            {
                callbacks.Clear();
                callbacks = null;
            }

            if (scopes != null)
            {
                scopes.Clear();
                scopes = null;
            }

            if (randomNumberGenerator != null)
                randomNumberGenerator = null;

            if (random != null)
                random = null;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void ResetLatePodObjects()
        {
            if (resolvers != null)
            {
                resolvers.Clear();
                resolvers = null;
            }

            if (runtimeOptions != null)
            {
                runtimeOptions.Clear();
                runtimeOptions = null;
            }

            if (traces != null)
            {
                traces.Clear();
                traces = null;
            }

            if (pluginArguments != null)
            {
                pluginArguments.Clear();
                pluginArguments = null;
            }

            if (policies != null)
            {
                policies.Clear();
                policies = null;
            }

            if (packageIndexes != null)
            {
                packageIndexes.Clear();
                packageIndexes = null;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void ResetUserObjects()
        {
            if (userObject != null)
                userObject = null; /* WARNING: Not owner, do NOT dispose. */

            if (resolverObject != null)
                resolverObject = null; /* WARNING: Not owner, do NOT dispose. */

            if (policyObject != null)
                policyObject = null; /* WARNING: Not owner, do NOT dispose. */

            if (applicationObject != null)
                applicationObject = null; /* WARNING: Not owner, do NOT dispose. */
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Disposal Helper Methods (Callbacks)
        private static void RemoveTargetDisposeCallback(
            IAlias alias
            )
        {
            try
            {
                Interpreter targetInterpreter = alias.TargetInterpreter;

                if (targetInterpreter != null)
                    targetInterpreter.RemoveDisposeCallback(alias);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void RemoveDisposeCallback(
            IAlias alias
            )
        {
            try
            {
                lock (syncRoot)
                {
                    if (postDisposeCallbacks != null)
                    {
                        DisposeCallback callback = alias.PostInterpreterDisposed;

                        if (callback != null)
                            postDisposeCallbacks -= callback;
                    }
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void FirePreDisposeCallbacks()
        {
            try
            {
                lock (syncRoot) /* TRANSACTIONAL */
                {
                    if (preDisposeCallbacks != null)
                    {
                        bool savedExit = this.PrivateExit;

                        try
                        {
                            //
                            // HACK: Permit script evaluation during pre-disposal
                            //       callbacks by temporarily resetting the exit
                            //       flag.
                            //
                            this.PrivateExit = false;

                            preDisposeCallbacks(this);
                            preDisposeCallbacks = null;
                        }
                        finally
                        {
                            this.PrivateExit = savedExit;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void FirePostDisposeCallbacks()
        {
            try
            {
                lock (syncRoot) /* TRANSACTIONAL */
                {
                    if (postDisposeCallbacks != null)
                    {
                        postDisposeCallbacks(this);
                        postDisposeCallbacks = null;
                    }
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(String.Format(
                    "{0}: {1}{2}",
                    GlobalState.GetCurrentThreadId(),
                    e, Environment.NewLine),
                    typeof(Interpreter).Name);
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For now, this event is internal only; however, it may
        //       eventually be exposed.
        //
        internal event DisposeCallback PreInterpreterDisposed
        {
            add
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    preDisposeCallbacks -= value;
                    preDisposeCallbacks += value;
                }
            }
            remove
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    preDisposeCallbacks -= value;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // NOTE: For now, this event is internal only; however, it may
        //       eventually be exposed.
        //
        internal event DisposeCallback PostInterpreterDisposed
        {
            add
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    postDisposeCallbacks -= value;
                    postDisposeCallbacks += value;
                }
            }
            remove
            {
                // CheckDisposed();

                lock (syncRoot)
                {
                    postDisposeCallbacks -= value;
                }
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        internal bool Deleted
        {
            get
            {
                lock (syncRoot)
                {
                    //
                    // NOTE: This flag is special.  Non-zero indicates that the
                    //       interpreter is currently being disposed; however,
                    //       the disposal process has not yet completed.  This
                    //       flag is checked and enforced by the Ready method
                    //       to prevent scripts from being evaluated during the
                    //       disposal process.
                    //
                    return deleted;
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool PrivateDeleted
        {
            get { /* NO-LOCK */ return deleted; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool Disposed
        {
            get { return PrivateDisposed; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private bool PrivateDisposed
        {
            get { /* NO-LOCK */ return disposed; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool IsPendingDispose(
            Interpreter interpreter
            )
        {
            return (interpreter != null) && (interpreter.disposeCount > 0);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static bool IsDisposed(
            Interpreter interpreter
            )
        {
            return (interpreter != null) && interpreter.PrivateDisposed;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        internal static bool IsDeletedOrDisposed(
            Interpreter interpreter
            )
        {
            return (interpreter != null) &&
                (interpreter.PrivateDeleted || interpreter.PrivateDisposed);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed && Engine.IsThrowOnDisposed(this, true))
                throw new InterpreterDisposedException(this, typeof(Interpreter));
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private /* protected virtual */ void Dispose(bool disposing)
        {
            TraceOps.DebugTrace(String.Format(
                "Dispose: called via {0} for interpreter {1} on thread {2} " +
                "(primary thread is {3}), count is {4}, wait count is {5}, " +
                "wait spin count is {6}, already disposed is {7}{8}", disposing ?
                    typeof(IDisposable).Name : "destructor", id,
                GlobalState.GetCurrentThreadId(), threadId, disposeCount,
                waitCount, waitSpinCount, disposed, Environment.NewLine),
                typeof(Interpreter).Name);

            if (!disposed)
            {
                if (Interlocked.Increment(ref disposeCount) == 1)
                {
#if NOTIFY || NOTIFY_OBJECT
                    //
                    // BUGFIX: Prevent notifications from firing and indirectly
                    //         recreating anything we have torn down (especially
                    //         thread specific data).
                    //
                    lock (syncRoot)
                    {
                        notifyFlags |= NotifyFlags.NoNotify;
                    }
#endif

                    //
                    // NOTE: Allow callbacks to figure out which interpreter is
                    //       terminating them (even if they were not directly
                    //       passed an Interpreter object).
                    //
                    GlobalState.PushActiveInterpreter(this);

                    //
                    // NOTE: Invoke the registered interpreter disposal callbacks
                    //       now, if any.
                    //
                    FirePreDisposeCallbacks();

                    //
                    // NOTE: Grab the lock [temporarily] to set the deleted
                    //       flag for the interpreter.
                    //
                    lock (syncRoot)
                    {
                        //
                        // NOTE: Mark this interpreter as "deleted" (i.e. "deletion
                        //       pending") so that any "user callbacks" do not attempt
                        //       to get too clever with their shutdown/cleanup code
                        //       (i.e. no script evaluation, etc).
                        //
                        if (!deleted)
                            deleted = true;
                    }

                    //
                    // NOTE: Unblock any and all pending wait calls now.  When they
                    //       awaken, they should realize that the interpreter has been
                    //       deleted [out from under them] and bail out.
                    //
                    SignalVariableEvent();

                    //
                    // NOTE: Used to keep track of how long we waited for the other
                    //       thread(s) to exit their variable wait states.
                    //
                    int elapsedMilliseconds = 0;

                    //
                    // HACK: Now, block until the pending calls to WaitVariable are
                    //       all cleared.  This is potentially dangerous because it
                    //       could block on the GC thread (?).  This loop is designed
                    //       to keep waiting until the wait count is zero OR until
                    //       the maximum timeout is reached (currently about 3000
                    //       milliseconds).  Also, since the deleted flag has already
                    //       been set for the interpreter (above), we should not have
                    //       to worry about waits being started after this point.
                    //
                    // BUGFIX: Calling the GetMinimumSleepTime method here was causing
                    //         an exception because the event manager was already
                    //         disposed via the GC.  In the future, much more care is
                    //         required to prevent this method from accessing anything
                    //         that can throw ObjectDisposedException.
                    //
                    int sleepMilliseconds = GetMinimumSleepTime();

                    while (Interlocked.CompareExchange(ref waitCount, 0, 0) != 0)
                    {
                        //
                        // NOTE: Wait for a while to give other threads a chance to
                        //       unwind out of their variable wait states.
                        //
                        HostOps.Sleep(sleepMilliseconds);

                        //
                        // NOTE: Keep track of the total elapsed wait time.  If this
                        //       value exceeds the total [default] allowed wait time,
                        //       report this situation as an error and bail out.
                        //
                        elapsedMilliseconds += sleepMilliseconds;

                        if (elapsedMilliseconds > ThreadOps.DefaultJoinTimeout)
                        {
                            TraceOps.DebugTrace(String.Format(
                                "{0}: Dispose: timeout waiting, interpreter = {1}, " +
                                "sleepMilliseconds = {2}, elapsedMilliseconds = {3}{4}",
                                GlobalState.GetCurrentThreadId(), id, sleepMilliseconds,
                                elapsedMilliseconds, Environment.NewLine),
                                typeof(Interpreter).Name);

                            break;
                        }
                    }

                    TraceOps.DebugTrace(String.Format(
                        "{0}: Dispose: done waiting, interpreter = {1}, " +
                        "sleepMilliseconds = {2}, elapsedMilliseconds = {3}{4}",
                        GlobalState.GetCurrentThreadId(), id, sleepMilliseconds,
                        elapsedMilliseconds, Environment.NewLine),
                        typeof(Interpreter).Name);

                    //
                    // NOTE: We obtain and hold the lock on the Interpreter
                    //       SyncRoot for almost the entire duration of the
                    //       cleanup.
                    //
                    lock (syncRoot)
                    {
                        //
                        // NOTE: If the interpreter was read-only and/or immutable,
                        //       we need to unset those flags before proceeding;
                        //       otherwise, commands and plugins cannot be terminated
                        //       gracefully.
                        //
                        if (readOnly)
                            readOnly = false;

                        if (immutable)
                            immutable = false;

                        //
                        // BUGFIX: Disposal ordering issue.  We do not care about
                        //         this if the host has already been disposed.
                        //
                        try
                        {
                            //
                            // NOTE: Mark host as in "exit mode" for additional
                            //       help in troubleshooting any shutdown issues.
                            //       This does not need to be undone later because
                            //       the host will also be disposed below.
                            //
                            if ((host != null) &&
                                FlagOps.HasFlags(host.GetFlags(), HostFlags.Exit, true))
                            {
                                host.Exiting = true;
                            }
                        }
                        catch
                        {
                            // do nothing.
                        }

                        //
                        // NOTE: Are we disposing (or being called via the finalizer)?
                        //
                        if (disposing)
                        {
                            ////////////////////////////////////
                            // dispose managed resources here...
                            ////////////////////////////////////

                            //
                            // BUGFIX: Does the interpreter have an active
                            //         finally timeout thread?  If so, stop
                            //         it now.
                            //
                            ReturnCode timeoutCode;
                            Result timeoutResult = null;

                            timeoutCode = InterruptFinallyTimeoutThread(
                                this, false, ref timeoutResult);

                            if (timeoutCode != ReturnCode.Ok)
                            {
                                DebugOps.Complain(this,
                                    timeoutCode, timeoutResult);
                            }

                            ///////////////////////////////////////////////////

                            //
                            // BUGFIX: Does the interpreter have an active
                            //         timeout thread?  If so, stop it now.
                            //
                            timeoutCode = InterruptTimeoutThread(
                                this, false, ref timeoutResult);

                            if (timeoutCode != ReturnCode.Ok)
                            {
                                DebugOps.Complain(this,
                                    timeoutCode, timeoutResult);
                            }

                            ///////////////////////////////////////////////////

#if SHELL && INTERACTIVE_COMMANDS
                            //
                            // BUGFIX: Does the interpreter have an active
                            //         garbage collection test thread?  If
                            //         so, stop it now.
                            //
                            if (TestOps.HasGcThread(this))
                            {
                                ReturnCode gcCode;
                                Result gcResult = null;

                                gcCode = TestOps.InterruptGcThread(
                                    this, false, ref gcResult);

                                if (gcCode != ReturnCode.Ok)
                                {
                                    DebugOps.Complain(this,
                                        gcCode, gcResult);
                                }
                            }
#endif

                            ///////////////////////////////////////////////////

                            //
                            // NOTE: Dispose any nested interpreters first.
                            //
                            DisposeSlaveInterpreters();

                            //
                            // NOTE: Attempt to terminuate managed plugins
                            //       gracefully.
                            //
                            DisposePlugins(false);

                            //
                            // NOTE: Attempt to terminuate managed commands
                            //       gracefully.
                            //
                            DisposeCommands(false);
                            DisposeHiddenCommands(false);

                            //
                            // NOTE: Attempt to terminuate user commands,
                            //       functions, and operators gracefully.
                            //
                            DisposeOperators();
                            DisposeFunctions();

#if DATA
                            //
                            // NOTE: Attempt to dispose our database related
                            //       objects, if any.
                            //
                            DisposeTransactions();
                            DisposeConnections();
#endif

                            //
                            // NOTE: Attempt to dispose all script visible
                            //       objects.
                            //
                            DisposeObjects();

                            //
                            // NOTE: Dispose of the open channels, if any.
                            //
                            DisposeChannels();

#if LIST_CACHE || PARSE_CACHE || EXECUTE_CACHE || TYPE_CACHE || COM_TYPE_CACHE
                            //
                            // NOTE: Clear our cached data.
                            //
                            ResetCaches();
#endif

                            //
                            // NOTE: Dispose the event manager, if any.
                            //
                            DisposeEventManager();

                            //
                            // NOTE: Clear all the "plain old data" objects
                            //       associated with this interpreter.
                            //
                            ResetEarlyPodObjects();
                        }

                        //////////////////////////////////////
                        // release unmanaged resources here...
                        //////////////////////////////////////

                        //
                        // NOTE: Attempt to terminuate all the remaining
                        //       (unmanaged) plugins gracefully.
                        //
                        DisposePlugins(true);

                        //
                        // NOTE: Attempt to terminuate all the remaining
                        //       (unmanaged) commands gracefully.
                        //
                        DisposeCommands(true);
                        DisposeHiddenCommands(true);

                        //
                        // NOTE: Dispose the packages now.  We do this after
                        //       the plugins because they may wish to withdraw
                        //       their associated package(s).
                        //
                        DisposePackages();

#if NATIVE && LIBRARY
                        //
                        // NOTE: Attempt to dispose the native delegates, if
                        //       any.
                        //
                        DisposeDelegates();

                        //
                        // NOTE: Attempt to dispose the native modules, if any.
                        //
                        DisposeModules();
#endif

#if APPDOMAINS
                        //
                        // NOTE: Dispose (i.e. unload) AppDomains that we own,
                        //       if any.
                        //
                        DisposeAppDomains();
#endif

                        //
                        // NOTE: Try to delete all namespaces now, starting
                        //       with the global namespace and working our
                        //       way down the "logical tree".
                        //
                        DisposeNamespaces();

                        //
                        // NOTE: Policies, packages, and package indexes, etc
                        //       are simply data, clear them now.  We have to
                        //       wait until this point in case plugins refer
                        //       to any of them while unloading.
                        //
                        ResetLatePodObjects();

#if DEBUGGER && !THREADING
                        //
                        // NOTE: Dispose our debugger, if any, now.
                        //
                        DisposeDebugger();
#endif

                        //
                        // NOTE: Close the variable event.
                        //
                        ThreadOps.CloseEvent(ref variableEvent);

                        //
                        // NOTE: Reset the user-defined and application-defined
                        //       objects.  We do not "dispose" these objects
                        //       because they do not belong to us.
                        //
                        ResetUserObjects();
                    }

#if NATIVE && TCL
                    //
                    // NOTE: Dispose of our [native] Tcl related objects,
                    //       if any, now.  If we are on the wrong thread, the
                    //       orphaned objects will be turned into "zombies" for
                    //       later pickup by the next Interpreter object to be
                    //       created on this thread.  Complaints (i.e. priority
                    //       error messages) will be reported if any errors are
                    //       encountered during this disposal process.
                    //
                    // HACK: Perhaps stronger measures are needed here to help
                    //       prevent resource leaks?  However, the Dispose
                    //       method is a very limited place.  For one thing, it
                    //       has no means of communicating failure to the caller,
                    //       which may be the GC thread (i.e. it is not supposed
                    //       to throw exceptions and it returns no results).
                    //
                    // WARNING: All users of Interpreter objects are STRONGLY
                    //          advised and encouraged to Dispose of their
                    //          Interpreter objects [on the same thread they
                    //          were created on] just as soon as they are
                    //          finished with them; otherwise, all the [native]
                    //          resources used by them will be disposed of
                    //          on a "best-effort" basis.
                    //
                    DisposeTcl(true, disposing, false);
#endif

                    //
                    // NOTE: Dispose all the thread-specific data for the
                    //       interpreter for this thread [only].
                    //
                    DisposeThread(true, disposing);

#if THREADING
                    //
                    // NOTE: The context manager has just been freed; therefore,
                    //       clear it now.
                    //
                    contextManager = null;

                    //
                    // NOTE: Purge all contexts for this thread from the context
                    //       manager that refer to [other] disposed interpreters.
                    //
                    ContextManager.Purge(false);
#endif

                    //
                    // NOTE: Dispose the host environment last.  This must now
                    //       be done without holding the lock on the Interpreter
                    //       SyncRoot; otherwise, a deadlock can occur.
                    //
                    //       Deadlock Example:
                    //
                    //       1. This thread (thread #1) holds the lock on the
                    //          Interpreter SyncRoot and wants the implicit lock
                    //          on the System.Console object to remove the
                    //          ConsoleCancelEventHandler.
                    //
                    //       2. The other thread (thread #2) holds the implicit
                    //          lock on the System.Console object while the call
                    //          to CancelEvaluate is pending awaiting the lock
                    //          on the Interpreter SyncRoot.
                    //
                    DisposeHost();

                    //
                    // NOTE: Invoke the registered interpreter disposal callbacks
                    //       now, if any.
                    //
                    FirePostDisposeCallbacks();

                    //
                    // NOTE: Remove this interpreter from the active interpreter
                    //       stack.
                    //
                    /* IGNORED */
                    GlobalState.PopActiveInterpreter();

                    //
                    // NOTE: Finally, remove this interpreter from the master
                    //       interpreter list.
                    //
                    /* IGNORED */
                    GlobalState.RemoveInterpreter(this);

                    //
                    // NOTE: Grab the global notify setting now because we need it
                    //       after marking the interpreter as disposed.
                    //
                    bool notify = this.GlobalNotify;

                    //
                    // NOTE: This object is now fully disposed.  We have reset
                    //       all of the internal data necessary for this object to
                    //       function correctly and there is currently no supported
                    //       way to "revive" it; therefore, it should never be used
                    //       again after this point.  This constraint is [normally]
                    //       enforced by the CheckDisposed method, which is called
                    //       from every publically accessible property and method
                    //       of this class.
                    //
                    disposed = true;

#if NOTIFY && NOTIFY_GLOBAL
                    //
                    // BUGFIX: Only notify other interpreters if the global notify
                    //         setting is enabled.  This prevents subtle locking
                    //         issues when tearing down interpreters that belong to
                    //         different threads [OR interpreters that are currently
                    //         being used from different threads].
                    //
                    if (notify)
                        /* IGNORED */
                        CheckNotifications(
                            null, false,
                            NotifyType.Interpreter, NotifyFlags.Removed,
                            null, this,
                            null, null, null);
#endif
                }
            }

            TraceOps.DebugTrace(String.Format(
                "{0}: Dispose: exited, interpreter = {1}, disposing = {2}{3}",
                GlobalState.GetCurrentThreadId(), id, disposing,
                Environment.NewLine), typeof(Interpreter).Name);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region System.Object Overrides
        public override bool Equals(object obj)
        {
            CheckDisposed();

            return Object.ReferenceEquals(this, obj);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public override int GetHashCode()
        {
            CheckDisposed();

            return GetHashCodeNoThrow();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public override string ToString()
        {
            CheckDisposed();

            return id.ToString();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable Members
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Static Constructor
        static Interpreter()
        {
            //
            // HACK: Force the static GlobalState class to be initialized now
            //       because it is required by quite a few other classes.
            //
            /* IGNORED */
            GlobalState.GetPackageName();

#if NATIVE && WINDOWS
            SetupOps.CreateMutexes();
#endif
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Constructors
        private Interpreter()
        {
            //
            // NOTE: This constructor is private because Interpreter objects MUST
            //       be created via the static Interpreter.Create factory method.
            //
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Destructor
        ~Interpreter()
        {
            Dispose(false);
        }
        #endregion
    }
}
