Example #1
0
        ///////////////////////////////////////////////////////////////////////

        #region Background Error Executor
        private static ReturnCode ExecuteBackgroundError(
            Interpreter interpreter,
            string handlerName,
            IExecute execute,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result,
            ref int errorLine
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return(ReturnCode.Error);
            }

            //
            // NOTE: Create a new call frame for the background error handler
            //       and push it.
            //
            ICallFrame frame = interpreter.NewTrackingCallFrame(
                StringList.MakeList("bgerror", handlerName),
                CallFrameFlags.BackgroundError);

            interpreter.PushAutomaticCallFrame(frame);

            try
            {
                //
                // NOTE: Save current engine flags and then enable external
                //       execution.
                //
                EngineFlags savedEngineFlags =
                    interpreter.BeginExternalExecution();

                try
                {
                    //
                    // NOTE: If the interpreter is configured to reset the
                    //       script cancellation flags prior to executing
                    //       the background error handler, do that now.
                    //
                    if (ScriptOps.HasFlags(
                            interpreter, InterpreterFlags.BgErrorResetCancel,
                            true))
                    {
                        /* IGNORED */
                        Engine.ResetCancel(interpreter, CancelFlags.BgError);
                    }

                    //
                    // NOTE: Evaluate the script and then check the result to
                    //       see if the background error handler failed or
                    //       canceled further background error handling for
                    //       this invocation of ProcessEvents.
                    //
                    ReturnCode code;

                    code = interpreter.Execute(
                        handlerName, execute, clientData, arguments,
                        ref result);

                    //
                    // NOTE: Maybe grab the new error line number, if any.
                    //
                    if (code != ReturnCode.Ok)
                    {
                        errorLine = Interpreter.GetErrorLine(interpreter);
                    }

                    //
                    // NOTE: We are done now, return.
                    //
                    return(code);
                }
                finally
                {
                    //
                    // NOTE: Restore saved engine flags, disabling external
                    //       execution as necessary.
                    //
                    /* IGNORED */
                    interpreter.EndAndCleanupExternalExecution(
                        savedEngineFlags);
                }
            }
            finally
            {
                //
                // 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.PopScopeCallFramesAndOneMore();
            }
        }
Example #2
0
        ///////////////////////////////////////////////////////////////////////

        public static ReturnCode HandleBackgroundError(
            Interpreter interpreter,
            ReturnCode code,
            Result result,
            ref bool bgError
            )
        {
            if (interpreter == null)
            {
                ReportBackgroundError(interpreter /* null */, null,
                                      "cannot handle background error, interpreter is " +
                                      "invalid.", "Original error", code, result, 0, null,
                                      ReturnCode.Ok, null, 0);

                return(ReturnCode.Error);
            }

            //
            // BUGFIX: Acquire the interpreter lock here; however, do not use
            //         the public property just in case the interpreter may be
            //         disposed at this point.
            //
            lock (interpreter.InternalSyncRoot) /* TRANSACTIONAL */
            {
                //
                // BUGFIX: Do not try to handle any background errors with a
                //         deleted or disposed interpreter.
                //
                if (Interpreter.IsDeletedOrDisposed(interpreter))
                {
                    ReportBackgroundError(interpreter /* disposed? */, null,
                                          "cannot handle background error, interpreter is " +
                                          "deleted or disposed.", "Original error", code,
                                          result, 0, null, ReturnCode.Ok, null, 0);

                    return(ReturnCode.Error);
                }

                int    errorLine   = Interpreter.GetErrorLine(interpreter);
                string handlerName = interpreter.BackgroundError;

                //
                // NOTE: If there is an invalid background error handler set,
                //       ignore the error.
                //
                if (!String.IsNullOrEmpty(handlerName))
                {
                    //
                    // NOTE: Must hold lock while processing the error.
                    //
                    // TODO: Need to more carefully analyze this lock usage at
                    //       some point.
                    //
                    lock (interpreter.SyncRoot) /* TRANSACTIONAL */
                    {
                        //
                        // NOTE: Should a failure to handle the background
                        //       error simply be ignored?
                        //
                        bool ignoreFailure = ScriptOps.HasFlags(interpreter,
                                                                InterpreterFlags.IgnoreBgErrorFailure, true);

                        //
                        // NOTE: We do not yet know if the background error
                        //       handler can actually be resolved.
                        //
                        bool haveBgError = false;

                        //
                        // NOTE: Construct a new argument list to pass along
                        //       to the actual error handler command, e.g.
                        //       "[list bgerror <message>]".
                        //
                        ArgumentList bgArguments = new ArgumentList(
                            handlerName, result);

                        //
                        // NOTE: Attempt to lookup the background error
                        //       handler via the current command resolvers
                        //       for the interpreter.  If this lookup fails
                        //       the default background error processing
                        //       will be used.
                        //
                        ReturnCode resolveCode;
                        Result     resolveError = null;
                        IExecute   bgExecute    = null;

                        resolveCode = interpreter.GetIExecuteViaResolvers(
                            interpreter.GetResolveEngineFlags(true),
                            handlerName, bgArguments, LookupFlags.Default,
                            ref bgExecute, ref resolveError);

                        if (resolveCode == ReturnCode.Ok)
                        {
                            //
                            // NOTE: We found a background error handler.
                            //
                            haveBgError = true;

                            //
                            // NOTE: Execute the background error handler now
                            //       and save the results.
                            //
                            ReturnCode bgCode;
                            Result     bgResult    = null;
                            int        bgErrorLine = 0;

                            bgCode = ExecuteBackgroundError(
                                interpreter, handlerName, bgExecute, null,
                                bgArguments, ref bgResult, ref bgErrorLine);

                            //
                            // NOTE: Now we handle the return code for the
                            //       background error handler.
                            //
                            if (bgCode == ReturnCode.Break)
                            {
                                //
                                // NOTE: A return code of "Break" indicates
                                //       that we should not call the background
                                //       error handler until the next time
                                //       ProcessEvents is invoked.
                                //
                                bgError = false;
                            }
                            else if (!ignoreFailure && (bgCode != ReturnCode.Ok))
                            {
                                //
                                // NOTE: Any other non-"Ok" return code is an
                                //       error an gets reported to the standard
                                //       error channel of the host, if any.
                                //
                                ReportBackgroundError(interpreter, handlerName,
                                                      "handler {0} failed for background error.",
                                                      "Original error", code, result, errorLine,
                                                      "Handler error", bgCode, bgResult,
                                                      bgErrorLine);
                            }
                        }

                        //
                        // NOTE: If there is no background error handler setup
                        //       just write the errorInfo to the error channel
                        //       (if possible).  If failures should be ignored,
                        //       skip reporting the problem.
                        //
                        if (!ignoreFailure && !haveBgError)
                        {
                            ReportBackgroundError(interpreter, handlerName,
                                                  "handler {0} missing for background error.",
                                                  "Original error", code, result, errorLine,
                                                  "Resolver error", resolveCode, resolveError,
                                                  0);
                        }
                    }
                }

                return(ReturnCode.Ok);
            }
        }
