Ejemplo n.º 1
0
        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
        public _Hash(
            ICommandData commandData
            )
            : base(commandData)
        {
            lock (syncRoot)
            {
                if (defaultAlgorithms == null)
                {
                    try
                    {
                        defaultAlgorithms = GetAlgorithms();
                    }
                    catch (Exception e)
                    {
                        TraceOps.DebugTrace(
                            e, typeof(_Hash).Name,
                            TracePriority.InternalError);
                    }

                    //
                    // HACK: Prevent this block from being entered again for
                    //       this application domain.
                    //
                    if (defaultAlgorithms == null)
                    {
                        defaultAlgorithms = new StringList();
                    }
                }
            }
        }
Ejemplo n.º 2
0
        ///////////////////////////////////////////////////////////////////////

        internal static bool Dispose(
            IEvent @event /* in */
            )
        {
            try
            {
                IDisposable disposable = @event as IDisposable;

                if (disposable != null)
                {
                    disposable.Dispose(); /* throw */
                    disposable = null;

                    return(true);
                }
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(
                    e, typeof(Event).Name,
                    TracePriority.EventError);
            }

            return(false);
        }
Ejemplo n.º 3
0
        ///////////////////////////////////////////////////////////////////////

        public ReturnCode VerifyModule(
            ref Result error
            )
        {
            if (String.IsNullOrEmpty(fileName))
            {
                error = "invalid Tcl native module file name";
                return(ReturnCode.Error);
            }

            if (!NativeOps.IsValidHandle(module))
            {
                error = "invalid Tcl native module handle";
                return(ReturnCode.Error);
            }

            //
            // HACK: We cannot actually verify the native module handle on any
            //       non-Windows operating system.
            //
            if (!PlatformOps.IsWindowsOperatingSystem())
            {
                return(ReturnCode.Ok);
            }

            try
            {
                IntPtr newModule = NativeOps.GetModuleHandle(fileName);

                if (newModule == IntPtr.Zero)
                {
                    error = String.Format(
                        "bad Tcl native module handle {0}, file name {1} is " +
                        "no longer loaded", module, FormatOps.WrapOrNull(
                            fileName));

                    TraceOps.DebugTrace(String.Format(
                                            "VerifyModule: {0}", FormatOps.WrapOrNull(error)),
                                        typeof(TclModule).Name, TracePriority.NativeError);

                    return(ReturnCode.Error);
                }

                if (newModule != module)
                {
                    //
                    // NOTE: This situation should really never happen.  If it
                    //       does, that indicates that the native Tcl module
                    //       was unloaded and then reloaded out from under the
                    //       native Tcl integration subsystem.
                    //
                    error = String.Format(
                        "bad Tcl native module handle {0}, got {1} for file " +
                        "name {2}", module, newModule, FormatOps.WrapOrNull(
                            fileName));

                    TraceOps.DebugTrace(String.Format(
                                            "VerifyModule: {0}",
                                            FormatOps.WrapOrNull(error)),
                                        typeof(TclModule).Name, TracePriority.NativeError);

                    return(ReturnCode.Error);
                }

                return(ReturnCode.Ok);
            }
            catch (Exception e)
            {
                error = e;
            }

            return(ReturnCode.Error);
        }
