Example #1
0
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code = ReturnCode.Ok;

            if (interpreter != null)
            {
                if (arguments != null)
                {
                    OptionDictionary options = new OptionDictionary(
                        new IOption[] {
                        new Option(null, OptionFlags.None, 1, Index.Invalid, "-exact", null),
                        new Option(null, OptionFlags.None, 3, Index.Invalid, "-integer", null),
                        new Option(null, OptionFlags.None, 3, Index.Invalid, "-substring", null),
                        new Option(null, OptionFlags.None, 1, Index.Invalid, "-glob", null),
                        new Option(null, OptionFlags.None, 1, Index.Invalid, "-regexp", null),
                        new Option(null, OptionFlags.None, 2, Index.Invalid, "-subst", null),
                        new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-nocase", null),
                        new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, Option.EndOfOptions, null)
                    });

                    int argumentIndex = Index.Invalid;

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

                    if (code == ReturnCode.Ok)
                    {
                        if ((argumentIndex != Index.Invalid) && ((argumentIndex + 1) < arguments.Count))
                        {
                            MatchMode mode = StringOps.DefaultSwitchMatchMode;

                            if (options.IsPresent("-integer"))
                            {
                                mode = MatchMode.Integer;
                            }
                            else if (options.IsPresent("-regexp"))
                            {
                                mode = MatchMode.RegExp;
                            }
                            else if (options.IsPresent("-glob"))
                            {
                                mode = MatchMode.Glob;
                            }
                            else if (options.IsPresent("-substring"))
                            {
                                mode = MatchMode.SubString;
                            }
                            else if (options.IsPresent("-exact"))
                            {
                                mode = MatchMode.Exact;
                            }

                            if (options.IsPresent("-subst"))
                            {
                                mode |= MatchMode.Substitute;
                            }

                            bool noCase = false;

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

                            bool            splitList = false;
                            StringList      list      = null;
                            IScriptLocation location  = null;

                            //
                            // NOTE: Is there only one argument following the string to match?
                            //
                            if ((argumentIndex + 2) == arguments.Count)
                            {
                                code = Parser.SplitList(
                                    interpreter, arguments[argumentIndex + 1], 0,
                                    Length.Invalid, true, ref list);

                                if (code == ReturnCode.Ok)
                                {
                                    if (list.Count > 0)
                                    {
                                        location  = arguments[argumentIndex + 1];
                                        splitList = true;
                                    }
                                    else
                                    {
                                        result = "wrong # args: should be \"switch ?switches? string {pattern body ... ?default body?}\"";
                                        code   = ReturnCode.Error;
                                    }
                                }
                            }
                            else
                            {
                                //
                                // TODO: Make sure this is always accurate.
                                //
                                code = ScriptOps.GetLocation(
                                    interpreter, arguments, argumentIndex + 1, ref location,
                                    ref result);

                                if (code == ReturnCode.Ok)
                                {
                                    list = ArgumentList.GetRangeAsStringList(arguments, argumentIndex + 1);
                                }
                            }

                            //
                            // NOTE: Ok, now we should have a list of patterns and bodies
                            //       if everything went Ok above.
                            //
                            if (code == ReturnCode.Ok)
                            {
                                //
                                // NOTE: Complain if there is an odd number of words in the
                                //       list of patterns and bodies.
                                //
                                if ((list.Count % 2) == 0)
                                {
                                    //
                                    // NOTE: Complain if the last body is a continuation.
                                    //
                                    if (String.Compare(list[list.Count - 1], Characters.MinusSign.ToString(),
                                                       StringOps.SystemStringComparisonType) != 0)
                                    {
                                        //
                                        // NOTE: Get the text to match against.
                                        //
                                        string input = arguments[argumentIndex];

                                        //
                                        // NOTE: We need to return an empty string if we do not
                                        //       match anything.
                                        //
                                        result = String.Empty;

                                        //
                                        // NOTE: Search the patterns for a match.
                                        //
                                        for (int index = 0; index < list.Count; index += 2)
                                        {
                                            Result pattern = list[index];

                                            bool match = false;

                                            if ((index == (list.Count - 2)) &&
                                                (String.Compare(pattern, Switch.Default, StringOps.SystemStringComparisonType) == 0))
                                            {
                                                //
                                                // NOTE: Default pattern at end always matches.
                                                //
                                                match = true;
                                            }
                                            else
                                            {
                                                if ((mode & MatchMode.Substitute) == MatchMode.Substitute)
                                                {
                                                    code = interpreter.SubstituteString(pattern, ref pattern);
                                                }

                                                if (code != ReturnCode.Ok)
                                                {
                                                    result = pattern;
                                                    break;
                                                }

                                                code = StringOps.Match(
                                                    interpreter, mode, input, pattern, noCase, ref match,
                                                    ref result);

                                                if (code != ReturnCode.Ok)
                                                {
                                                    break;
                                                }
                                            }

                                            if (!match)
                                            {
                                                continue;
                                            }

                                            //
                                            // NOTE: We've got a match. Find a body to execute, skipping
                                            //       bodies that are "-".
                                            //
                                            for (int index2 = index + 1; ; index2 += 2)
                                            {
                                                if (index2 >= list.Count)
                                                {
                                                    result = "fall-out when searching for body to match pattern";
                                                    code   = ReturnCode.Error;

                                                    goto switch_done;
                                                }

                                                if (String.Compare(list[index2], Characters.MinusSign.ToString(),
                                                                   StringOps.SystemStringComparisonType) != 0)
                                                {
                                                    code = interpreter.EvaluateScript(list[index2], location, ref result);

                                                    if (code == ReturnCode.Error)
                                                    {
                                                        Engine.AddErrorInformation(interpreter, result,
                                                                                   String.Format("{0}    (\"{1}\" arm line {2})",
                                                                                                 Environment.NewLine, FormatOps.Ellipsis(pattern),
                                                                                                 Interpreter.GetErrorLine(interpreter)));
                                                    }

                                                    goto switch_done;
                                                }
                                            }
                                        }

switch_done:
                                        ;
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "no body specified for pattern \"{0}\"",
                                            list[list.Count - 2]);

                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "extra switch pattern with no body";
                                    code   = ReturnCode.Error;

                                    if (splitList)
                                    {
                                        /*
                                         * Check if this can be due to a badly placed comment
                                         * in the switch block.
                                         *
                                         * The following is an heuristic to detect the infamous
                                         * "comment in switch" error: just check if a pattern
                                         * begins with '#'.
                                         */

                                        for (int index = 0; index < list.Count; index++)
                                        {
                                            if (!String.IsNullOrEmpty(list[index]) &&
                                                (list[index][0] == Characters.NumberSign))
                                            {
                                                result += ", this may be due to a comment incorrectly placed " +
                                                          "outside of a switch body - see the \"switch\" documentation";

                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            if ((argumentIndex != Index.Invalid) &&
                                Option.LooksLikeOption(arguments[argumentIndex]))
                            {
                                result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                            }
                            else
                            {
                                result = "wrong # args: should be \"switch ?switches? string pattern body ... ?default body?\"";
                            }

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

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

        #region IExecute Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            //
            // NOTE: *WARNING* We do NOT actually support namespaces.  This
            //       command exists for the sole purpose of improving source
            //       code compatibility with simple stand alone scripts that
            //       may simply wrap themselves in a "namespace eval" block,
            //       etc.  Any other (more involved) use may not work at all
            //       or may cause undesired and/or unpredictable results.
            //
            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 "children":
                            {
                                if ((arguments.Count >= 2) && (arguments.Count <= 4))
                                {
                                    string name = null;

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

                                    string pattern = null;

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

                                    IEnumerable <INamespace> children = NamespaceOps.Children(
                                        interpreter, name, pattern, false, ref result);

                                    if (children != null)
                                    {
                                        StringList list = new StringList();

                                        foreach (INamespace child in children)
                                        {
                                            list.Add(child.QualifiedName);
                                        }

                                        result = list;
                                    }
                                    else
                                    {
                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace children ?name? ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "code":
                            {
                                if (arguments.Count == 3)
                                {
                                    string text = arguments[2];

                                    if (!NamespaceOps.IsSubCommand(interpreter, text, "inscope"))
                                    {
                                        INamespace currentNamespace = null;

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

                                        if (code == ReturnCode.Ok)
                                        {
                                            StringList list = new StringList();

                                            list.Add(NamespaceOps.MakeAbsoluteName(
                                                         this.Name));

                                            list.Add("inscope");

                                            list.Add(NamespaceOps.MakeAbsoluteName(
                                                         currentNamespace.QualifiedName));

                                            list.Add(text);

                                            result = list;
                                        }
                                    }
                                    else
                                    {
                                        result = text;         /* COMPAT: Tcl. */
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace code script\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "current":
                            {
                                if (arguments.Count == 2)
                                {
                                    INamespace currentNamespace = null;

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

                                    if (code == ReturnCode.Ok)
                                    {
                                        if (currentNamespace != null)
                                        {
                                            result = currentNamespace.QualifiedName;
                                        }
                                        else
                                        {
                                            result = "current namespace is invalid";
                                            code   = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace current\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "delete":
                            {
                                if (arguments.Count >= 2)
                                {
                                    for (int index = 2; index < arguments.Count; index++)
                                    {
                                        code = interpreter.DeleteNamespace(
                                            VariableFlags.None, arguments[index], false,
                                            ref result);

                                        if (code != ReturnCode.Ok)
                                        {
                                            break;
                                        }
                                    }

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

                            case "enable":
                            {
                                if ((arguments.Count >= 2) && (arguments.Count <= 4))
                                {
                                    if (arguments.Count >= 3)
                                    {
                                        bool enabled = false;

                                        code = Value.GetBoolean2(
                                            arguments[2], ValueFlags.AnyBoolean,
                                            interpreter.CultureInfo, ref enabled, ref result);

                                        bool force = false;

                                        if ((code == ReturnCode.Ok) && (arguments.Count >= 4))
                                        {
                                            code = Value.GetBoolean2(
                                                arguments[3], ValueFlags.AnyBoolean,
                                                interpreter.CultureInfo, ref force, ref result);
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            code = NamespaceOps.Enable(
                                                interpreter, enabled, force, ref result);
                                        }
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = interpreter.AreNamespacesEnabled();
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace enable ?enabled? ?force?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "eval":
                            {
                                if (arguments.Count >= 4)
                                {
                                    string namespaceName = NamespaceOps.MapName(
                                        interpreter, arguments[2]);

                                    INamespace @namespace = NamespaceOps.Lookup(
                                        interpreter, namespaceName, false, true,
                                        ref result);

                                    if (@namespace != null)
                                    {
                                        string name = StringList.MakeList("namespace eval", @namespace.QualifiedName);

                                        ICallFrame frame = interpreter.NewNamespaceCallFrame(
                                            name, CallFrameFlags.Evaluate | CallFrameFlags.UseNamespace,
                                            arguments, @namespace, false);

                                        interpreter.PushNamespaceCallFrame(frame);

                                        if (arguments.Count == 4)
                                        {
                                            code = interpreter.EvaluateScript(arguments[3], ref result);
                                        }
                                        else
                                        {
                                            code = interpreter.EvaluateScript(arguments, 3, ref result);
                                        }

                                        if (code == ReturnCode.Error)
                                        {
                                            Engine.AddErrorInformation(interpreter, result,
                                                                       String.Format("{0}    (in namespace eval \"{1}\" script line {2})",
                                                                                     Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace,
                                                                                                                                          true), Interpreter.GetErrorLine(interpreter)));
                                        }

                                        /* IGNORED */
                                        interpreter.PopNamespaceCallFrame(frame);

                                        /* NO RESULT */
                                        Engine.CleanupNamespacesOrComplain(interpreter);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace eval name arg ?arg ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "exists":
                            {
                                if (arguments.Count == 3)
                                {
                                    result = ConversionOps.ToInt(NamespaceOps.Lookup(
                                                                     interpreter, arguments[2], false, false) != null);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace exists name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "export":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-clear", 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, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        bool clear = false;

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

                                        StringList patterns = new StringList();

                                        if (argumentIndex != Index.Invalid)
                                        {
                                            patterns.AddObjects(ArgumentList.GetRange(arguments, argumentIndex));
                                        }

                                        code = NamespaceOps.Export(interpreter, null, patterns, clear, ref result);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace export ?-clear? ?pattern pattern ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "forget":
                            {
                                if (arguments.Count >= 2)
                                {
                                    if (arguments.Count >= 3)
                                    {
                                        code = NamespaceOps.Forget(interpreter,
                                                                   new StringList(ArgumentList.GetRange(arguments, 2)),
                                                                   ref result);

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

                            case "import":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-force", 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, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        bool force = false;

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

                                        StringList patterns = new StringList();

                                        if (argumentIndex != Index.Invalid)
                                        {
                                            patterns.AddObjects(ArgumentList.GetRange(arguments, argumentIndex));
                                        }

                                        code = NamespaceOps.Import(interpreter, patterns, force, ref result);
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace import ?-force? ?pattern pattern ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

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

                            case "inscope":
                            {
                                if (arguments.Count >= 4)
                                {
                                    string namespaceName = NamespaceOps.MapName(
                                        interpreter, arguments[2]);

                                    INamespace @namespace = NamespaceOps.Lookup(
                                        interpreter, namespaceName, false, false,
                                        ref result);

                                    if (@namespace != null)
                                    {
                                        if (arguments.Count > 4)
                                        {
                                            IScriptLocation location = null;

#if DEBUGGER && BREAKPOINTS
                                            code = ScriptOps.GetLocation(
                                                interpreter, arguments, 3, ref location,
                                                ref result);

                                            if (code == ReturnCode.Ok)
#endif
                                            {
                                                string name = StringList.MakeList("namespace inscope", @namespace.QualifiedName);

                                                ICallFrame frame = interpreter.NewNamespaceCallFrame(
                                                    name, CallFrameFlags.InScope | CallFrameFlags.UseNamespace,
                                                    arguments, @namespace, false);

                                                interpreter.PushNamespaceCallFrame(frame);

                                                StringList list = new StringList(arguments, 4);

                                                code = interpreter.EvaluateScript(
                                                    ListOps.Concat(arguments[3], list.ToString()),
                                                    location, ref result);

                                                if (code == ReturnCode.Error)
                                                {
                                                    Engine.AddErrorInformation(interpreter, result,
                                                                               String.Format("{0}    (in namespace inscope \"{1}\" script line {2})",
                                                                                             Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace,
                                                                                                                                                  true), Interpreter.GetErrorLine(interpreter)));
                                                }

                                                /* IGNORED */
                                                interpreter.PopNamespaceCallFrame(frame);

                                                /* NO RESULT */
                                                Engine.CleanupNamespacesOrComplain(interpreter);
                                            }
                                        }
                                        else
                                        {
                                            string name = StringList.MakeList("namespace inscope", @namespace.QualifiedName);

                                            ICallFrame frame = interpreter.NewNamespaceCallFrame(
                                                name, CallFrameFlags.InScope | CallFrameFlags.UseNamespace,
                                                arguments, @namespace, false);

                                            interpreter.PushNamespaceCallFrame(frame);

                                            code = interpreter.EvaluateScript(arguments[3], ref result);

                                            if (code == ReturnCode.Error)
                                            {
                                                Engine.AddErrorInformation(interpreter, result,
                                                                           String.Format("{0}    (in namespace inscope \"{1}\" script line {2})",
                                                                                         Environment.NewLine, NamespaceOps.MaybeQualifiedName(@namespace,
                                                                                                                                              true), Interpreter.GetErrorLine(interpreter)));
                                            }

                                            /* IGNORED */
                                            interpreter.PopNamespaceCallFrame(frame);

                                            /* NO RESULT */
                                            Engine.CleanupNamespacesOrComplain(interpreter);
                                        }
                                    }
                                    else
                                    {
                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace inscope name arg ?arg...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "mappings":
                            {
                                if (arguments.Count == 2)
                                {
                                    lock (interpreter.SyncRoot)         /* TRANSACTIONAL */
                                    {
                                        StringDictionary namespaceMappings = interpreter.NamespaceMappings;

                                        if (namespaceMappings != null)
                                        {
                                            result = namespaceMappings.KeysAndValuesToString(null, false);
                                            code   = ReturnCode.Ok;
                                        }
                                        else
                                        {
                                            result = "namespace mappings not available";
                                            code   = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace mappings\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "name":
                            {
                                if (arguments.Count == 3)
                                {
                                    string name = arguments[2];

                                    if (!NamespaceOps.IsQualifiedName(name))
                                    {
                                        result = NamespaceOps.MakeQualifiedName(interpreter, name, true);
                                        code   = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        result = "only non-qualified names are allowed";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace name name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "origin":
                            {
                                if (arguments.Count == 3)
                                {
                                    code = NamespaceOps.Origin(interpreter, null, arguments[2], ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace origin name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "parent":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    code = NamespaceOps.Parent(
                                        interpreter, (arguments.Count == 3) ? arguments[2] : null,
                                        ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace parent ?name?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "qualifiers":
                            {
                                if (arguments.Count == 3)
                                {
                                    string qualifiers = null;
                                    string tail       = null;

                                    code = NamespaceOps.SplitName(
                                        arguments[2], ref qualifiers, ref tail, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = qualifiers;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace qualifiers string\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "rename":
                            {
                                if (arguments.Count == 4)
                                {
                                    code = interpreter.RenameNamespace(
                                        arguments[2], arguments[3], RenameGlobalOk,
                                        RenameInUseOk, ref result);
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace rename oldName newName\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "tail":
                            {
                                if (arguments.Count == 3)
                                {
                                    string qualifiers = null;
                                    string tail       = null;

                                    code = NamespaceOps.SplitName(
                                        arguments[2], ref qualifiers, ref tail, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = tail;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace tail string\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "unknown":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    INamespace currentNamespace = null;

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

                                    if (code == ReturnCode.Ok)
                                    {
                                        if (currentNamespace != null)
                                        {
                                            if (arguments.Count == 3)
                                            {
                                                string unknown = StringOps.NullIfEmpty(arguments[2]);

                                                if (String.IsNullOrEmpty(unknown) &&
                                                    NamespaceOps.IsGlobal(interpreter, currentNamespace))
                                                {
                                                    currentNamespace.Unknown = interpreter.GlobalUnknown;
                                                }
                                                else
                                                {
                                                    currentNamespace.Unknown = unknown;
                                                }

                                                result = unknown;
                                            }
                                            else
                                            {
                                                result = currentNamespace.Unknown;
                                            }
                                        }
                                        else
                                        {
                                            if (arguments.Count == 3)
                                            {
                                                string unknown = StringOps.NullIfEmpty(arguments[2]);

                                                if (String.IsNullOrEmpty(unknown))
                                                {
                                                    interpreter.GlobalUnknown = TclVars.Unknown;
                                                }
                                                else
                                                {
                                                    interpreter.GlobalUnknown = unknown;
                                                }

                                                result = unknown;
                                            }
                                            else
                                            {
                                                result = interpreter.GlobalUnknown;
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace unknown ?script?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "which":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-command", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-variable", 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, OptionBehaviorFlags.LastIsNonOption, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        if ((argumentIndex != Index.Invalid) &&
                                            ((argumentIndex + 1) == arguments.Count))
                                        {
                                            string name = arguments[argumentIndex];

                                            bool isCommand = false;

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

                                            bool isVariable = false;

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

                                            if (!isCommand || !isVariable)
                                            {
                                                NamespaceFlags flags = NamespaceFlags.None;

                                                if (isCommand)
                                                {
                                                    flags |= NamespaceFlags.Command;
                                                }
                                                else if (isVariable)
                                                {
                                                    flags |= NamespaceFlags.Variable;
                                                }
                                                else
                                                {
                                                    flags |= NamespaceFlags.Command;
                                                }

                                                code = NamespaceOps.Which(interpreter, null, name, flags, ref result);
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";
                                                code   = ReturnCode.Error;
                                            }
                                        }
                                        else
                                        {
                                            if ((argumentIndex != Index.Invalid) &&
                                                Option.LooksLikeOption(arguments[argumentIndex]))
                                            {
                                                result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";
                                            }

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";
                                    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 \"namespace subcommand ?arg ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

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

        #region IExecute Members
        public override ReturnCode Execute(
            Interpreter interpreter,
            IClientData clientData,
            ArgumentList arguments,
            ref Result result
            )
        {
            ReturnCode code;

            //
            // NOTE: *WARNING* We do NOT actually support namespaces.  This
            //       command exists for the sole purpose of improving source
            //       code compatibility with simple stand alone scripts that
            //       may simply wrap themselves in a "namespace eval" block,
            //       etc.  Any other (more involved) use may not work at all
            //       or may cause undesired and/or unpredictable results.
            //
            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 "children":
                            {
                                if ((arguments.Count >= 2) && (arguments.Count <= 4))
                                {
                                    string name = null;

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

                                    if ((arguments.Count < 3) ||
                                        NamespaceOps.IsGlobalName(name))
                                    {
                                        result = String.Empty;
                                        code   = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        if (NamespaceOps.IsAbsoluteName(name))
                                        {
                                            result = String.Format("namespace \"{0}\" not found", name);
                                        }
                                        else
                                        {
                                            result = String.Format("namespace \"{0}\" not found in \"{1}\"",
                                                                   name, TclVars.GlobalNamespace);
                                        }

                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace children ?name? ?pattern?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "code":
                            {
                                if (arguments.Count == 3)
                                {
                                    //
                                    // NOTE: We are always in the global namespace, fake it.
                                    //
                                    result = new StringList(
                                        TclVars.GlobalNamespace + this.Name, "inscope",
                                        TclVars.GlobalNamespace, arguments[2]);

                                    code = ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace code script\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "current":
                            {
                                if (arguments.Count == 2)
                                {
                                    result = TclVars.GlobalNamespace;
                                    code   = ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace current\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "delete":
                            {
                                if (arguments.Count >= 2)
                                {
                                    code = ReturnCode.Ok;

                                    for (int index = 2; index < arguments.Count; index++)
                                    {
                                        if (!NamespaceOps.IsGlobalName(arguments[index]))
                                        {
                                            //
                                            // NOTE: We only know about the global namespace; an attempt
                                            //       to delete any other namespace is an error.
                                            //
                                            result = String.Format(
                                                "unknown namespace \"{0}\" in namespace delete command",
                                                arguments[index]);

                                            code = ReturnCode.Error;
                                            break;
                                        }
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        for (int index = 2; index < arguments.Count; /* index++ */)
                                        {
                                            //
                                            // NOTE: Delete the one-and-only namespace (global) now (actually,
                                            //       as soon as the evaluation stack unwinds).
                                            //
                                            code = interpreter.DeleteNamespace(
                                                VariableFlags.None, arguments[index], false, ref result);

                                            //
                                            // NOTE: Since we only know about the global namespace there
                                            //       is no point in attempting to delete it multiple times.
                                            //
                                            break;
                                        }
                                    }

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

                            case "enable":
                            {
                                if ((arguments.Count >= 2) && (arguments.Count <= 4))
                                {
                                    if (arguments.Count >= 3)
                                    {
                                        bool enabled = false;

                                        code = Value.GetBoolean2(
                                            arguments[2], ValueFlags.AnyBoolean,
                                            interpreter.CultureInfo, ref enabled, ref result);

                                        bool force = false;

                                        if ((code == ReturnCode.Ok) && (arguments.Count >= 4))
                                        {
                                            code = Value.GetBoolean2(
                                                arguments[3], ValueFlags.AnyBoolean,
                                                interpreter.CultureInfo, ref force, ref result);
                                        }

                                        if (code == ReturnCode.Ok)
                                        {
                                            code = NamespaceOps.Enable(
                                                interpreter, enabled, force, ref result);
                                        }
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = interpreter.AreNamespacesEnabled();
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace enable ?enabled? ?force?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "eval":
                            {
                                if (arguments.Count >= 4)
                                {
                                    string name = StringList.MakeList("namespace eval", arguments[2]);

                                    ICallFrame frame = interpreter.NewTrackingCallFrame(name,
                                                                                        CallFrameFlags.Namespace | CallFrameFlags.Evaluate);

                                    interpreter.PushAutomaticCallFrame(frame);

                                    if (arguments.Count == 4)
                                    {
                                        code = interpreter.EvaluateScript(arguments[3], ref result);
                                    }
                                    else
                                    {
                                        code = interpreter.EvaluateScript(arguments, 3, ref result);
                                    }

                                    if (code == ReturnCode.Error)
                                    {
                                        Engine.AddErrorInformation(interpreter, result,
                                                                   String.Format("{0}    (in namespace eval \"{1}\" script line {2})",
                                                                                 Environment.NewLine, arguments[2], 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();
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace eval name arg ?arg ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "exists":
                            {
                                if (arguments.Count == 3)
                                {
                                    if (NamespaceOps.IsGlobalName(arguments[2]))
                                    {
                                        result = true;
                                    }
                                    else
                                    {
                                        result = false;
                                    }

                                    code = ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace exists name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "export":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-clear", 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, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    //
                                    // NOTE: We do not support importing or exporting of namespace commands
                                    //       because we do not really support namespaces; therefore, we do
                                    //       nothing.
                                    //
                                    if (code == ReturnCode.Ok)
                                    {
                                        result = String.Empty;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace export ?-clear? ?pattern pattern ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "forget":
                            {
                                if (arguments.Count >= 2)
                                {
                                    //
                                    // NOTE: We do not support importing or exporting of namespace commands
                                    //       because we do not really support namespaces; therefore, we do
                                    //       nothing.
                                    //
                                    result = String.Empty;
                                    code   = ReturnCode.Ok;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace forget ?pattern pattern ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "import":
                            {
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-force", 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, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    //
                                    // NOTE: We do not support importing or exporting of namespace commands
                                    //       because we do not really support namespaces; therefore, we do
                                    //       nothing.
                                    //
                                    if (code == ReturnCode.Ok)
                                    {
                                        result = String.Empty;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace import ?-force? ?pattern pattern ...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

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

                            case "inscope":
                            {
                                if (arguments.Count >= 4)
                                {
                                    if (NamespaceOps.IsGlobalName(arguments[2]))
                                    {
                                        if (arguments.Count > 4)
                                        {
                                            IScriptLocation location = null;

#if DEBUGGER && BREAKPOINTS
                                            code = ScriptOps.GetLocation(
                                                interpreter, arguments, 3, ref location,
                                                ref result);

                                            if (code == ReturnCode.Ok)
#endif
                                            {
                                                string name = StringList.MakeList("namespace inscope", arguments[2]);

                                                ICallFrame frame = interpreter.NewTrackingCallFrame(name,
                                                                                                    CallFrameFlags.Namespace | CallFrameFlags.InScope);

                                                interpreter.PushAutomaticCallFrame(frame);

                                                StringList list = new StringList(arguments, 4);

                                                code = interpreter.EvaluateScript(
                                                    ListOps.Concat(arguments[3], list.ToString()),
                                                    location, ref result);

                                                if (code == ReturnCode.Error)
                                                {
                                                    Engine.AddErrorInformation(interpreter, result,
                                                                               String.Format("{0}    (in namespace inscope \"{1}\" script line {2})",
                                                                                             Environment.NewLine, arguments[2], 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();
                                            }
                                        }
                                        else
                                        {
                                            string name = StringList.MakeList("namespace inscope", arguments[2]);

                                            ICallFrame frame = interpreter.NewTrackingCallFrame(name,
                                                                                                CallFrameFlags.Namespace | CallFrameFlags.InScope);

                                            interpreter.PushAutomaticCallFrame(frame);

                                            code = interpreter.EvaluateScript(arguments[3], ref result);

                                            if (code == ReturnCode.Error)
                                            {
                                                Engine.AddErrorInformation(interpreter, result,
                                                                           String.Format("{0}    (in namespace inscope \"{1}\" script line {2})",
                                                                                         Environment.NewLine, arguments[2], 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();
                                        }
                                    }
                                    else
                                    {
                                        result = String.Format(
                                            "unknown namespace \"{0}\" in inscope namespace command",
                                            arguments[2]);

                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace inscope name arg ?arg...?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "mappings":
                            {
                                if (arguments.Count == 2)
                                {
                                    lock (interpreter.SyncRoot)         /* TRANSACTIONAL */
                                    {
                                        StringDictionary namespaceMappings = interpreter.NamespaceMappings;

                                        if (namespaceMappings != null)
                                        {
                                            result = namespaceMappings.KeysAndValuesToString(null, false);
                                            code   = ReturnCode.Ok;
                                        }
                                        else
                                        {
                                            result = "namespace mappings not available";
                                            code   = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace mappings\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "name":
                            {
                                if (arguments.Count == 3)
                                {
                                    //
                                    // NOTE: We are always in the global namespace, fake it.
                                    //
                                    string name = arguments[2];

                                    if (!NamespaceOps.IsQualifiedName(name))
                                    {
                                        result = NamespaceOps.MakeAbsoluteName(name);
                                        code   = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        result = "only non-qualified names are allowed";
                                        code   = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace name name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "origin":
                            {
                                if (arguments.Count == 3)
                                {
                                    string   executeName = arguments[2];
                                    IExecute execute     = null;

                                    code = interpreter.GetIExecuteViaResolvers(
                                        interpreter.GetResolveEngineFlags(true),
                                        executeName, null, LookupFlags.Default,
                                        ref execute, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = TclVars.GlobalNamespace + executeName;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace origin name\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "parent":
                            {
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    //
                                    // NOTE: Either they did not specify a namespace argument (use current
                                    //       namespace, which is always global and always exists) or they
                                    //       specified a namespace which should be the global one; otherwise,
                                    //       an error is reported because we do not really support namespaces.
                                    //
                                    if ((arguments.Count == 2) ||
                                        NamespaceOps.IsGlobalName(arguments[2]))
                                    {
                                        result = String.Empty;
                                        code   = ReturnCode.Ok;
                                    }
                                    else
                                    {
                                        //
                                        // NOTE: See if they prefixed the argument with "::" to figure out
                                        //       the appropriate error message (Tcl emulation).
                                        //
                                        if (NamespaceOps.IsAbsoluteName(arguments[2]))
                                        {
                                            result = String.Format("namespace \"{0}\" not found", arguments[2]);
                                        }
                                        else
                                        {
                                            result = String.Format("namespace \"{0}\" not found in \"{1}\"",
                                                                   arguments[2], TclVars.GlobalNamespace);
                                        }

                                        code = ReturnCode.Error;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace parent ?name?\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "qualifiers":
                            {
                                if (arguments.Count == 3)
                                {
                                    string qualifiers = null;
                                    string tail       = null;

                                    code = NamespaceOps.SplitName(
                                        arguments[2], ref qualifiers, ref tail, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = qualifiers;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace qualifiers string\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "rename":
                            {
                                if (arguments.Count == 4)
                                {
                                    result = "not implemented";
                                    code   = ReturnCode.Error;
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace rename oldName newName\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "tail":
                            {
                                if (arguments.Count == 3)
                                {
                                    string qualifiers = null;
                                    string tail       = null;

                                    code = NamespaceOps.SplitName(
                                        arguments[2], ref qualifiers, ref tail, ref result);

                                    if (code == ReturnCode.Ok)
                                    {
                                        result = tail;
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace tail string\"";
                                    code   = ReturnCode.Error;
                                }
                                break;
                            }

                            case "unknown":
                            {
                                //
                                // NOTE: The string is currently used as the name of the command
                                //       or procedure to execute when an unknown command is
                                //       encountered by the engine.
                                //
                                if ((arguments.Count == 2) || (arguments.Count == 3))
                                {
                                    if (arguments.Count == 3)
                                    {
                                        string unknown = StringOps.NullIfEmpty(arguments[2]);

                                        if (String.IsNullOrEmpty(unknown))
                                        {
                                            interpreter.NamespaceUnknown = interpreter.GlobalUnknown;
                                        }
                                        else
                                        {
                                            interpreter.NamespaceUnknown = unknown;
                                        }

                                        result = unknown;
                                    }
                                    else
                                    {
                                        result = interpreter.NamespaceUnknown;
                                    }

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

                            case "which":
                            {
                                //
                                // TODO: *FIXME* Only the global namespace is supported here.
                                //
                                if (arguments.Count >= 2)
                                {
                                    OptionDictionary options = new OptionDictionary(
                                        new IOption[] {
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-command", null),
                                            new Option(null, OptionFlags.None, Index.Invalid, Index.Invalid, "-variable", 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, OptionBehaviorFlags.LastIsNonOption, false, ref argumentIndex, ref result);
                                    }
                                    else
                                    {
                                        code = ReturnCode.Ok;
                                    }

                                    if (code == ReturnCode.Ok)
                                    {
                                        if ((argumentIndex != Index.Invalid) &&
                                            ((argumentIndex + 1) == arguments.Count))
                                        {
                                            string name = arguments[argumentIndex];

                                            bool isCommand = false;

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

                                            bool isVariable = false;

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

                                            if (!isCommand || !isVariable)
                                            {
                                                if (!isCommand && !isVariable)
                                                {
                                                    isCommand = true;
                                                }

                                                if (isCommand)
                                                {
                                                    IExecute execute = null;

                                                    code = interpreter.GetIExecuteViaResolvers(
                                                        interpreter.GetResolveEngineFlags(true),
                                                        name, null, LookupFlags.Default, ref execute,
                                                        ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        result = TclVars.GlobalNamespace +
                                                                 ScriptOps.MakeCommandName(name);
                                                    }
                                                    else
                                                    {
                                                        result = String.Empty;
                                                        code   = ReturnCode.Ok;
                                                    }
                                                }
                                                else
                                                {
                                                    VariableFlags flags    = VariableFlags.NamespaceWhichMask;
                                                    IVariable     variable = null;

                                                    code = interpreter.GetVariableViaResolversWithSplit(
                                                        name, ref flags, ref variable, ref result);

                                                    if (code == ReturnCode.Ok)
                                                    {
                                                        result = TclVars.GlobalNamespace +
                                                                 ScriptOps.MakeVariableName(name);
                                                    }
                                                    else
                                                    {
                                                        result = String.Empty;
                                                        code   = ReturnCode.Ok;
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";         /* COMPAT: Tcl */
                                                code   = ReturnCode.Error;
                                            }
                                        }
                                        else
                                        {
                                            if ((argumentIndex != Index.Invalid) &&
                                                Option.LooksLikeOption(arguments[argumentIndex]))
                                            {
                                                result = OptionDictionary.BadOption(options, arguments[argumentIndex]);
                                            }
                                            else
                                            {
                                                result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";
                                            }

                                            code = ReturnCode.Error;
                                        }
                                    }
                                }
                                else
                                {
                                    result = "wrong # args: should be \"namespace which ?-command? ?-variable? name\"";
                                    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 \"namespace subcommand ?arg ...?\"";
                        code   = ReturnCode.Error;
                    }
                }
                else
                {
                    result = "invalid argument list";
                    code   = ReturnCode.Error;
                }
            }
            else
            {
                result = "invalid interpreter";
                code   = ReturnCode.Error;
            }

            return(code);
        }