Example #3
0
        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IExecute Members
        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)
                    {
                        string subCommand = arguments[1];
                        bool   tried      = false;

                        code = ScriptOps.TryExecuteSubCommandFromEnsemble(
                            interpreter, this, clientData, arguments, true,
                            false, ref subCommand, ref tried, ref result);

                        if ((code == ReturnCode.Ok) && !tried)
                        {
                            switch (subCommand)
                            {
                            case "forget":
                            {
                                if (arguments.Count >= 2)
                                {
                                    code = interpreter.PkgForget(
                                        new StringList(arguments, 2), ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package forget ?package package ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "ifneeded":
                            {
                                if ((arguments.Count == 4) || (arguments.Count == 5))
                                {
                                    Version version = null;

                                    code = Value.GetVersion(
                                        arguments[3], interpreter.CultureInfo,
                                        ref version, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        string text = null;

                                        if (arguments.Count == 5)
                                        {
                                            text = arguments[4];
                                        }

                                        code = interpreter.PkgIfNeeded(
                                            arguments[2], version, text, interpreter.PackageFlags,
                                            ref result);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package ifneeded package version ?script?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "indexes":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    string pattern = null;

                                    if (arguments.Count == 3)
                                    {
                                        pattern = arguments[2];
                                    }

                                    code = interpreter.PkgIndexes(
                                        pattern, false, ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package indexes ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "info":
                            {
                                if (arguments.Count == 3)
                                {
                                    IPackage package = null;

                                    code = interpreter.GetPackage(
                                        arguments[2], LookupFlags.Default,
                                        ref package, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        bool         scrub = interpreter.IsSafe();
                                        PackageFlags flags = package.Flags;
                                        Guid         id    = AttributeOps.GetObjectId(package);

                                        result = StringList.MakeList(
                                            "kind", package.Kind,
                                            "id", package.Id.Equals(Guid.Empty) ? id : package.Id,
                                            "name", package.Name,
                                            "description", package.Description,
                                            "indexFileName", scrub ? PathOps.ScrubPath(
                                                GlobalState.GetBasePath(), package.IndexFileName) :
                                            package.IndexFileName,
                                            "provideFileName", scrub ? PathOps.ScrubPath(
                                                GlobalState.GetBasePath(), package.ProvideFileName) :
                                            package.ProvideFileName,
                                            "flags", flags,
                                            "loaded", (package.Loaded != null) ? package.Loaded : null,
                                            "ifNeeded", (!scrub && (package.IfNeeded != null)) ?
                                            package.IfNeeded.KeysAndValuesToString(null, false) :
                                            null);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package info name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "loaded":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    string pattern = null;

                                    if (arguments.Count == 3)
                                    {
                                        pattern = arguments[2];
                                    }

                                    code = interpreter.PkgLoaded(
                                        pattern, false, false, ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package loaded ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "names":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    string pattern = null;

                                    if (arguments.Count == 3)
                                    {
                                        pattern = arguments[2];
                                    }

                                    code = interpreter.PkgNames(
                                        pattern, false, ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package names ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "present":
                            {
                                if (arguments.Count >= 3)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-exact", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                                        });

                                    int argumentIndex = Index.Invalid;

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

                                    if (code == ReturnCode.Ok)
                                    {
                                        if ((argumentIndex != Index.Invalid) &&
                                            ((argumentIndex + 2) >= arguments.Count))
                                        {
                                            bool exact = false;

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

                                            Version version = null;

                                            if ((argumentIndex + 1) < arguments.Count)
                                            {
                                                code = Value.GetVersion(
                                                    arguments[argumentIndex + 1], interpreter.CultureInfo,
                                                    ref version, ref result);
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                code = interpreter.PresentPackage(
                                                    arguments[argumentIndex], version, exact, ref result);
                                            }
                                        }
                                        else
                                        {
                                            if ((argumentIndex != Index.Invalid) &&
                                                Option.LooksLikeOption(arguments[argumentIndex]))
                                            {
                                                result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"package present ?-exact? package ?version?\"";
                                            }

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package present ?-exact? package ?version?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "provide":
                            {
                                if ((arguments.Count == 3) || (arguments.Count == 4))
                                {
                                    PackageFlags flags = interpreter.PackageFlags;

                                    if (!FlagOps.HasFlags(flags, PackageFlags.NoProvide, true))
                                    {
                                        Version version = null;

                                        if (arguments.Count == 4)
                                        {
                                            code = Value.GetVersion(arguments[3], interpreter.CultureInfo, ref version, ref result);
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            code = interpreter.PkgProvide(arguments[2], version, flags, ref result);
                                        }
                                    }
                                    else
                                    {
                                        //
                                        // HACK: Do nothing, provide no package, and return nothing.
                                        //
                                        result = String.Empty;
                                        code   = ReturnCode.Ok;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package provide package ?version?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "relativefilename":
                            {
                                if ((arguments.Count == 3) || (arguments.Count == 4))
                                {
                                    PathComparisonType pathComparisonType = PathComparisonType.Default;

                                    if (arguments.Count == 4)
                                    {
                                        object enumValue = EnumOps.TryParseFlagsEnum(
                                            interpreter, typeof(PathComparisonType),
                                            pathComparisonType.ToString(), arguments[3],
                                            interpreter.CultureInfo, true, true, true,
                                            ref result);

                                        if (enumValue is EventFlags)
                                        {
                                            pathComparisonType = (PathComparisonType)enumValue;
                                        }
                                        else
                                        {
                                            code = ReturnCode.Error;
                                        }
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        string fileName = null;

                                        code = PackageOps.GetRelativeFileName(
                                            interpreter, arguments[2], pathComparisonType,
                                            ref fileName, ref result);

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = fileName;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package relativefilename fileName ?type?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "require":
                            {
                                if (arguments.Count >= 3)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-exact", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                                        });

                                    int argumentIndex = Index.Invalid;

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

                                    if (code == ReturnCode.Ok)
                                    {
                                        if ((argumentIndex != Index.Invalid) && ((argumentIndex + 2) >= arguments.Count))
                                        {
                                            bool exact = false;

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

                                            Version version = null;

                                            if ((argumentIndex + 1) < arguments.Count)
                                            {
                                                code = Value.GetVersion(
                                                    arguments[argumentIndex + 1], interpreter.CultureInfo,
                                                    ref version, ref result);
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                code = interpreter.RequirePackage(
                                                    arguments[argumentIndex], version, exact, ref result);
                                            }

                                            //
                                            // NOTE: This is a new feature.  If the initial attempt to
                                            //       require a package fails, call the package fallback
                                            //       delegate for the interpreter and then try requiring
                                            //       the package again.
                                            //
                                            if ((code != ReturnCode.Ok) && !ScriptOps.HasFlags(
                                                    interpreter, InterpreterFlags.NoPackageFallback, true))
                                            {
                                                PackageCallback packageFallback = interpreter.PackageFallback;

                                                if (packageFallback != null)
                                                {
                                                    code = packageFallback(
                                                        interpreter, arguments[argumentIndex], version, null,
                                                        interpreter.PackageFlags, exact, ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        code = interpreter.RequirePackage(
                                                            arguments[argumentIndex], version, exact, ref result);
                                                    }
                                                }
                                            }

                                            //
                                            // BUGFIX: This is really a new feature.  In the event of a failure
                                            //         here, we now fallback to the "unknown package handler",
                                            //         just like Tcl does.
                                            //
                                            if ((code != ReturnCode.Ok) && !ScriptOps.HasFlags(
                                                    interpreter, InterpreterFlags.NoPackageUnknown, true))
                                            {
                                                string text = interpreter.PackageUnknown + Characters.Space +
                                                              Parser.Quote(arguments[argumentIndex]);

                                                if (version != null)
                                                {
                                                    text += Characters.Space + Parser.Quote(version.ToString());
                                                }

                                                code = interpreter.EvaluateScript(text, ref result);         /* EXEMPT */

                                                if (code == ReturnCode.Ok)
                                                {
                                                    code = interpreter.RequirePackage(
                                                        arguments[argumentIndex], version, exact, ref result);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if ((argumentIndex != Index.Invalid) &&
                                                Option.LooksLikeOption(arguments[argumentIndex]))
                                            {
                                                result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"package require ?-exact? package ?version?\"";
                                            }

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package require ?-exact? package ?version?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "reset":
                            {
                                if (arguments.Count == 2)
                                {
                                    code = interpreter.ResetPkgIndexes(ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = String.Empty;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package reset\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "scan":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-interpreter", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-preferfilesystem", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-preferhost", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-host", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-normal", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nonormal", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-recursive", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-resolve", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-refresh", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-autopath", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                                        });

                                    int argumentIndex = Index.Invalid;

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

                                    if (code == ReturnCode.Ok)
                                    {
                                        lock (interpreter.SyncRoot)         /* TRANSACTIONAL */
                                        {
                                            PackageIndexFlags flags;

                                            if (options.IsPresent("-interpreter"))
                                            {
                                                flags = interpreter.PackageIndexFlags;
                                            }
                                            else
                                            {
                                                flags = PackageIndexFlags.Default;
                                            }

                                            if (options.IsPresent("-preferfilesystem"))
                                            {
                                                flags |= PackageIndexFlags.PreferFileSystem;
                                            }

                                            if (options.IsPresent("-preferhost"))
                                            {
                                                flags |= PackageIndexFlags.PreferHost;
                                            }

                                            if (options.IsPresent("-host"))
                                            {
                                                flags |= PackageIndexFlags.Host;
                                            }

                                            if (options.IsPresent("-normal"))
                                            {
                                                flags |= PackageIndexFlags.Normal;
                                            }

                                            if (options.IsPresent("-nonormal"))
                                            {
                                                flags |= PackageIndexFlags.NoNormal;
                                            }

                                            if (options.IsPresent("-recursive"))
                                            {
                                                flags |= PackageIndexFlags.Recursive;
                                            }

                                            if (options.IsPresent("-refresh"))
                                            {
                                                flags |= PackageIndexFlags.Refresh;
                                            }

                                            if (options.IsPresent("-resolve"))
                                            {
                                                flags |= PackageIndexFlags.Resolve;
                                            }

                                            bool autoPath = false;

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

                                            StringList paths;

                                            if (argumentIndex != Index.Invalid)
                                            {
                                                //
                                                // NOTE: Refresh the specified path list.
                                                //
                                                paths = new StringList(arguments, argumentIndex);
                                            }
                                            else
                                            {
                                                //
                                                // NOTE: Refresh the default path list.
                                                //
                                                paths = GlobalState.GetAutoPathList(interpreter, autoPath);

                                                //
                                                // NOTE: Did they request the auto-path be rebuilt?
                                                //
                                                if (autoPath)
                                                {
                                                    //
                                                    // NOTE: Since the actual auto-path may have changed,
                                                    //       update the variable now.  We disable traces
                                                    //       here because we manually rescan, if necessary,
                                                    //       below.
                                                    //
                                                    code = interpreter.SetLibraryVariableValue(
                                                        VariableFlags.SkipTrace, TclVars.AutoPath,
                                                        (paths != null) ? paths.ToString() : null,
                                                        ref result);
                                                }
                                            }

                                            if (code == ReturnCode.Ok)
                                            {
                                                PackageIndexDictionary packageIndexes = interpreter.CopyPackageIndexes();

                                                if (code == ReturnCode.Ok)
                                                {
                                                    code = PackageOps.FindAll(
                                                        interpreter, paths, flags, ref packageIndexes,
                                                        ref result);
                                                }

                                                if (code == ReturnCode.Ok)
                                                {
                                                    interpreter.PackageIndexes = packageIndexes;
                                                    result = String.Empty;
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package scan ?options? ?dir dir ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "unknown":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    if (arguments.Count == 3)
                                    {
                                        interpreter.PackageUnknown = arguments[2];
                                        result = String.Empty;
                                    }
                                    else
                                    {
                                        result = interpreter.PackageUnknown;
                                    }

                                    code = ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package unknown ?command?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "vcompare":
                            {
                                if (arguments.Count == 4)
                                {
                                    Version version1 = null;

                                    code = Value.GetVersion(
                                        arguments[2], interpreter.CultureInfo,
                                        ref version1, ref result);

                                    Version version2 = null;

                                    if (code == ReturnCode.Ok)
                                    {
                                        code = Value.GetVersion(
                                            arguments[3], interpreter.CultureInfo,
                                            ref version2, ref result);
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = PackageOps.VersionCompare(version1, version2);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package vcompare version1 version2\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "versions":
                            {
                                if (arguments.Count == 3)
                                {
                                    code = interpreter.PkgVersions(
                                        arguments[2], ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package versions package\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "vloaded":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    string pattern = null;

                                    if (arguments.Count == 3)
                                    {
                                        pattern = arguments[2];
                                    }

                                    code = interpreter.PkgLoaded(
                                        pattern, false, true, ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package vloaded ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "vsatisfies":
                            {
                                if (arguments.Count == 4)
                                {
                                    PackageFlags flags = interpreter.PackageFlags;

                                    if (!FlagOps.HasFlags(flags, PackageFlags.AlwaysSatisfy, true))
                                    {
                                        Version version1 = null;

                                        code = Value.GetVersion(arguments[2], interpreter.CultureInfo, ref version1, ref result);

                                        Version version2 = null;

                                        if (code == ReturnCode.Ok)
                                        {
                                            code = Value.GetVersion(
                                                arguments[3], interpreter.CultureInfo,
                                                ref version2, ref result);
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            result = PackageOps.VersionSatisfies(
                                                version1, version2, false);
                                        }
                                    }
                                    else
                                    {
                                        //
                                        // HACK: Always fake that this was a satisfied package request.
                                        //
                                        result = true;
                                        code   = ReturnCode.Ok;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package vsatisfies version1 version2\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "withdraw":
                            {
                                if ((arguments.Count == 3) || (arguments.Count == 4))
                                {
                                    Version version = null;

                                    if (arguments.Count == 4)
                                    {
                                        code = Value.GetVersion(
                                            arguments[3], interpreter.CultureInfo,
                                            ref version, ref result);
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        code = interpreter.WithdrawPackage(
                                            arguments[2], version, ref result);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"package withdraw package ?version?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            default:
                            {
                                result = ScriptOps.BadSubCommand(
                                    interpreter, null, null, subCommand, this, null, null);

                                code = ReturnCode.Error;
                                break;
                            }
                            }
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"package arg ?arg ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Example #4
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    //
                    // try {<tryBody>}
                    // [finally {<finallyBody>}]
                    //
                    if ((arguments.Count == 2) || (arguments.Count == 4))
                    {
                        if ((arguments.Count < 3) || (String.Compare(arguments[2],
                                                                     Try.Finally, StringOps.SystemStringComparisonType) == 0))
                        {
                            string name = StringList.MakeList("try");

                            ICallFrame frame = interpreter.NewTrackingCallFrame(name,
                                                                                CallFrameFlags.Try);

                            interpreter.PushAutomaticCallFrame(frame);

                            ReturnCode tryCode;
                            Result     tryResult = null;

                            tryCode = interpreter.EvaluateScript(arguments[1], ref tryResult);

                            if (tryCode == ReturnCode.Error)
                            {
                                Engine.AddErrorInformation(interpreter, tryResult,
                                                           String.Format("{0}    (\"try\" body line {1})",
                                                                         Environment.NewLine, Interpreter.GetErrorLine(interpreter)));
                            }

                            //
                            // 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.PopScopeCallFramesAndOneMore();

                            Result     finallyResult = null;
                            ReturnCode finallyCode   = ReturnCode.Ok;

                            if (arguments.Count == 4)
                            {
                                name = StringList.MakeList("finally");

                                frame = interpreter.NewTrackingCallFrame(name,
                                                                         CallFrameFlags.Finally);

                                interpreter.PushAutomaticCallFrame(frame);

                                //
                                // BUGFIX: Preserve any and all existing error related
                                //         information during evaluation of the finally
                                //         block.
                                //
                                Engine.SetNoResetError(interpreter, true);

                                //
                                // NOTE: If there was an error during the try block as well,
                                //       keep them somewhat organized in the final error
                                //       information.
                                //
                                if (tryCode == ReturnCode.Error)
                                {
                                    Engine.AddErrorInformation(interpreter, null,
                                                               String.Format("{0}    ... continued ...",
                                                                             Environment.NewLine));
                                }

                                //
                                // NOTE: If the appropriate flag is set, call into the
                                //       Engine.ResetCancel method (with "force" enabled)
                                //       prior to evaluating the finally block script.
                                //       It should be noted here that even though the
                                //       return code of this call is checked by the code,
                                //       it basically cannot fail at this point.
                                //
                                Result canceledResult = null;
                                bool   canceled       = false;
                                bool   unwound        = false;
                                bool   resetCancel    = false;

                                //
                                // NOTE: If the appropriate flag is set, reset the Exit
                                //       property prior to evaluating the finally block
                                //       script.
                                //
                                bool exit      = false;
                                bool resetExit = false;

                                try
                                {
                                    if (ScriptOps.HasFlags(interpreter,
                                                           InterpreterFlags.FinallyResetCancel, true))
                                    {
                                        ReturnCode resetCode;
                                        Result     resetError = null;

                                        resetCode = Engine.ResetCancel(
                                            interpreter, CancelFlags.TryBlock, ref canceledResult,
                                            ref canceled, ref unwound, ref resetCancel,
                                            ref resetError);

                                        if (resetCode != ReturnCode.Ok)
                                        {
                                            DebugOps.Complain(interpreter, resetCode, resetError);
                                        }
                                    }

                                    if (ScriptOps.HasFlags(interpreter,
                                                           InterpreterFlags.FinallyResetExit, true))
                                    {
                                        exit = interpreter.Exit;

                                        if (exit)
                                        {
                                            interpreter.Exit = false;
                                            resetExit        = true;
                                        }
                                    }

                                    ReturnCode timeoutCode;
                                    Result     timeoutResult = null;

                                    timeoutCode = Interpreter.StartFinallyTimeoutThread(
                                        interpreter, false, true, ref timeoutResult);

                                    if (timeoutCode != ReturnCode.Ok)
                                    {
                                        DebugOps.Complain(interpreter, timeoutCode, timeoutResult);
                                    }

                                    try
                                    {
                                        //
                                        // NOTE: Evaluate the finally block.
                                        //
                                        finallyCode = interpreter.EvaluateScript(
                                            arguments[3], ref finallyResult);
                                    }
                                    finally
                                    {
                                        timeoutCode = Interpreter.InterruptFinallyTimeoutThread(
                                            interpreter, false, ref timeoutResult);

                                        if (timeoutCode != ReturnCode.Ok)
                                        {
                                            DebugOps.Complain(interpreter, timeoutCode, timeoutResult);
                                        }
                                    }
                                }
                                finally
                                {
                                    if (exit && resetExit)
                                    {
                                        if (ScriptOps.HasFlags(interpreter,
                                                               InterpreterFlags.FinallyRestoreExit, true))
                                        {
                                            interpreter.Exit = true;
                                        }
                                    }

                                    if ((canceled || unwound) && resetCancel)
                                    {
                                        if (ScriptOps.HasFlags(interpreter,
                                                               InterpreterFlags.FinallyRestoreCancel, true))
                                        {
                                            CancelFlags cancelFlags = CancelFlags.FinallyBlock;

                                            if (unwound)
                                            {
                                                cancelFlags |= CancelFlags.Unwind;
                                            }

                                            ReturnCode cancelCode;
                                            Result     cancelError = null;

                                            cancelCode = Engine.CancelEvaluate(
                                                interpreter, canceledResult, cancelFlags,
                                                ref cancelError);

                                            if (cancelCode != ReturnCode.Ok)
                                            {
                                                DebugOps.Complain(interpreter, cancelCode, cancelError);
                                            }
                                        }
                                    }
                                }

                                if (finallyCode == ReturnCode.Error)
                                {
                                    Engine.AddErrorInformation(interpreter, finallyResult,
                                                               String.Format("{0}    (\"finally\" body line {1})",
                                                                             Environment.NewLine, Interpreter.GetErrorLine(interpreter)));
                                }

                                //
                                // NOTE: Restore normal result reset semantics.
                                //
                                Engine.SetNoResetError(interpreter, false);

                                //
                                // 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.PopScopeCallFramesAndOneMore();
                            }

                            //
                            // NOTE: Initially, the overall command return code and result
                            //       is that of the try block; however, if the finally block
                            //       fails, that will be the return code and result.
                            //
                            if (finallyCode == ReturnCode.Ok)
                            {
                                result = tryResult;
                                code   = tryCode;
                            }
                            else
                            {
                                result = finallyResult;
                                code   = finallyCode;
                            }
                        }
                        else
                        {
                            result = String.Format(
                                "expected \"finally\" but got \"{0}\"",
                                arguments[2]);

                            code = ReturnCode.Error;
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"try script ?finally script?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    return(ReturnCode.Error);
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Example #5
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 >= 4)
                    {
                        StringList list = null;

                        //
                        // WARNING: Cannot cache list representation here, the list
                        //          is modified below.
                        //
                        code = Parser.SplitList(
                            interpreter, arguments[1], 0,
                            Length.Invalid, false, ref list,
                            ref result);

                        if (code == ReturnCode.Ok)
                        {
                            int firstIndex = Index.Invalid;

                            code = Value.GetIndex(
                                arguments[2], list.Count, ValueFlags.AnyIndex,
                                interpreter.CultureInfo, ref firstIndex,
                                ref result);

                            if (code == ReturnCode.Ok)
                            {
                                int lastIndex = Index.Invalid;

                                code = Value.GetIndex(
                                    arguments[3], list.Count, ValueFlags.AnyIndex,
                                    interpreter.CultureInfo, ref lastIndex,
                                    ref result);

                                if (code == ReturnCode.Ok)
                                {
                                    if (firstIndex < 0)
                                    {
                                        firstIndex = 0;
                                    }

                                    if ((firstIndex < list.Count) || (list.Count == 0))
                                    {
                                        if (list.Count > 0)
                                        {
                                            if (lastIndex >= list.Count)
                                            {
                                                lastIndex = list.Count - 1;
                                            }

                                            int numToDelete;

                                            if (firstIndex <= lastIndex)
                                            {
                                                numToDelete = (lastIndex - firstIndex + 1);
                                            }
                                            else
                                            {
                                                numToDelete = 0;
                                            }

                                            list.RemoveRange(firstIndex, numToDelete);

                                            if (arguments.Count >= 5)
                                            {
                                                list.InsertRange(firstIndex, arguments, 4);
                                            }

                                            result = list;
                                        }
                                        else if (ScriptOps.HasFlags(interpreter,
                                                                    InterpreterFlags.ReplaceEmptyListOk, true))
                                        {
                                            result = list;
                                        }
                                        else
                                        {
                                            result = String.Format(
                                                "list doesn't contain element {0}", arguments[2]);

                                            code = ReturnCode.Error;
                                        }
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "list doesn't contain element {0}", arguments[2]);

                                        code = ReturnCode.Error;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        result = "wrong # args: should be \"lreplace list first last ?value ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Example #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 == 5) || (arguments.Count == 6))
                    {
                        ///////////////////////////////////////////////////////////////////////////////////////////////
                        //
                        // test name description ?constraints? body result
                        //
                        ///////////////////////////////////////////////////////////////////////////////////////////////

                        string name = arguments[1];

#if DEBUGGER
                        if (DebuggerOps.CanHitBreakpoints(interpreter,
                                                          EngineFlags.None, BreakpointType.Test))
                        {
                            code = interpreter.CheckBreakpoints(
                                code, BreakpointType.Test, name,
                                null, null, this, null, clientData,
                                arguments, ref result);
                        }

                        if (code == ReturnCode.Ok)
#endif
                        {
                            string description = arguments[2];

                            string          constraints;
                            string          body;
                            IScriptLocation bodyLocation;
                            string          expectedResult;

                            if (arguments.Count == 6)
                            {
                                constraints    = arguments[3];
                                body           = arguments[4];
                                bodyLocation   = arguments[4];
                                expectedResult = arguments[5];
                            }
                            else
                            {
                                constraints    = null;
                                body           = arguments[3];
                                bodyLocation   = arguments[3];
                                expectedResult = arguments[4];
                            }

                            ReturnCodeList returnCodes = new ReturnCodeList(new ReturnCode[] {
                                ReturnCode.Ok, ReturnCode.Return
                            });

                            MatchMode mode = StringOps.DefaultResultMatchMode;

                            bool noCase = false;

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

                            int testLevels = interpreter.EnterTestLevel();

                            try
                            {
                                //
                                // NOTE: Create a place to put all the output of the this command.
                                //
                                StringBuilder testData = StringOps.NewStringBuilder();

                                //
                                // NOTE: Are we going to skip this test?
                                //
                                bool skip = false;
                                bool fail = true;

                                code = TestOps.CheckConstraints(
                                    interpreter, testLevels, name, constraints,
                                    false, false, testData, ref skip, ref fail,
                                    ref result);

                                //
                                // NOTE: Track the fact that we handled this test.
                                //
                                int[] testStatistics = null;

                                if (code == ReturnCode.Ok)
                                {
                                    testStatistics = interpreter.TestStatistics;

                                    if ((testStatistics != null) && (testLevels == 1) && skip)
                                    {
                                        Interlocked.Increment(ref testStatistics[
                                                                  (int)TestInformationType.Total]);
                                    }
                                }

                                if ((code == ReturnCode.Ok) && !skip)
                                {
                                    code = TestOps.RecordInformation(
                                        interpreter, TestInformationType.Counts, name,
                                        null, true, ref result);
                                }

                                //
                                // NOTE: Check test constraints to see if we should run the test.
                                //
                                if ((code == ReturnCode.Ok) && !skip)
                                {
                                    ReturnCode bodyCode   = ReturnCode.Ok;
                                    Result     bodyResult = null;

                                    //
                                    // NOTE: Only run the test body if the setup is successful.
                                    //
                                    if (body != null)
                                    {
                                        TestOps.AppendFormat(
                                            interpreter, testData, TestOutputType.Start,
                                            "---- {0} start", name);

                                        TestOps.AppendLine(
                                            interpreter, testData, TestOutputType.Start);

                                        int savedPreviousLevels = interpreter.BeginNestedExecution();

                                        try
                                        {
                                            ICallFrame frame = interpreter.NewTrackingCallFrame(
                                                StringList.MakeList(this.Name, "body", name),
                                                CallFrameFlags.Test);

                                            interpreter.PushAutomaticCallFrame(frame);

                                            try
                                            {
                                                bodyCode = interpreter.EvaluateScript(
                                                    body, bodyLocation, ref bodyResult);

                                                if ((bodyResult == null) && ScriptOps.HasFlags(
                                                        interpreter, InterpreterFlags.TestNullIsEmpty,
                                                        true))
                                                {
                                                    bodyResult = String.Empty;
                                                }

                                                if (bodyCode == ReturnCode.Error)
                                                {
                                                    /* IGNORED */
                                                    interpreter.CopyErrorInformation(
                                                        VariableFlags.None, ref bodyResult);
                                                }
                                            }
                                            finally
                                            {
                                                //
                                                // 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.PopScopeCallFramesAndOneMore();
                                            }
                                        }
                                        catch (Exception e)
                                        {
                                            bodyResult = e;
                                            bodyCode   = ReturnCode.Error;
                                        }
                                        finally
                                        {
                                            interpreter.EndNestedExecution(savedPreviousLevels);
                                        }
                                    }

                                    //
                                    // NOTE: Did we fail to match the return code?
                                    //
                                    bool codeFailure = !returnCodes.Contains(bodyCode);

                                    //
                                    // NOTE: Does the actual result match the expected result?
                                    //
                                    bool       scriptFailure = false;
                                    ReturnCode scriptCode    = ReturnCode.Ok;
                                    Result     scriptResult  = null;

                                    if (!codeFailure)
                                    {
                                        if (expectedResult != null)
                                        {
                                            scriptCode = TestOps.Match(
                                                interpreter, mode, bodyResult,
                                                expectedResult, noCase, null,
                                                TestOps.RegExOptions, false,
                                                ref scriptFailure, ref scriptResult);

                                            if (scriptCode == ReturnCode.Ok)
                                            {
                                                scriptFailure = !scriptFailure;
                                            }
                                            else
                                            {
                                                scriptFailure = true;
                                            }
                                        }
                                    }

                                    //
                                    // NOTE: If any of the important things failed, the test fails.
                                    //
                                    if (!(codeFailure || scriptFailure))
                                    {
                                        //
                                        // PASS: Test ran with no errors and the results match
                                        //       what we expected.
                                        //
                                        if ((testStatistics != null) && (testLevels == 1))
                                        {
                                            Interlocked.Increment(ref testStatistics[
                                                                      (int)TestInformationType.Passed]);

                                            Interlocked.Increment(ref testStatistics[
                                                                      (int)TestInformationType.Total]);
                                        }

                                        TestOps.AppendFormat(
                                            interpreter, testData, TestOutputType.Pass,
                                            "++++ {0} PASSED", name);

                                        TestOps.AppendLine(
                                            interpreter, testData, TestOutputType.Pass);
                                    }
                                    else
                                    {
                                        //
                                        // FAIL: Test ran with errors or the result does not match
                                        //       what we expected.
                                        //
                                        if ((testStatistics != null) && (testLevels == 1))
                                        {
                                            if (fail)
                                            {
                                                Interlocked.Increment(ref testStatistics[
                                                                          (int)TestInformationType.Failed]);

                                                Interlocked.Increment(ref testStatistics[
                                                                          (int)TestInformationType.Total]);
                                            }
                                        }

                                        //
                                        // NOTE: Keep track of each test that fails.
                                        //
                                        if (testLevels == 1)
                                        {
                                            TestOps.RecordInformation(
                                                interpreter, TestInformationType.FailedNames,
                                                name, null, true);
                                        }

                                        TestOps.AppendLine(
                                            interpreter, testData, TestOutputType.Fail);

                                        TestOps.AppendFormat(
                                            interpreter, testData, TestOutputType.Fail,
                                            "==== {0} {1} {2}", name, description.Trim(),
                                            fail ? "FAILED" : "IGNORED");

                                        TestOps.AppendLine(
                                            interpreter, testData, TestOutputType.Fail);

                                        if (body != null)
                                        {
                                            TestOps.AppendLine(
                                                interpreter, testData, TestOutputType.Body,
                                                "==== Contents of test case:");

                                            TestOps.AppendLine(
                                                interpreter, testData, TestOutputType.Body,
                                                body);
                                        }

                                        if (scriptFailure)
                                        {
                                            if (scriptCode == ReturnCode.Ok)
                                            {
                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    "---- Result was:");

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    bodyResult);

                                                TestOps.AppendFormat(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    "---- Result should have been ({0} matching):",
                                                    mode);

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Reason);

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    expectedResult);
                                            }
                                            else
                                            {
                                                TestOps.Append(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    "---- Error testing result: ");

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Reason,
                                                    scriptResult);

                                                if ((scriptResult != null) &&
                                                    (scriptResult.ErrorInfo != null))
                                                {
                                                    TestOps.Append(
                                                        interpreter, testData, TestOutputType.Error,
                                                        "---- errorInfo(matchResult): ");

                                                    TestOps.AppendLine(
                                                        interpreter, testData, TestOutputType.Error,
                                                        scriptResult.ErrorInfo);

                                                    TestOps.Append(
                                                        interpreter, testData, TestOutputType.Error,
                                                        "---- errorCode(matchResult): ");

                                                    TestOps.AppendLine(
                                                        interpreter, testData, TestOutputType.Error,
                                                        scriptResult.ErrorCode);
                                                }
                                            }
                                        }

                                        if (codeFailure)
                                        {
                                            ReturnCodeDictionary returnCodeMessages =
                                                interpreter.TestReturnCodeMessages;

                                            string codeMessage;

                                            if ((returnCodeMessages == null) ||
                                                (!returnCodeMessages.TryGetValue(
                                                     bodyCode, out codeMessage) &&
                                                 !returnCodeMessages.TryGetValue(
                                                     ReturnCode.Invalid, out codeMessage)))
                                            {
                                                codeMessage = "Unknown";
                                            }

                                            TestOps.AppendFormat(
                                                interpreter, testData, TestOutputType.Reason,
                                                "---- {0}; Return code was: {1}",
                                                codeMessage, bodyCode);

                                            TestOps.AppendLine(
                                                interpreter, testData, TestOutputType.Reason);

                                            TestOps.Append(
                                                interpreter, testData, TestOutputType.Reason,
                                                "---- Return code should have been one of: ");

                                            TestOps.AppendLine(
                                                interpreter, testData, TestOutputType.Reason,
                                                returnCodes.ToString());

                                            if ((bodyResult != null) &&
                                                (bodyResult.ErrorInfo != null) &&
                                                !returnCodes.Contains(ReturnCode.Error))
                                            {
                                                TestOps.Append(
                                                    interpreter, testData, TestOutputType.Error,
                                                    "---- errorInfo(body): ");

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Error,
                                                    bodyResult.ErrorInfo);

                                                TestOps.Append(
                                                    interpreter, testData, TestOutputType.Error,
                                                    "---- errorCode(body): ");

                                                TestOps.AppendLine(
                                                    interpreter, testData, TestOutputType.Error,
                                                    bodyResult.ErrorCode);
                                            }
                                        }

                                        TestOps.AppendFormat(
                                            interpreter, testData, TestOutputType.Fail,
                                            "==== {0} {1}", name, fail ? "FAILED" : "IGNORED");

                                        TestOps.AppendLine(
                                            interpreter, testData, TestOutputType.Fail);
                                    }
                                }

                                //
                                // NOTE: Did the above code succeed?
                                //
                                if (code == ReturnCode.Ok)
                                {
                                    //
                                    // NOTE: The result is the complete output produced by the
                                    //       entire test.
                                    //
                                    if (testData != null)
                                    {
                                        result = testData;
                                    }
                                    else
                                    {
                                        result = String.Empty;
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Engine.SetExceptionErrorCode(interpreter, e);

                                result = e;
                                code   = ReturnCode.Error;
                            }
                            finally
                            {
                                interpreter.ExitTestLevel();
                            }
                        }
                    }
                    else
                    {
                        result = String.Format(
                            "wrong # args: should be \"{0} name description constraints body result\"",
                            this.Name);

                        code = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }
Example #7
0
        ///////////////////////////////////////////////////////////////////////

        #region IExecute Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return(ReturnCode.Error);
            }

            if (arguments == null)
            {
                result = "invalid argument list";
                return(ReturnCode.Error);
            }

            if ((arguments.Count < 2) || (arguments.Count > 4))
            {
                result = ScriptOps.WrongNumberOfArguments(this, 1,
                                                          arguments, "script ?resultVarName? ?optionsVarName?");

                return(ReturnCode.Error);
            }

            string name = StringList.MakeList(this.Name);

            ICallFrame frame = interpreter.NewTrackingCallFrame(name,
                                                                CallFrameFlags.Catch);

            interpreter.PushAutomaticCallFrame(frame);

            EngineFlags engineFlags = interpreter.EngineFlags;

            if (Engine.HasNoResetError(engineFlags))
            {
                engineFlags |= EngineFlags.ErrorAlreadyLogged;
            }

            ReturnCode code;
            Result     localResult = null;
            int        errorLine   = 0;

            /* IGNORED */
            interpreter.EnterCatchLevel();

            try
            {
                code = interpreter.EvaluateScript(
                    arguments[1], engineFlags, ref localResult,
                    ref errorLine);
            }
            finally
            {
                if (interpreter.ExitCatchLevel() == 0)
                {
                    if (ScriptOps.HasFlags(interpreter,
                                           InterpreterFlags.CatchResetCancel, true))
                    {
                        ReturnCode resetCode;
                        Result     resetError = null;

                        resetCode = Engine.ResetCancel(
                            interpreter, CancelFlags.CatchBlock,
                            ref resetError);

                        if (resetCode != ReturnCode.Ok)
                        {
                            DebugOps.Complain(
                                interpreter, resetCode, resetError);
                        }
                    }

                    if (ScriptOps.HasFlags(interpreter,
                                           InterpreterFlags.CatchResetExit, true))
                    {
                        bool exit = interpreter.Exit;

                        if (exit)
                        {
                            interpreter.Exit = false;
                        }
                    }
                }
            }

            //
            // BUGFIX: Prevent messing up the custom errorInfo from the [error]
            //         command by checking to see if the "error already logged"
            //         flag has been set.
            //
            engineFlags = interpreter.EngineFlags;

            if ((code == ReturnCode.Error) &&
                !Engine.HasErrorAlreadyLogged(engineFlags) &&
                !Engine.HasNoResetError(engineFlags))
            {
                Engine.AddErrorInformation(interpreter, localResult,
                                           String.Format("{0}    (\"catch\" body line {1})",
                                                         Environment.NewLine, errorLine));
            }

            //
            // 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.PopScopeCallFramesAndOneMore();

            //
            // NOTE: The result of this command is the integer conversion of
            //       the return code received from the evaluated script.
            //
            Engine.ResetResult(interpreter, ref result);
            result            = ConversionOps.ToInt(code);
            result.ReturnCode = code; /* NOTE: For ease of use. */

            //
            // NOTE: See if the caller wants to save the result and/or error
            //       message in a variable.
            //
            if (arguments.Count >= 3)
            {
                Result error = null;

                code = interpreter.SetVariableValue(
                    VariableFlags.NoReady, arguments[2], localResult, null,
                    ref error);

                if (code != ReturnCode.Ok)
                {
                    Engine.ResetResult(interpreter, ref result);

                    result = String.Format(
                        "couldn't save command result in variable: {0}",
                        error);

                    return(code);
                }
            }

            //
            // NOTE: See if the caller wants to save the "return options" in a
            //       variable.
            //
            if (arguments.Count >= 4)
            {
                StringList list  = new StringList();
                Result     error = null;

                if (result.ReturnCode == ReturnCode.Return)
                {
                    int level = 0;

                    code = interpreter.GetInfoLevel(
                        null, ref level, ref error);

                    if (code != ReturnCode.Ok)
                    {
                        Engine.ResetResult(interpreter, ref error);

                        result = String.Format(
                            "couldn't get current level: {0}", error);

                        return(code);
                    }

                    list.Add("-code",
                             ((int)interpreter.ReturnCode).ToString());

                    list.Add("-level", level.ToString());
                }
                else
                {
                    list.Add("-code", result.String);
                    list.Add("-level", Value.ZeroString);
                }

                if (result.ReturnCode == ReturnCode.Error)
                {
                    Result     errorCode = null;
                    Result     errorInfo = null;
                    ResultList errors    = null;

                    code = interpreter.CopyErrorInformation(
                        VariableFlags.None, true, ref errorCode, ref errorInfo,
                        ref errors);

                    if (code != ReturnCode.Ok)
                    {
                        Engine.ResetResult(interpreter, ref result);

                        result = errors;
                        return(code);
                    }

                    list.Add("-errorcode", errorCode);
                    list.Add("-errorinfo", errorInfo);
                    list.Add("-errorline", errorLine.ToString());
                }

                code = interpreter.SetVariableValue(
                    VariableFlags.NoReady, arguments[3], list.ToString(), null,
                    ref error);

                if (code != ReturnCode.Ok)
                {
                    Engine.ResetResult(interpreter, ref result);

                    result = String.Format(
                        "couldn't save return options in variable: {0}",
                        error);

                    return(code);
                }
            }

            //
            // NOTE: We are "catching" (masking) the error; therefore, do not
            //       propogate it.
            //
            return(ReturnCode.Ok);
        }