Ejemplo n.º 4
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    if (arguments.Count >= 1)
                    {
                        OptionDictionary options = new OptionDictionary(
                            new IOption[] {
                            new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-force", null),
                            new Option(null, OptionFlags.Unsafe, Index.Invalid, Index.Invalid, "-fail", null),
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid, Index.Invalid, "-message", null),
                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-current", null),
                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                        });

                        int argumentIndex = Index.Invalid;

                        if (arguments.Count > 1)
                        {
                            code = interpreter.GetOptions(options, arguments, 0, 1, Index.Invalid, false, ref argumentIndex, ref result);
                        }
                        else
                        {
                            code = ReturnCode.Ok;
                        }

                        if (code == ReturnCode.Ok)
                        {
                            if ((argumentIndex == Index.Invalid) ||
                                ((argumentIndex + 1) == arguments.Count))
                            {
                                bool force = false;

                                if (options.IsPresent("-force"))
                                {
                                    force = true;
                                }

                                bool fail = false;

                                if (options.IsPresent("-fail"))
                                {
                                    fail = true;
                                }

                                Variant value   = null;
                                string  message = null;

                                if (options.IsPresent("-message", ref value))
                                {
                                    message = value.ToString();
                                }

                                //
                                // NOTE: The default exit code is "success" (i.e. zero).
                                //
                                ExitCode exitCode = ResultOps.SuccessExitCode();

                                if (options.IsPresent("-current"))
                                {
                                    exitCode = interpreter.ExitCode;
                                }

                                //
                                // NOTE: Was an exit code specified in the command?
                                //
                                if (argumentIndex != Index.Invalid)
                                {
                                    object enumValue = EnumOps.TryParseEnum(
                                        typeof(ExitCode), arguments[argumentIndex],
                                        true, true, ref result);

                                    if (enumValue is ExitCode)
                                    {
                                        exitCode = (ExitCode)enumValue;
                                    }
                                    else
                                    {
                                        result = ScriptOps.BadValue(
                                            null, "exit code", arguments[argumentIndex],
                                            Enum.GetNames(typeof(ExitCode)), null, ", or an integer");

                                        code = ReturnCode.Error;
                                    }
                                }

                                //
                                // NOTE: Make sure we succeeded at coverting the exit code to an integer.
                                //
                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Make sure the interpreter host, if any, agrees to exit (i.e. it may deny the
                                    //       request if the application is doing something that should not be interrupted).
                                    //
                                    code = interpreter.CanExit(exitCode, force, fail, message, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        //
                                        // NOTE: Exit the application (either by marking the current interpreter as "exited"
                                        //       or physically exiting the containing process).
                                        //
                                        TraceOps.DebugTrace(String.Format(
                                                                "Execute: {0}, interpreter = {1}, message = {2}",
                                                                force && fail ?
                                                                "forcibly failing" : force ? "forcibly exiting" : "exiting",
                                                                FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(message)),
                                                            typeof(Exit).Name, TracePriority.Command);

                                        if (force)
                                        {
#if !MONO
                                            if (fail && !CommonOps.Runtime.IsMono())
                                            {
                                                try
                                                {
                                                    //
                                                    // NOTE: Using this method to exit a script is NOT recommended unless
                                                    //       you are trying to prevent damaging another part of the system.
                                                    //
                                                    // MONO: This method is not supported by the Mono runtime.
                                                    //
                                                    Environment.FailFast(message);

                                                    /* NOT REACHED */
                                                    result = "failed to exit process";
                                                    code   = ReturnCode.Error;
                                                }
                                                catch (Exception e)
                                                {
                                                    result = e;
                                                    code   = ReturnCode.Error;
                                                }
                                            }
                                            else
#endif
                                            {
                                                //
                                                // BUGFIX: Try to dispose our containing interpreter now.  We must do
                                                //         this to prevent it from being disposed on a random GC thread.
                                                //
                                                try
                                                {
                                                    interpreter.Dispose();
                                                    interpreter = null;
                                                }
                                                catch (Exception e)
                                                {
                                                    result = e;
                                                    code   = ReturnCode.Error;
                                                }

                                                //
                                                // NOTE: If we could not dispose the interpreter properly, complain;
                                                //       however, keep exiting anyway.
                                                //
                                                if (code != ReturnCode.Ok)
                                                {
                                                    DebugOps.Complain(interpreter, code, result);
                                                }

                                                try
                                                {
                                                    //
                                                    // NOTE: Using this method to exit a script is NOT recommended unless
                                                    //       you are running a standalone script in the Eagle Shell (i.e.
                                                    //       you are not hosted within another application).
                                                    //
                                                    Environment.Exit((int)exitCode);

                                                    /* NOT REACHED */
                                                    result = "failed to exit process";
                                                    code   = ReturnCode.Error;
                                                }
                                                catch (Exception e)
                                                {
                                                    result = e;
                                                    code   = ReturnCode.Error;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            interpreter.ExitCode = exitCode;
                                            interpreter.Exit     = true;

                                            result = String.Empty;
                                            code   = ReturnCode.Ok;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if ((argumentIndex != Index.Invalid) &&
                                    Option.LooksLikeOption(arguments[argumentIndex]))
                                {
                                    result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"exit ?options? ?returnCode?\"";
                                }

                                code = ReturnCode.Error;
                            }
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"exit ?options? ?returnCode?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Ejemplo n.º 5
0
        ///////////////////////////////////////////////////////////////////////

        #region INotify Members
        public override ReturnCode Notify(
            Interpreter interpreter,
            IScriptEventArgs eventArgs,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            //
            // NOTE: If we are disabled -OR- there are no event arguments -OR-
            //       this event does not match the kind we are interested in
            //       then just return "success" now.
            //
            if (disabled || (eventArgs == null) ||
                !FlagOps.HasFlags(
                    eventArgs.NotifyTypes, NotifyType.Engine, false) ||
                !FlagOps.HasFlags(
                    eventArgs.NotifyFlags, NotifyFlags.Executed, false))
            {
                return(ReturnCode.Ok);
            }

            //
            // NOTE: In "direct" mode, skip [almost] all the tracing ceremony
            //       and just call into Trace.WriteLine().  Otherwise, use the
            //       TraceOps class and all its special handling.  Either way,
            //       figure out the String.Format() arguments ahead of time,
            //       based on our current "normalize" and "ellipsis" settings.
            //
            try
            {
                string arg0 = FormatOps.WrapTraceOrNull(
                    normalizeArguments, ellipsisArguments, quoteArguments,
                    displayArguments, eventArgs.Arguments);

                string arg1 = FormatOps.WrapTraceOrNull(
                    normalizeResult, ellipsisResult, quoteResult,
                    displayResult, eventArgs.Result);

                if (direct)
                {
                    //
                    // NOTE: This is just an extremely thin wrapper around
                    //       the Trace.WriteLine method.
                    //
                    DebugOps.TraceWriteLine(String.Format(
                                                directFormat, arg0, arg1), directCategory);
                }
                else
                {
                    //
                    // NOTE: Use the tracing subsystem.
                    //
                    TraceOps.DebugTrace(String.Format(
                                            normalFormat, arg0, arg1), normalCategory,
                                        TracePriority.EngineDebug);
                }

                return(ReturnCode.Ok);
            }
            catch (Exception e)
            {
                TraceOps.DebugTrace(
                    e, typeof(Trace).Name,
                    TracePriority.EngineError);

                result = e;
                return(ReturnCode.Error);
            }
        }
Ejemplo n.º 6
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    if (arguments.Count >= 2)
                    {
                        OptionDictionary options = new OptionDictionary(
                            new IOption[] {
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-debug", null),                  // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-commandline", null),            // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-dequote", null),                // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-quoteall", null),               // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-unicode", null),                // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-ignorestderr", null),           // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-killonerror", null),            // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-keepnewline", null),            // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-noexitcode", null),             // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-nocapture", null),              // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-shell", null),                  // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-nocarriagereturns", null),      // simple switch
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, "-trimall", null),                // simple switch
                            new Option(typeof(ExitCode), OptionFlags.MustHaveEnumValue,
                                       Index.Invalid, Index.Invalid, "-success", null), // success exit code
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-domainname", null),
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-username", null),
                            new Option(null, OptionFlags.MustHaveSecureStringValue, Index.Invalid,
                                       Index.Invalid, "-password", null),
                            new Option(null, OptionFlags.MustHaveListValue, Index.Invalid,
                                       Index.Invalid, "-preprocessarguments", null), // command
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-directory", null),           // directory name
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-processid", null),           // varName for processId
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-exitcode", null),            // varName for exitCode
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-stdin", null),               // varName for StdIn input
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-stdout", null),              // varName for StdOut output
                            new Option(null, OptionFlags.MustHaveValue, Index.Invalid,
                                       Index.Invalid, "-stderr", null),              // varName for StdErr output
                            new Option(typeof(EventFlags), OptionFlags.MustHaveEnumValue,
                                       Index.Invalid, Index.Invalid, "-eventflags",
                                       new Variant(interpreter.EngineEventFlags)),
                            new Option(null, OptionFlags.None, Index.Invalid,
                                       Index.Invalid, Option.EndOfOptions, null)
                        });

                        int argumentIndex = Index.Invalid;

                        code = interpreter.GetOptions(options, arguments, 0, 1,
                                                      Index.Invalid, true, ref argumentIndex, ref result);

                        if (code == ReturnCode.Ok)
                        {
                            if (argumentIndex != Index.Invalid)
                            {
                                bool debug = false;

                                if (options.IsPresent("-debug"))
                                {
                                    debug = true;
                                }

                                bool commandLine = false;

                                if (options.IsPresent("-commandline"))
                                {
                                    commandLine = true;
                                }

                                bool dequote = false;

                                if (options.IsPresent("-dequote"))
                                {
                                    dequote = true;
                                }

                                bool quoteAll = false;

                                if (options.IsPresent("-quoteall"))
                                {
                                    quoteAll = true;
                                }

                                bool captureExitCode = true;

                                if (options.IsPresent("-noexitcode"))
                                {
                                    captureExitCode = false;
                                }

                                bool captureInput  = true;
                                bool captureOutput = true;

                                if (options.IsPresent("-nocapture"))
                                {
                                    captureInput  = false;
                                    captureOutput = false;
                                }

                                bool useUnicode = false;

                                if (options.IsPresent("-unicode"))
                                {
                                    useUnicode = true;
                                }

                                bool ignoreStdErr = false;

                                if (options.IsPresent("-ignorestderr"))
                                {
                                    ignoreStdErr = true;
                                }

                                bool killOnError = false;

                                if (options.IsPresent("-killonerror"))
                                {
                                    killOnError = true;
                                }

                                bool keepNewLine = false;

                                if (options.IsPresent("-keepnewline"))
                                {
                                    keepNewLine = true;
                                }

                                bool carriageReturns = true;

                                if (options.IsPresent("-nocarriagereturns"))
                                {
                                    carriageReturns = false;
                                }

                                bool trimAll = false;

                                if (options.IsPresent("-trimall"))
                                {
                                    trimAll = true;
                                }

                                bool useShellExecute = false;

                                if (options.IsPresent("-shell"))
                                {
                                    useShellExecute = true;
                                }

                                Variant  value           = null;
                                ExitCode?successExitCode = null;

                                if (options.IsPresent("-success", ref value))
                                {
                                    successExitCode = (ExitCode)value.Value;
                                }

                                string domainName = null;

                                if (options.IsPresent("-domainname", ref value))
                                {
                                    domainName = value.ToString();
                                }

                                string userName = null;

                                if (options.IsPresent("-username", ref value))
                                {
                                    userName = value.ToString();
                                }

                                SecureString password = null;

                                if (options.IsPresent("-password", ref value))
                                {
                                    password = (SecureString)value.Value;
                                }

                                string directory = null;

                                if (options.IsPresent("-directory", ref value))
                                {
                                    directory = value.ToString();
                                }

                                string processIdVarName = null;

                                if (options.IsPresent("-processid", ref value))
                                {
                                    processIdVarName = value.ToString();
                                }

                                string exitCodeVarName = null;

                                if (options.IsPresent("-exitcode", ref value))
                                {
                                    exitCodeVarName = value.ToString();
                                }

                                string stdInVarName = null;

                                if (options.IsPresent("-stdin", ref value))
                                {
                                    stdInVarName = value.ToString();
                                }

                                string stdOutVarName = null;

                                if (options.IsPresent("-stdout", ref value))
                                {
                                    stdOutVarName = value.ToString();
                                }

                                string stdErrVarName = null;

                                if (options.IsPresent("-stderr", ref value))
                                {
                                    stdErrVarName = value.ToString();
                                }

                                EventFlags eventFlags = interpreter.EngineEventFlags;

                                if (options.IsPresent("-eventflags", ref value))
                                {
                                    eventFlags = (EventFlags)value.Value;
                                }

                                StringList list = null;

                                if (options.IsPresent("-preprocessarguments", ref value))
                                {
                                    list = (StringList)value.Value;
                                }

                                int  argumentStopIndex = arguments.Count - 1;
                                bool background        = false;

                                if (arguments[arguments.Count - 1] ==
                                    Characters.Ampersand.ToString())
                                {
                                    argumentStopIndex--;
                                    background = true;
                                }

                                string execFileName = arguments[argumentIndex];

                                if (!PathOps.IsRemoteUri(execFileName))
                                {
                                    execFileName = PathOps.GetNativePath(execFileName);
                                }

                                string execArguments = null;

                                if ((argumentIndex + 1) < arguments.Count)
                                {
                                    if (commandLine)
                                    {
                                        execArguments = RuntimeOps.BuildCommandLine(
                                            ArgumentList.GetRangeAsStringList(arguments,
                                                                              argumentIndex + 1, argumentStopIndex,
                                                                              dequote),
                                            quoteAll);
                                    }
                                    else
                                    {
                                        execArguments = ListOps.Concat(arguments,
                                                                       argumentIndex + 1, argumentStopIndex);
                                    }
                                }

                                Result input = null;

                                if ((code == ReturnCode.Ok) && !useShellExecute &&
                                    captureInput && (stdInVarName != null))
                                {
                                    code = interpreter.GetVariableValue(VariableFlags.None,
                                                                        stdInVarName, ref input, ref result);
                                }

                                if (debug)
                                {
                                    TraceOps.DebugTrace(String.Format(
                                                            "Execute: interpreter = {0}, domainName = {1}, userName = {2}, " +
                                                            "password = {3}, execFileName = {4}, execArguments = {5}, " +
                                                            "directory = {6}, input = {7}, eventFlags = {8}, debug = {9}, " +
                                                            "commandLine = {10}, dequote = {11}, quoteAll = {12}, " +
                                                            "useShellExecute = {13}, captureExitCode = {14}, " +
                                                            "captureInput = {15}, captureOutput = {16}, useUnicode = {17}, " +
                                                            "ignoreStdErr = {18}, killOnError = {19}, keepNewLine = {20}, " +
                                                            "carriageReturns = {21}, trimAll = {22}, background = {23}, " +
                                                            "successExitCode = {24}, processIdVarName = {25}, exitCodeVarName = {26}, " +
                                                            "stdInVarName = {27}, stdOutVarName = {28}, stdErrVarName = {29}",
                                                            FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(domainName),
                                                            FormatOps.WrapOrNull(userName), FormatOps.WrapOrNull(password),
                                                            FormatOps.WrapOrNull(execFileName), FormatOps.WrapOrNull(execArguments),
                                                            FormatOps.WrapOrNull(directory), FormatOps.WrapOrNull(input),
                                                            FormatOps.WrapOrNull(eventFlags), debug, commandLine, dequote, quoteAll,
                                                            useShellExecute, captureExitCode, captureInput, captureOutput, useUnicode,
                                                            ignoreStdErr, killOnError, keepNewLine, carriageReturns, trimAll, background,
                                                            FormatOps.WrapOrNull(successExitCode), FormatOps.WrapOrNull(processIdVarName),
                                                            FormatOps.WrapOrNull(exitCodeVarName), FormatOps.WrapOrNull(stdInVarName),
                                                            FormatOps.WrapOrNull(stdOutVarName), FormatOps.WrapOrNull(stdErrVarName)),
                                                        typeof(Exec).Name, TracePriority.Command);
                                }

                                int      processId = 0;
                                ExitCode exitCode  = ResultOps.SuccessExitCode();
                                Result   error     = null;

                                if (code == ReturnCode.Ok)
                                {
                                    if (list != null)
                                    {
                                        list.Add(execFileName);
                                        list.Add(directory);
                                        list.Add(execArguments);

                                        code = interpreter.EvaluateScript(list.ToString(), ref result);

                                        if (code == ReturnCode.Return)
                                        {
                                            execArguments = result;
                                            code          = ReturnCode.Ok;
                                        }
                                        else if (code == ReturnCode.Continue)
                                        {
                                            code = ReturnCode.Ok;
                                            goto done;
                                        }
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        code = ProcessOps.ExecuteProcess(
                                            interpreter, domainName, userName, password, execFileName,
                                            execArguments, directory, input, eventFlags, useShellExecute,
                                            captureExitCode, captureOutput, useUnicode, ignoreStdErr,
                                            killOnError, keepNewLine, background, !background,
                                            ref processId, ref exitCode, ref result, ref error);
                                    }
                                }

done:

                                if (debug)
                                {
                                    TraceOps.DebugTrace(String.Format(
                                                            "Execute: interpreter = {0}, domainName = {1}, userName = {2}, " +
                                                            "password = {3}, execFileName = {4}, execArguments = {5}, " +
                                                            "directory = {6}, input = {7}, eventFlags = {8}, debug = {9}, " +
                                                            "commandLine = {10}, dequote = {11}, quoteAll = {12}, " +
                                                            "useShellExecute = {13}, captureExitCode = {14}, " +
                                                            "captureInput = {15}, captureOutput = {16}, useUnicode = {17}, " +
                                                            "ignoreStdErr = {18}, killOnError = {19}, keepNewLine = {20}, " +
                                                            "carriageReturns = {21}, trimAll = {22}, background = {23}, " +
                                                            "successExitCode = {24}, processIdVarName = {25}, exitCodeVarName = {26}, " +
                                                            "stdInVarName = {27}, stdOutVarName = {28}, stdErrVarName = {29}, " +
                                                            "processId = {30}, exitCode = {31}, result = {32}, error = {33}",
                                                            FormatOps.InterpreterNoThrow(interpreter), FormatOps.WrapOrNull(domainName),
                                                            FormatOps.WrapOrNull(userName), FormatOps.WrapOrNull(password),
                                                            FormatOps.WrapOrNull(execFileName), FormatOps.WrapOrNull(execArguments),
                                                            FormatOps.WrapOrNull(directory), FormatOps.WrapOrNull(input),
                                                            FormatOps.WrapOrNull(eventFlags), debug, commandLine, dequote, quoteAll,
                                                            useShellExecute, captureExitCode, captureInput, captureOutput, useUnicode,
                                                            ignoreStdErr, killOnError, keepNewLine, carriageReturns, trimAll, background,
                                                            FormatOps.WrapOrNull(successExitCode), FormatOps.WrapOrNull(processIdVarName),
                                                            FormatOps.WrapOrNull(exitCodeVarName), FormatOps.WrapOrNull(stdInVarName),
                                                            FormatOps.WrapOrNull(stdOutVarName), FormatOps.WrapOrNull(stdErrVarName),
                                                            processId, exitCode, FormatOps.WrapOrNull(true, true, result),
                                                            FormatOps.WrapOrNull(true, true, error)), typeof(Exec).Name,
                                                        TracePriority.Command);
                                }

                                //
                                // NOTE: Even upon failure, always set the variable to contain
                                //       process Id, if applicable.
                                //
                                if (processIdVarName != null)
                                {
                                    /* IGNORED */
                                    interpreter.SetVariableValue( /* EXEMPT */
                                        VariableFlags.NoReady, processIdVarName,
                                        processId.ToString(), null);
                                }

                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: Remove all carriage returns from output (leaving
                                    //       only line feeds as line separators)?
                                    //
                                    if (!carriageReturns)
                                    {
                                        if (!String.IsNullOrEmpty(result))
                                        {
                                            result = result.Replace(
                                                Characters.CarriageReturnString,
                                                String.Empty);
                                        }

                                        if (!String.IsNullOrEmpty(error))
                                        {
                                            error = error.Replace(
                                                Characters.CarriageReturnString,
                                                String.Empty);
                                        }
                                    }

                                    //
                                    // NOTE: Remove all surrounding whitespace from the output?
                                    //
                                    if (trimAll)
                                    {
                                        if (!String.IsNullOrEmpty(result))
                                        {
                                            result = result.Trim();
                                        }

                                        if (!String.IsNullOrEmpty(error))
                                        {
                                            error = error.Trim();
                                        }
                                    }

                                    //
                                    // NOTE: Now, "result" contains any StdOut output and "error"
                                    //        contains any StdErr output.
                                    //
                                    if ((code == ReturnCode.Ok) && !background &&
                                        captureExitCode && (exitCodeVarName != null))
                                    {
                                        code = interpreter.SetVariableValue(VariableFlags.None,
                                                                            exitCodeVarName, exitCode.ToString(), null, ref error);
                                    }

                                    if ((code == ReturnCode.Ok) && !useShellExecute &&
                                        !background && captureOutput && (stdOutVarName != null))
                                    {
                                        code = interpreter.SetVariableValue(VariableFlags.None,
                                                                            stdOutVarName, result, null, ref error);
                                    }

                                    if ((code == ReturnCode.Ok) && !useShellExecute &&
                                        !background && captureOutput && (stdErrVarName != null))
                                    {
                                        code = interpreter.SetVariableValue(VariableFlags.None,
                                                                            stdErrVarName, error, null, ref error);
                                    }

                                    //
                                    // NOTE: If they specified a "success" exit code, make sure
                                    //       that is the same as the exit code we actually got
                                    //       from the process.
                                    //
                                    if ((code == ReturnCode.Ok) && !background && captureExitCode &&
                                        (successExitCode != null) && (exitCode != successExitCode))
                                    {
                                        /* IGNORED */
                                        interpreter.SetVariableValue( /* EXEMPT */
                                            Engine.ErrorCodeVariableFlags, TclVars.ErrorCode,
                                            StringList.MakeList(
                                                "CHILDSTATUS", processId, exitCode),
                                            null);

                                        Engine.SetErrorCodeSet(interpreter, true);

                                        error = "child process exited abnormally";
                                        code  = ReturnCode.Error;
                                    }

                                    if (code != ReturnCode.Ok)
                                    {
                                        //
                                        // NOTE: Transfer error to command result.
                                        //
                                        result = error;
                                    }
                                }
                                else
                                {
                                    //
                                    // NOTE: Transfer error to command result.
                                    //
                                    result = error;
                                }
                            }
                            else
                            {
                                result = "wrong # args: should be \"exec ?options? arg ?arg ...?\"";
                                code   = ReturnCode.Error;
                            }
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"exec ?options? arg ?arg ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Ejemplo n.º 7
0
        ///////////////////////////////////////////////////////////////////////

        public virtual void TrimExcess( /* O(N) */
            int minimumCount,           /* in */
            int maximumCount,           /* in */
            int minimumRemoveCount,     /* in */
            int maximumRemoveCount,     /* in */
            int minimumAccessCount,     /* in */
            int maximumAccessCount,     /* in */
            ref int possibleRemoveCount /* out */
            )
        {
            //
            // NOTE: Initially, assume that we cannot do any trimming, due to
            //       the parameters specified by the caller; later, this may
            //       change.
            //
            possibleRemoveCount = 0;

            //
            // NOTE: Is there a maximum number of items configured for this
            //       cache?  If not, do nothing.
            //
            if (maximumCount >= 0)
            {
                //
                // NOTE: Grab the current number of items in this cache and see
                //       if it exceeds the configured maximum.
                //
                int beforeCount = this.Count;

                if (beforeCount > maximumCount)
                {
                    //
                    // NOTE: Figure out how many milliseconds it has been since
                    //       we last trimmed excess elements, if ever.
                    //
                    double milliseconds = GetLastTrimMilliseconds();

                    //
                    // NOTE: If we have never trimmed excess elements or it has
                    //       been longer than the configured time span, do it
                    //       again now.
                    //
                    if ((milliseconds == Milliseconds.Never) ||
                        (milliseconds > trimMilliseconds))
                    {
                        //
                        // NOTE: How many items need to be removed to fit
                        //       within the upper limit?
                        //
                        int removeCount = beforeCount - maximumCount;

                        //
                        // NOTE: We know that some trimming is possible;
                        //       if the correct parameters are specified
                        //       by the caller.
                        //
                        possibleRemoveCount = removeCount;

                        //
                        // NOTE: If there is no lower limit on the number
                        //       of items that should remain in the cache
                        //       -OR- the number of items that to remain
                        //       in the cache satisfies it, then proceed
                        //       with removing the items.
                        //
                        if (((minimumCount < 0) ||
                             ((beforeCount - removeCount) >= minimumCount)) &&
                            ((minimumRemoveCount < 0) ||
                             (removeCount >= minimumRemoveCount)))
                        {
                            //
                            // NOTE: If the number of items to be removed
                            //       exceeds the specified maximum, just
                            //       make it the specified maximum.
                            //
                            if ((maximumRemoveCount >= 0) &&
                                (removeCount > maximumRemoveCount))
                            {
                                removeCount = maximumRemoveCount;
                            }

                            //
                            // NOTE: Try to remove the specified number of
                            //       items.  This MAY have no effect -OR-
                            //       it may cause the removal of a different
                            //       number of items.
                            //
                            int foundCount   = 0;
                            int removedCount = 0;

                            Remove(minimumAccessCount, maximumAccessCount,
                                   removeCount, ref foundCount, ref removedCount);

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

#if DEBUG
                            if (removedCount != removeCount)
                            {
                                int afterCount = this.Count;

                                TraceOps.DebugTrace(String.Format(
                                                        "TrimExcess: minimumAccessCount = {0}, " +
                                                        "maximumAccessCount = {1}, " +
                                                        "removeCount = {2}, foundCount = {3}, " +
                                                        "removedCount = {4}, beforeCount = {5}, " +
                                                        "afterCount = {6}, trimCount = {7}",
                                                        minimumAccessCount, maximumAccessCount,
                                                        removeCount, foundCount, removedCount,
                                                        beforeCount, afterCount, trimCount),
                                                    GetType().Name, TracePriority.EngineDebug);
                            }
#endif

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

                            //
                            // NOTE: Ok, we have successfully trimmed the
                            //       excess elements, record the current
                            //       time so that we will not do it again
                            //       too soon.
                            //
                            lastTrim = Now; lastTrimCount = removedCount;

                            //
                            // NOTE: Another trim operation was completed.
                            //
                            trimCount++;
                        }
                    }
                }
            }
        }
Ejemplo n.º 8
0
        ///////////////////////////////////////////////////////////////////////////////////////////////

        private /* protected virtual */ void Dispose(
            bool disposing
            ) /* throw */
        {
            TraceOps.DebugTrace(String.Format(
                                    "Dispose: called, disposing = {0}, disposed = {1}",
                                    disposing, disposed), typeof(TclBridge).Name,
                                TracePriority.CleanupDebug);

            if (!disposed)
            {
                if (!this.disposing)
                {
                    //
                    // NOTE: We are now disposing this object (prevent re-entrancy).
                    //
                    this.disposing = true;

                    //
                    // NOTE: This method should not normally throw; however, if it does
                    //       we do not want our disposing flag to be stuck set to true.
                    //
                    try
                    {
                        //if (disposing)
                        //{
                        //    ////////////////////////////////////
                        //    // dispose managed resources here...
                        //    ////////////////////////////////////
                        //}

                        //////////////////////////////////////
                        // release unmanaged resources here...
                        //////////////////////////////////////

                        //
                        // NOTE: If necessary (and possible), delete the Tcl command via the
                        //       token we saved earlier (when the Tcl command was created).
                        //
                        ReturnCode deleteCode  = ReturnCode.Ok;
                        Result     deleteError = null;

                        //
                        // NOTE: If we have a valid command token then we are still hooked to
                        //       Tcl via our inbound native delegates and we must unhook
                        //       successfully or throw to prevent our internal object state
                        //       from being made inconsistent.
                        //
                        if (token != IntPtr.Zero)
                        {
                            if (interpreter != null)
                            {
                                ITclApi tclApi = TclApi.GetTclApi(interpreter);

                                //
                                // BUGFIX: We want to force deletion of this bridged command
                                //         if the force flag was specified upon creation OR
                                //         if the command is not actively being used.
                                //
                                deleteCode = TclWrapper.DeleteCommandFromToken(
                                    tclApi, interp, forceDelete || (objCmdProcLevels == 0),
                                    ref token, ref deleteError);
                            }
                            else
                            {
                                deleteError = "invalid interpreter";
                                deleteCode  = ReturnCode.Error;
                            }
                        }

                        //
                        // NOTE: Did we succeed in deleting the command from Tcl, if it
                        //       was necessary?
                        //
                        if (!noComplain && (deleteCode != ReturnCode.Ok))
                        {
                            //
                            // NOTE: If the command deletion was necessary and it failed
                            //       for any reason, complain very loudly.
                            //
                            DebugOps.Complain(interpreter, deleteCode, deleteError);

                            //
                            // BUGFIX: Also, we must throw an exception here to prevent
                            //         the delegates from being disposed while Tcl still
                            //         refers to them (tclLoad-1.2 GC race).
                            //
                            throw new ScriptException(deleteCode, deleteError);
                        }

                        //
                        // NOTE: If necessary, release the GCHandle that is keeping this
                        //       object alive.
                        //
                        if (handle.IsAllocated)
                        {
                            handle.Free();
                        }

                        //
                        // NOTE: We do not own these objects; therefore, we just null out
                        //       the references to them (in case we are the only thing
                        //       keeping them alive).
                        //
                        interpreter = null;
                        execute     = null;
                        clientData  = null;

                        //
                        // NOTE: Zero out our Tcl interpreter.  We do not delete it because
                        //       we do not own it.
                        //
                        interp = IntPtr.Zero;

                        //
                        // NOTE: Zero out our created Tcl command token.  We should not need
                        //       to call Tcl to delete the actual command because by this time
                        //       it should already have been deleted.
                        //
                        token = IntPtr.Zero;

                        //
                        // NOTE: Finally, we should be able to safely remove our references
                        //       to the Tcl callback delegates at this point because we already
                        //       deleted the Tcl command related to them.
                        //
                        objCmdProc    = null;
                        cmdDeleteProc = null;

                        //
                        // NOTE: Zero out our command nesting level.
                        //
                        objCmdProcLevels = 0;

                        //
                        // NOTE: This object is now disposed.
                        //
                        disposed = true;
                    }
                    finally
                    {
                        //
                        // NOTE: We are no longer disposing this object.
                        //
                        this.disposing = false;
                    }
                }
            }
        }
Ejemplo n.º 9
0
        ///////////////////////////////////////////////////////////////////////////////////////////////
        //
        // -- CmdDeleteProc --
        //
        // DeleteProc will be invoked when (if) name is deleted. This can occur through a
        // call to Tcl_DeleteCommand, Tcl_DeleteCommandFromToken, or Tcl_DeleteInterp, or
        // by replacing name in another call to Tcl_CreateObjCommand. DeleteProc is
        // invoked before the command is deleted, and gives the application an
        // opportunity to release any structures associated with the command.
        //
        private static void CmdDeleteProc(
            IntPtr clientData
            )
        {
            //
            // NOTE: We need to kill the associated TclBridge object
            //       instance and remove any references to the bridge
            //       from the containing interpreter.
            //
            try
            {
                //
                // NOTE: Rehydrate the handle from the clientData that Tcl just
                //       passed us.
                //
                GCHandle handle = GCHandle.FromIntPtr(clientData); /* throw */

                //
                // NOTE: Make sure the handle has a valid target.
                //
                if (handle.IsAllocated && (handle.Target != null))
                {
                    //
                    // NOTE: Attempt to cast the handle to a TclBridge object; if this
                    //       fails, we cannot continue to handle this call.
                    //
                    TclBridge tclBridge = handle.Target as TclBridge;

                    if (tclBridge != null)
                    {
                        //
                        // NOTE: Skip messing with the TclBridge or interpreter object if it is
                        //       already being disposed (i.e. we are NOT being called directly
                        //       due to the command being removed from the Tcl interpreter or
                        //       the Tcl interpreter being deleted). The caller of the dispose
                        //       method will handle removing the TclBridge object from the
                        //       collection in the interpreter.
                        //
                        if (!tclBridge.disposing)
                        {
                            //
                            // NOTE: Grab the associated interpreter from the TclBridge
                            //       object.
                            //
                            Interpreter interpreter = tclBridge.interpreter;

                            //
                            // NOTE: Remove all instances of the TclBridge object from its
                            //       interpreter.
                            //
                            if (interpreter != null)
                            {
                                /* IGNORED */
                                interpreter.RemoveTclBridges(tclBridge);
                            }

                            //
                            // NOTE: Prevent the Dispose method from trying to delete the Tcl
                            //       command itself (since it is already being deleted).
                            //
                            tclBridge.token = IntPtr.Zero;

                            //
                            // NOTE: Cleanup all the resources used by this TclBridge object.
                            //       In theory, this object disposal can throw; however, in
                            //       practice we know that it does not attempt to do anything
                            //       that can actually "fail" unless it has a valid command
                            //       token, which we have already cleared (Tcl has notified us,
                            //       by calling this delegate, that it has already deleted the
                            //       command in question).
                            //
                            tclBridge.Dispose(); /* throw */
                        }
                    }
                    else
                    {
                        TraceOps.DebugTrace(
                            "invalid Tcl bridge object",
                            typeof(Tcl_CmdDeleteProc).Name,
                            TracePriority.MarshalError);
                    }
                }
                else
                {
                    TraceOps.DebugTrace(
                        "invalid GC handle",
                        typeof(Tcl_CmdDeleteProc).Name,
                        TracePriority.MarshalError);
                }
            }
            catch (Exception e)
            {
                //
                // NOTE: Nothing we can do here except log the failure.
                //
                TraceOps.DebugTrace(
                    e, typeof(Tcl_CmdDeleteProc).Name,
                    TracePriority.NativeError);
            }
        }
Ejemplo n.º 10
0
        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Tcl Command Callbacks
        ///////////////////////////////////////////////////////////////////////////////////////////////
        // **** WARNING ***** BEGIN CODE DIRECTLY CALLED BY THE NATIVE TCL RUNTIME ***** WARNING **** /
        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // -- ObjCmdProc --
        //
        // When proc is invoked, the clientData and interp parameters will be copies of
        // the clientData and interp arguments given to Tcl_CreateObjCommand. Typically,
        // clientData points to an application-specific data structure that describes
        // what to do when the command procedure is invoked. Objc and objv describe the
        // arguments to the command, objc giving the number of argument objects
        // (including the command name) and objv giving the values of the arguments. The
        // objv array will contain objc values, pointing to the argument objects. Unlike
        // argv[argv] used in a string-based command procedure, objv[objc] will not
        // contain NULL. Additionally, when proc is invoked, it must not modify the
        // contents of the objv array by assigning new pointer values to any element of
        // the array (for example, objv[2] = NULL) because this will cause memory to be
        // lost and the runtime stack to be corrupted. The CONST in the declaration of
        // objv will cause ANSI-compliant compilers to report any such attempted
        // assignment as an error. However, it is acceptable to modify the internal
        // representation of any individual object argument. For instance, the user may
        // call Tcl_GetIntFromObj on objv[2] to obtain the integer representation of that
        // object; that call may change the type of the object that objv[2] points at,
        // but will not change where objv[2] points. proc must return an integer code
        // that is either TCL_OK, TCL_ERROR, TCL_RETURN, TCL_BREAK, or TCL_CONTINUE. See
        // the Tcl overview man page for details on what these codes mean. Most normal
        // commands will only return TCL_OK or TCL_ERROR. In addition, if proc needs to
        // return a non-empty result, it can call Tcl_SetObjResult to set the
        // interpreter's result. In the case of a TCL_OK return code this gives the
        // result of the command, and in the case of TCL_ERROR this gives an error
        // message. Before invoking a command procedure, Tcl_EvalObjEx sets interpreter's
        // result to point to an object representing an empty string, so simple commands
        // can return an empty result by doing nothing at all. The contents of the objv
        // array belong to Tcl and are not guaranteed to persist once proc returns: proc
        // should not modify them. Call Tcl_SetObjResult if you want to return something
        // from the objv array.
        //
        private static ReturnCode ObjCmdProc(
            IntPtr clientData,
            IntPtr interp,
            int objc,
            IntPtr objv
            )
        {
            ReturnCode code;

            try
            {
                //
                // NOTE: Rehydrate the handle from the clientData that Tcl just
                //       passed us.
                //
                GCHandle handle = GCHandle.FromIntPtr(clientData); /* throw */

                //
                // NOTE: Make sure the handle has a valid target.
                //
                if (handle.IsAllocated && (handle.Target != null))
                {
                    //
                    // NOTE: Attempt to cast the handle to a TclBridge object; if this
                    //       fails, we cannot continue to handle this call.
                    //
                    TclBridge tclBridge = handle.Target as TclBridge;

                    if (tclBridge != null)
                    {
                        Interlocked.Increment(ref tclBridge.objCmdProcLevels);

                        try
                        {
                            //
                            // NOTE: Grab the interpreter reference NOW, it may go bye bye if the
                            //       TclBridge object gets disposed.
                            //
                            Interpreter interpreter = tclBridge.interpreter;

                            if (interpreter != null)
                            {
                                //
                                // NOTE: Cache the fields of the interpreter object that we will
                                //       need to access below without holding a lock.
                                //
                                ITclApi     tclApi           = TclApi.GetTclApi(interpreter);
                                EngineFlags savedEngineFlags = interpreter.BeginExternalExecution();
                                bool        noCacheArgument  = false;

#if ARGUMENT_CACHE
                                if (Engine.HasNoCacheArgument(savedEngineFlags))
                                {
                                    noCacheArgument = true;
                                }
#endif

                                try
                                {
                                    if (tclApi != null)
                                    {
                                        Result   result  = null;
                                        IExecute execute = tclBridge.execute;

                                        if (execute != null)
                                        {
                                            ArgumentList arguments = new ArgumentList();

                                            for (int index = 0; index < objc; index++)
                                            {
                                                IntPtr objPtr =
                                                    Marshal.ReadIntPtr(objv, index * IntPtr.Size);

                                                string value =
                                                    TclWrapper.GetString(tclApi, objPtr);

                                                if (value == null)
                                                {
                                                    value = String.Empty;
                                                }

                                                arguments.Add(Argument.GetOrCreate(
                                                                  interpreter, value, noCacheArgument));
                                            }

                                            string name = (arguments.Count > 0) ? arguments[0] : null;

                                            try
                                            {
                                                code = interpreter.Execute(
                                                    name, execute, tclBridge.clientData, arguments,
                                                    ref result);
                                            }
                                            catch (Exception e)
                                            {
                                                result = String.Format(
                                                    "caught exception while executing: {0}",
                                                    e);

                                                code = ReturnCode.Error;
                                            }
                                        }
                                        else
                                        {
                                            result = "invalid execute object";
                                            code   = ReturnCode.Error;
                                        }

                                        //
                                        // NOTE: Set the Tcl interpreter result to the result of the
                                        //       Eagle command.
                                        //
                                        if (!String.IsNullOrEmpty(result))
                                        {
                                            TclWrapper.SetResult(
                                                tclApi, interp, TclWrapper.NewString(tclApi, result));
                                        }
                                        else
                                        {
                                            TclWrapper.ResetResult(tclApi, interp);
                                        }
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: There is no available Tcl API object; therefore, we
                                        //       cannot set the Tcl interpreter result.
                                        //
                                        TraceOps.DebugTrace(
                                            "invalid Tcl API object",
                                            typeof(Tcl_ObjCmdProc).Name,
                                            TracePriority.MarshalError);

                                        code = ReturnCode.Error;
                                    }
                                }
                                finally
                                {
                                    /* IGNORED */
                                    interpreter.EndAndCleanupExternalExecution(savedEngineFlags);
                                }
                            }
                            else
                            {
                                //
                                // NOTE: An invalid interpreter means that we have no Tcl API object to
                                //       work with either, punt on setting the Tcl interpreter result.
                                //
                                TraceOps.DebugTrace(
                                    "invalid interpreter",
                                    typeof(Tcl_ObjCmdProc).Name,
                                    TracePriority.MarshalError);

                                code = ReturnCode.Error;
                            }
                        }
                        finally
                        {
                            Interlocked.Decrement(ref tclBridge.objCmdProcLevels);
                        }
                    }
                    else
                    {
                        //
                        // NOTE: What now?  We have no way of communicating with Tcl at this
                        //       point.
                        //
                        TraceOps.DebugTrace(
                            "invalid Tcl bridge object",
                            typeof(Tcl_ObjCmdProc).Name,
                            TracePriority.MarshalError);

                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    //
                    // NOTE: Again, nothing we can do at this point.
                    //
                    TraceOps.DebugTrace(
                        "invalid GC handle",
                        typeof(Tcl_ObjCmdProc).Name,
                        TracePriority.MarshalError);

                    code = ReturnCode.Error;
                }
            }
            catch (Exception e)
            {
                //
                // NOTE: Nothing we can do here except log the failure.
                //
                TraceOps.DebugTrace(
                    e, typeof(Tcl_ObjCmdProc).Name,
                    TracePriority.NativeError);

                //
                // NOTE: At this point, we may not even be able to get to the Tcl API object
                //       we need to set the Tcl interpreter result; therefore, we are going
                //       to punt for now.
                //
                code = ReturnCode.Error;
            }

            return(code);
        }
Ejemplo n.º 11
0
        ///////////////////////////////////////////////////////////////////////

        #region Private
        private static bool IsPresent(
            OptionDictionary options,
            string name,
            bool noCase,
            bool strict,
            ref Variant value,
            ref int index
            )
        {
            if (options != null)
            {
                if (name != null)
                {
                    if (noCase)
                    {
                        //
                        // HACK: Perform a linear search of the options.  We
                        //       should not need to do this since the options
                        //       are in a dictionary; however, we want to
                        //       preserve the "case-sensitive" semantics unless
                        //       otherwise requested by the caller.
                        //
                        bool found = false;

                        foreach (KeyValuePair <string, IOption> pair in options)
                        {
                            if (String.Compare(pair.Key, 0, name, 0, name.Length,
                                               StringOps.SystemNoCaseStringComparisonType) == 0)
                            {
                                found = true;

                                IOption option = pair.Value;

                                if ((option != null) &&
                                    option.IsPresent(options, ref value))
                                {
                                    index = option.Index;
                                    return(true);
                                }
                            }
                        }

                        if (strict && !found)
                        {
                            //
                            // NOTE: This should not really happen, issue a
                            //       debug trace.
                            //
                            TraceOps.DebugTrace(String.Format(
                                                    "IsPresent: {0}",
                                                    BadOption(options, name)),
                                                typeof(OptionDictionary).Name,
                                                TracePriority.Command);
                        }
                    }
                    else
                    {
                        IOption option;

                        if (options.TryGetValue(name, out option))
                        {
                            if ((option != null) &&
                                option.IsPresent(options, ref value))
                            {
                                index = option.Index;
                                return(true);
                            }
                        }
                        else if (strict)
                        {
                            //
                            // NOTE: This should not really happen, issue a
                            //       debug trace.
                            //
                            TraceOps.DebugTrace(String.Format(
                                                    "IsPresent: {0}",
                                                    BadOption(options, name)),
                                                typeof(OptionDictionary).Name,
                                                TracePriority.Command);
                        }
                    }
                }
            }

            return(false);
        }