Example #1
0
    /// <summary> Chain this frame into the call frame stack and binds the parameters
    /// values to the formal parameters of the procedure.
    /// 
    /// </summary>
    /// <param name="proc">the procedure.
    /// </param>
    /// <param name="proc">argv the parameter values.
    /// </param>
    /// <exception cref=""> TclException if wrong number of arguments.
    /// </exception>
    internal void chain( Procedure proc, TclObject[] objv )
    {
      // FIXME: double check this ns thing in case where proc is renamed to different ns.
      this.ns = proc.ns;
      this.objv = objv;
      // FIXME : quick level hack : fix later
      level = ( interp.varFrame == null ) ? 1 : ( interp.varFrame.level + 1 );
      caller = interp.frame;
      callerVar = interp.varFrame;
      interp.frame = this;
      interp.varFrame = this;

      // parameter bindings

      int numArgs = proc.argList.Length;

      if ( ( !proc.isVarArgs ) && ( objv.Length - 1 > numArgs ) )
      {
        wrongNumProcArgs( objv[0], proc );
      }

      int i, j;
      for ( i = 0, j = 1; i < numArgs; i++, j++ )
      {
        // Handle the special case of the last formal being
        // "args".  When it occurs, assign it a list consisting of
        // all the remaining actual arguments.

        TclObject varName = proc.argList[i][0];
        TclObject value = null;

        if ( ( i == ( numArgs - 1 ) ) && proc.isVarArgs )
        {
          value = TclList.newInstance();
          value.preserve();
          for ( int k = j; k < objv.Length; k++ )
          {
            TclList.append( interp, value, objv[k] );
          }
          interp.setVar( varName, value, 0 );
          value.release();
        }
        else
        {
          if ( j < objv.Length )
          {
            value = objv[j];
          }
          else if ( proc.argList[i][1] != null )
          {
            value = proc.argList[i][1];
          }
          else
          {
            wrongNumProcArgs( objv[0], proc );
          }
          interp.setVar( varName, value, 0 );
        }
      }
    }
Example #2
0
        internal Procedure(Interp interp, NamespaceCmd.Namespace ns, string name, TclObject args, TclObject b, string sFileName, int sLineNumber)
        {
            this.NS       = ns;
            srcFileName   = sFileName;
            srcLineNumber = sLineNumber;

            // Break up the argument list into argument specifiers, then process
            // each argument specifier.

            int numArgs = TclList.getLength(interp, args);

            ArgList = new TclObject[numArgs][];
            for (int i = 0; i < numArgs; i++)
            {
                ArgList[i] = new TclObject[2];
            }

            for (int i = 0; i < numArgs; i++)
            {
                // Now divide the specifier up into name and default.

                TclObject argSpec = TclList.index(interp, args, i);
                int       specLen = TclList.getLength(interp, argSpec);

                if (specLen == 0)
                {
                    throw new TclException(interp, "procedure \"" + name + "\" has argument with no name");
                }
                if (specLen > 2)
                {
                    throw new TclException(interp, "too many fields in argument " + "specifier \"" + argSpec + "\"");
                }

                ArgList[i][0] = TclList.index(interp, argSpec, 0);
                ArgList[i][0].Preserve();
                if (specLen == 2)
                {
                    ArgList[i][1] = TclList.index(interp, argSpec, 1);
                    ArgList[i][1].Preserve();
                }
                else
                {
                    ArgList[i][1] = null;
                }
            }


            if (numArgs > 0 && (ArgList[numArgs - 1][0].ToString().Equals("args")))
            {
                isVarArgs = true;
            }
            else
            {
                isVarArgs = false;
            }


            body        = new CharPointer(b.ToString());
            body_length = body.Length();
        }
Example #3
0
        protected internal Hashtable VarTable; // Stores the variables of this CallFrame.

        /// <summary>
        /// Creates a CallFrame for the global variables.</summary>
        /// <param name="interp">
        /// current interpreter.
        /// </param>
        internal CallFrame(Interp i)
        {
            Interp = i;
            NS = i.GlobalNS;
            VarTable = new Hashtable();
            Caller = null;
            CallerVar = null;
            Objv = null;
            Level = 0;
            IsProcCallFrame = true;
        }
Example #4
0
        protected internal Hashtable VarTable; // Stores the variables of this CallFrame.

        /// <summary>
        /// Creates a CallFrame for the global variables.</summary>
        /// <param name="interp">
        /// current interpreter.
        /// </param>
        internal CallFrame(Interp i)
        {
            Interp          = i;
            NS              = i.GlobalNS;
            VarTable        = new Hashtable();
            Caller          = null;
            CallerVar       = null;
            Objv            = null;
            Level           = 0;
            IsProcCallFrame = true;
        }
Example #5
0
        /// <summary> Creates a CallFrame for the global variables.</summary>
        /// <param name="interp">current interpreter.
        /// </param>

        internal CallFrame(Interp i)
        {
            interp          = i;
            ns              = i.globalNs;
            varTable        = new Hashtable();
            caller          = null;
            callerVar       = null;
            objv            = null;
            level           = 0;
            isProcCallFrame = true;
        }
Example #6
0
        /// <summary>
        /// Chain this frame into the call frame stack and binds the parameters values to the formal parameters of the procedure.
        /// </summary>
        /// <param name="proc">
        /// the procedure.
        /// </param>
        /// <param name="proc">
        /// argv the parameter values.
        /// </param>
        /// <exception cref="">
        /// TclException if wrong number of arguments.
        /// </exception>
        internal void Chain(Procedure proc, TclObject[] objv)
        {
            // FIXME: double check this ns thing in case where proc is renamed to different ns.
            NS   = proc.NS;
            Objv = objv;
            // FIXME : quick level hack : fix later
            Level           = (Interp.VarFrame == null ? 1 : Interp.VarFrame.Level + 1);
            Caller          = Interp.Frame;
            CallerVar       = Interp.VarFrame;
            Interp.Frame    = this;
            Interp.VarFrame = this;
            // parameter bindings
            int numArgs = proc.ArgList.Length;

            if (!proc.isVarArgs && objv.Length - 1 > numArgs)
            {
                WrongNumProcArgs(objv[0], proc);
            }
            for (int i = 0, j = 1; i < numArgs; i++, j++)
            {
                // Handle the special case of the last formal being "args".  When it occurs, assign it a list consisting of
                // all the remaining actual arguments.
                TclObject varName = proc.ArgList[i][0];
                TclObject value   = null;
                if (i == (numArgs - 1) && proc.isVarArgs)
                {
                    value = TclList.NewInstance();
                    value.Preserve();
                    for (int k = j; k < objv.Length; k++)
                    {
                        TclList.Append(Interp, value, objv[k]);
                    }
                    Interp.SetVar(varName, value, 0);
                    value.Release();
                }
                else
                {
                    if (j < objv.Length)
                    {
                        value = objv[j];
                    }
                    else if (proc.ArgList[i][1] != null)
                    {
                        value = proc.ArgList[i][1];
                    }
                    else
                    {
                        WrongNumProcArgs(objv[0], proc);
                    }
                    Interp.SetVar(varName, value, 0);
                }
            }
        }
Example #7
0
        /*
         *----------------------------------------------------------------------
         *
         * InfoProcsCmd --
         *
         *      Called to implement the "info procs" command that returns the
         *      procedures in the current namespace that match an optional pattern.
         *      Handles the following syntax:
         *
         *          info procs ?pattern?
         *
         * Results:
         *      Returns if successful, raises TclException otherwise.
         *
         * Side effects:
         *      Returns a result in the interpreter's result object.
         *
         *----------------------------------------------------------------------
         */

        private static void InfoProcsCmd(Interp interp, TclObject[] objv)
        {
            string cmdName, pattern;

            NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
            IDictionaryEnumerator  search;
            WrappedCommand         cmd, realCmd;
            TclObject list;

            if (objv.Length == 2)
            {
                pattern = null;
            }
            else if (objv.Length == 3)
            {
                pattern = objv[2].ToString();
            }
            else
            {
                throw new TclNumArgsException(interp, 2, objv, "?pattern?");
            }

            // Scan through the current namespace's command table and return a list
            // of all procs that match the pattern.

            list = TclList.newInstance();
            for (search = currNs.cmdTable.GetEnumerator(); search.MoveNext();)
            {
                cmdName = ((string)search.Key);
                cmd     = (WrappedCommand)search.Value;

                // If the command isn't itself a proc, it still might be an
                // imported command that points to a "real" proc in a different
                // namespace.

                realCmd = NamespaceCmd.getOriginalCommand(cmd);

                if (Procedure.isProc(cmd) || ((realCmd != null) && Procedure.isProc(realCmd)))
                {
                    if (((System.Object)pattern == null) || Util.stringMatch(cmdName, pattern))
                    {
                        TclList.append(interp, list, TclString.newInstance(cmdName));
                    }
                }
            }

            interp.setResult(list);
            return;
        }
Example #8
0
        /*
         *----------------------------------------------------------------------
         *
         *  InfoGlobalsCmd --
         *
         *      Called to implement the "info globals" command that returns the list
         *      of global variables matching an optional pattern. Handles the
         *      following syntax:
         *
         *          info globals ?pattern?*
         *
         * Results:
         *      Returns if successful, raises TclException otherwise.
         *
         * Side effects:
         *      Returns a result in the interpreter's result object.
         *
         *----------------------------------------------------------------------
         */

        private static void InfoGlobalsCmd(Interp interp, TclObject[] objv)
        {
            string varName, pattern;

            NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
            IDictionaryEnumerator  search;
            Var       var;
            TclObject list;

            if (objv.Length == 2)
            {
                pattern = null;
            }
            else if (objv.Length == 3)
            {
                pattern = objv[2].ToString();
            }
            else
            {
                throw new TclNumArgsException(interp, 2, objv, "?pattern?");
            }

            // Scan through the global :: namespace's variable table and create a
            // list of all global variables that match the pattern.

            list = TclList.newInstance();

            for (search = globalNs.varTable.GetEnumerator(); search.MoveNext();)
            {
                varName = ((string)search.Key);
                var     = (Var)search.Value;
                if (var.isVarUndefined())
                {
                    continue;
                }
                if (((System.Object)pattern == null) || Util.stringMatch(varName, pattern))
                {
                    TclList.append(interp, list, TclString.newInstance(varName));
                }
            }

            interp.setResult(list);
            return;
        }
Example #9
0
        /*
         *----------------------------------------------------------------------
         *
         * InfoCommandsCmd --
         *
         *	Called to implement the "info commands" command that returns the
         *	list of commands in the interpreter that match an optional pattern.
         *	The pattern, if any, consists of an optional sequence of namespace
         *	names separated by "::" qualifiers, which is followed by a
         *	glob-style pattern that restricts which commands are returned.
         *	Handles the following syntax:
         *
         *          info commands ?pattern?
         *
         * Results:
         *      Returns if successful, raises TclException otherwise.
         *
         * Side effects:
         *      Returns a result in the interpreter's result object.
         *
         *----------------------------------------------------------------------
         */

        private static void InfoCommandsCmd(Interp interp, TclObject[] objv)
        {
            string cmdName, pattern, simplePattern;
            IDictionaryEnumerator search;

            NamespaceCmd.Namespace ns;
            NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
            NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
            TclObject      list, elemObj;
            bool           specificNsInPattern = false; // Init. to avoid compiler warning.
            WrappedCommand cmd;

            // Get the pattern and find the "effective namespace" in which to
            // list commands.

            if (objv.Length == 2)
            {
                simplePattern       = null;
                ns                  = currNs;
                specificNsInPattern = false;
            }
            else if (objv.Length == 3)
            {
                // From the pattern, get the effective namespace and the simple
                // pattern (no namespace qualifiers or ::'s) at the end. If an
                // error was found while parsing the pattern, return it. Otherwise,
                // if the namespace wasn't found, just leave ns NULL: we will
                // return an empty list since no commands there can be found.


                pattern = objv[2].ToString();

                // Java does not support passing an address so we pass
                // an array of size 1 and then assign arr[0] to the value
                NamespaceCmd.Namespace[] nsArr     = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
                string[] simplePatternArr          = new string[1];

                NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr);

                // Get the values out of the arrays!
                ns            = nsArr[0];
                simplePattern = simplePatternArr[0];

                if (ns != null)
                {
                    // we successfully found the pattern's ns
                    specificNsInPattern = (simplePattern.CompareTo(pattern) != 0);
                }
            }
            else
            {
                throw new TclNumArgsException(interp, 2, objv, "?pattern?");
            }

            // Scan through the effective namespace's command table and create a
            // list with all commands that match the pattern. If a specific
            // namespace was requested in the pattern, qualify the command names
            // with the namespace name.

            list = TclList.newInstance();

            if (ns != null)
            {
                search = ns.cmdTable.GetEnumerator();
                while (search.MoveNext())
                {
                    cmdName = ((string)search.Key);
                    if (((System.Object)simplePattern == null) || Util.stringMatch(cmdName, simplePattern))
                    {
                        if (specificNsInPattern)
                        {
                            cmd     = (WrappedCommand)search.Value;
                            elemObj = TclString.newInstance(interp.getCommandFullName(cmd));
                        }
                        else
                        {
                            elemObj = TclString.newInstance(cmdName);
                        }
                        TclList.append(interp, list, elemObj);
                    }
                }

                // If the effective namespace isn't the global :: namespace, and a
                // specific namespace wasn't requested in the pattern, then add in
                // all global :: commands that match the simple pattern. Of course,
                // we add in only those commands that aren't hidden by a command in
                // the effective namespace.

                if ((ns != globalNs) && !specificNsInPattern)
                {
                    search = globalNs.cmdTable.GetEnumerator();
                    while (search.MoveNext())
                    {
                        cmdName = ((string)search.Key);
                        if (((System.Object)simplePattern == null) || Util.stringMatch(cmdName, simplePattern))
                        {
                            if (ns.cmdTable[cmdName] == null)
                            {
                                TclList.append(interp, list, TclString.newInstance(cmdName));
                            }
                        }
                    }
                }
            }

            interp.setResult(list);
            return;
        }
Example #10
0
        /*
         *----------------------------------------------------------------------
         *
         * InfoVarsCmd --
         *
         *	Called to implement the "info vars" command that returns the
         *	list of variables in the interpreter that match an optional pattern.
         *	The pattern, if any, consists of an optional sequence of namespace
         *	names separated by "::" qualifiers, which is followed by a
         *	glob-style pattern that restricts which variables are returned.
         *	Handles the following syntax:
         *
         *          info vars ?pattern?
         *
         * Results:
         *      Returns if successful, raises TclException otherwise.
         *
         * Side effects:
         *      Returns a result in the interpreter's result object.
         *
         *----------------------------------------------------------------------
         */

        private static void InfoVarsCmd(Interp interp, TclObject[] objv)
        {
            string varName, pattern, simplePattern;
            IDictionaryEnumerator search;
            Var var;

            NamespaceCmd.Namespace ns;
            NamespaceCmd.Namespace globalNs = NamespaceCmd.getGlobalNamespace(interp);
            NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace(interp);
            TclObject list, elemObj;
            bool      specificNsInPattern = false; // Init. to avoid compiler warning.

            // Get the pattern and find the "effective namespace" in which to
            // list variables. We only use this effective namespace if there's
            // no active Tcl procedure frame.

            if (objv.Length == 2)
            {
                simplePattern       = null;
                ns                  = currNs;
                specificNsInPattern = false;
            }
            else if (objv.Length == 3)
            {
                // From the pattern, get the effective namespace and the simple
                // pattern (no namespace qualifiers or ::'s) at the end. If an
                // error was found while parsing the pattern, return it. Otherwise,
                // if the namespace wasn't found, just leave ns = null: we will
                // return an empty list since no variables there can be found.


                pattern = objv[2].ToString();

                // Java does not support passing an address so we pass
                // an array of size 1 and then assign arr[0] to the value
                NamespaceCmd.Namespace[] nsArr     = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummy1Arr = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummy2Arr = new NamespaceCmd.Namespace[1];
                string[] simplePatternArr          = new string[1];

                NamespaceCmd.getNamespaceForQualName(interp, pattern, null, 0, nsArr, dummy1Arr, dummy2Arr, simplePatternArr);

                // Get the values out of the arrays!
                ns            = nsArr[0];
                simplePattern = simplePatternArr[0];

                if (ns != null)
                {
                    // we successfully found the pattern's ns
                    specificNsInPattern = (simplePattern.CompareTo(pattern) != 0);
                }
            }
            else
            {
                throw new TclNumArgsException(interp, 2, objv, "?pattern?");
            }

            // If the namespace specified in the pattern wasn't found, just return.

            if (ns == null)
            {
                return;
            }

            list = TclList.newInstance();

            if ((interp.varFrame == null) || !interp.varFrame.isProcCallFrame || specificNsInPattern)
            {
                // There is no frame pointer, the frame pointer was pushed only
                // to activate a namespace, or we are in a procedure call frame
                // but a specific namespace was specified. Create a list containing
                // only the variables in the effective namespace's variable table.

                search = ns.varTable.GetEnumerator();
                while (search.MoveNext())
                {
                    varName = ((string)search.Key);
                    var     = (Var)search.Value;
                    if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0))
                    {
                        if (((System.Object)simplePattern == null) || Util.stringMatch(varName, simplePattern))
                        {
                            if (specificNsInPattern)
                            {
                                elemObj = TclString.newInstance(Var.getVariableFullName(interp, var));
                            }
                            else
                            {
                                elemObj = TclString.newInstance(varName);
                            }
                            TclList.append(interp, list, elemObj);
                        }
                    }
                }

                // If the effective namespace isn't the global :: namespace, and a
                // specific namespace wasn't requested in the pattern (i.e., the
                // pattern only specifies variable names), then add in all global ::
                // variables that match the simple pattern. Of course, add in only
                // those variables that aren't hidden by a variable in the effective
                // namespace.

                if ((ns != globalNs) && !specificNsInPattern)
                {
                    search = globalNs.varTable.GetEnumerator();
                    while (search.MoveNext())
                    {
                        varName = ((string)search.Key);
                        var     = (Var)search.Value;
                        if (!var.isVarUndefined() || ((var.flags & VarFlags.NAMESPACE_VAR) != 0))
                        {
                            if (((System.Object)simplePattern == null) || Util.stringMatch(varName, simplePattern))
                            {
                                // Skip vars defined in current namespace
                                if (ns.varTable[varName] == null)
                                {
                                    TclList.append(interp, list, TclString.newInstance(varName));
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                AppendLocals(interp, list, simplePattern, true);
            }

            interp.setResult(list);
            return;
        }
Example #11
0
 /// <summary>
 /// Chain this frame into the call frame stack and binds the parameters values to the formal parameters of the procedure.
 /// </summary>
 /// <param name="proc">
 /// the procedure.
 /// </param>
 /// <param name="proc">
 /// argv the parameter values.
 /// </param>
 /// <exception cref="">
 /// TclException if wrong number of arguments.
 /// </exception>
 internal void Chain(Procedure proc, TclObject[] objv)
 {
     // FIXME: double check this ns thing in case where proc is renamed to different ns.
     NS = proc.NS;
     Objv = objv;
     // FIXME : quick level hack : fix later
     Level = (Interp.VarFrame == null ? 1 : Interp.VarFrame.Level + 1);
     Caller = Interp.Frame;
     CallerVar = Interp.VarFrame;
     Interp.Frame = this;
     Interp.VarFrame = this;
     // parameter bindings
     int numArgs = proc.ArgList.Length;
     if (!proc.isVarArgs && objv.Length - 1 > numArgs)
         WrongNumProcArgs(objv[0], proc);
     for (int i = 0, j = 1; i < numArgs; i++, j++)
     {
         // Handle the special case of the last formal being "args".  When it occurs, assign it a list consisting of
         // all the remaining actual arguments.
         TclObject varName = proc.ArgList[i][0];
         TclObject value = null;
         if (i == (numArgs - 1) && proc.isVarArgs)
         {
             value = TclList.NewInstance();
             value.Preserve();
             for (int k = j; k < objv.Length; k++)
                 TclList.Append(Interp, value, objv[k]);
             Interp.SetVar(varName, value, 0);
             value.Release();
         }
         else
         {
             if (j < objv.Length)
                 value = objv[j];
             else if (proc.ArgList[i][1] != null)
                 value = proc.ArgList[i][1];
             else
                 WrongNumProcArgs(objv[0], proc);
             Interp.SetVar(varName, value, 0);
         }
     }
 }
Example #12
0
        public Interp()
        {
            InitBlock();
            //freeProc = null;
            _errorLine = 0;

            // An empty result is used pretty often. We will use a shared TclObject instance to represent the empty result so that we
            // don't need to create a new TclObject instance every time the interpreter result is set to empty.
            _nullResult = TclString.NewInstance(string.Empty);
            _nullResult.Preserve(); // Increment refCount to 1
            _nullResult.Preserve(); // Increment refCount to 2 (shared)
            _result = TclString.NewInstance(string.Empty); // _nullResult; // correcponds to iPtr->objResultPtr
            _result.Preserve();
            //
            _expr = new Expression();
            _nestLevel = 0;
            _maxNestingDepth = 1000;
            //
            Frame = null;
            VarFrame = null;
            //
            _returnCode = TCL.CompletionCode.OK;
            _errorInfo = null;
            _errorCode = null;
            //
            _packageTable = new Hashtable();
            _packageUnknown = null;
            _cmdCount = 0;
            _termOffset = 0;
            _resolvers = null;
            _evalFlags = 0;
            _scriptFile = null;
            _flags = 0;
            _isSafe = false;
            _assocData = null;
            //
            GlobalNS = NamespaceCmd.createNamespace(this, null, null);
            if (GlobalNS == null)
                throw new TclRuntimeError("Interp(): can't create global namespace");
            // Init things that are specific to the Jacl implementation
            _workingDir = new FileInfo(System.Environment.CurrentDirectory);
            NoEval = 0;
            //
            _notifier = Notifier.GetNotifierForThread(System.Threading.Thread.CurrentThread);
            _notifier.Preserve();
            //
            RandSeedInit = false;
            //
            _deleted = false;
            _errInProgress = false;
            _errAlreadyLogged = false;
            _errCodeSet = false;
            //
            _dbg = initDebugInfo();
            //
            _slaveTable = new Hashtable();
            _targetTable = new Hashtable();
            _aliasTable = new Hashtable();
            // init parser variables
            Parser.init(this);
            TclParse.init(this);
            // Initialize the Global (static) channel table and the local interp channel table.
            _interpChanTable = TclIO.getInterpChanTable(this);
            // Sets up the variable trace for tcl_precision.
            Util.setupPrecisionTrace(this);
            // Create the built-in commands.
            CreateCommands();
            try
            {
                // Set up tcl_platform, tcl_version, tcl_library and other global variables.
                SetVar("tcl_platform", "platform", "windows", TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_platform", "byteOrder", "bigEndian", TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_platform", "os", Environment.OSVersion.Platform.ToString(), TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_platform", "osVersion", Environment.OSVersion.Version.ToString(), TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_platform", "machine", Util.tryGetSystemProperty("os.arch", "?"), TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_version", TCL_VERSION, TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_patchLevel", TCL_PATCH_LEVEL, TCL.VarFlag.GLOBAL_ONLY);
                SetVar("tcl_library", "resource:/tcl/lang/library", TCL.VarFlag.GLOBAL_ONLY);
                if (Util.Windows)
                    SetVar("tcl_platform", "host_platform", "windows", TCL.VarFlag.GLOBAL_ONLY);
                else if (Util.Mac)
                    SetVar("tcl_platform", "host_platform", "macintosh", TCL.VarFlag.GLOBAL_ONLY);
                else
                    SetVar("tcl_platform", "host_platform", "unix", TCL.VarFlag.GLOBAL_ONLY);
                // Create the env array an populated it with proper values.
                Env.initialize(this);
                // Register Tcl's version number. Note: This MUST be  done before the call to evalResource, otherwise
                // calls to "package require tcl" will fail.
                pkgProvide("Tcl", TCL_VERSION);
                // Source the init.tcl script to initialize auto-loading.
                evalResource("/tcl/lang/library/init.tcl");
            }
            catch (TclException e)
            {
                Debug.WriteLine(GetResult().ToString());
                SupportClass.WriteStackTrace(e, Console.Error);
                throw new TclRuntimeError("unexpected TclException: " + e.Message, e);
            }
        }
Example #13
0
        protected internal void renameCommand(string oldName, string newName)
        {
            Interp interp = this;
            string newTail;
            NamespaceCmd.Namespace cmdNs, newNs;
            WrappedCommand cmd;
            Hashtable table, oldTable;
            string hashKey, oldHashKey;

            // Find the existing command. An error is returned if cmdName can't
            // be found.

            cmd = NamespaceCmd.findCommand(interp, oldName, null, 0);
            if (cmd == null)
            {
                throw new TclException(interp, "can't " + ((((System.Object)newName == null) || (newName.Length == 0)) ? "delete" : "rename") + " \"" + oldName + "\": command doesn't exist");
            }
            cmdNs = cmd.ns;

            // If the new command name is NULL or empty, delete the command. Do this
            // with Tcl_DeleteCommandFromToken, since we already have the command.

            if (((System.Object)newName == null) || (newName.Length == 0))
            {
                DeleteCommandFromToken(cmd);
                return;
            }

            // Make sure that the destination command does not already exist.
            // The rename operation is like creating a command, so we should
            // automatically create the containing namespaces just like
            // Tcl_CreateCommand would.

            NamespaceCmd.Namespace[] newNsArr = new NamespaceCmd.Namespace[1];
            NamespaceCmd.Namespace[] dummyArr = new NamespaceCmd.Namespace[1];
            string[] newTailArr = new string[1];

            NamespaceCmd.getNamespaceForQualName(interp, newName, null, TCL.VarFlag.CREATE_NS_IF_UNKNOWN, newNsArr, dummyArr, dummyArr, newTailArr);

            newNs = newNsArr[0];
            newTail = newTailArr[0];

            if ((newNs == null) || ((System.Object)newTail == null))
            {
                throw new TclException(interp, "can't rename to \"" + newName + "\": bad command name");
            }
            if (newNs.cmdTable[newTail] != null)
            {
                throw new TclException(interp, "can't rename to \"" + newName + "\": command already exists");
            }

            // Warning: any changes done in the code here are likely
            // to be needed in Tcl_HideCommand() code too.
            // (until the common parts are extracted out)     --dl

            // Put the command in the new namespace so we can check for an alias
            // loop. Since we are adding a new command to a namespace, we must
            // handle any shadowing of the global commands that this might create.

            oldTable = cmd.table;
            oldHashKey = cmd.hashKey;
            newNs.cmdTable.Add(newTail, cmd);
            cmd.table = newNs.cmdTable;
            cmd.hashKey = newTail;
            cmd.ns = newNs;

            // FIXME : this is a nasty hack that fixes renaming for Procedures
            // that move from one namespace to another, but the real problem
            // is that a rename does not work for Command instances in general

            if (cmd.cmd is Procedure)
            {
                Procedure p = (Procedure)cmd.cmd;
                p.NS = cmd.ns;
            }

            // Now check for an alias loop. If we detect one, put everything back
            // the way it was and report the error.

            try
            {
                interp.preventAliasLoop(interp, cmd);
            }
            catch (TclException e)
            {
                newNs.cmdTable.Remove(newTail);
                cmd.table = oldTable;
                cmd.hashKey = oldHashKey;
                cmd.ns = cmdNs;
                throw;
            }

            // The new command name is okay, so remove the command from its
            // current namespace. This is like deleting the command, so bump
            // the cmdEpoch to invalidate any cached references to the command.

            SupportClass.HashtableRemove(oldTable, oldHashKey);

            return;
        }
Example #14
0
        public void createObjCommand(string cmdName, dxObjCmdProc proc, object clientData, dxCmdDeleteProc deleteProc)
        // Command object to associate with cmdName.
        {
            ImportRef oldRef = null;
            NamespaceCmd.Namespace ns;
            WrappedCommand cmd, refCmd;
            string tail;
            ImportedCmdData data;
            int _new;

            if (_deleted)
            {
                // The interpreter is being deleted.  Don't create any new
                // commands; it's not safe to muck with the interpreter anymore.

                return;
            }

            // Determine where the command should reside. If its name contains 
            // namespace qualifiers, we put it in the specified namespace; 
            // otherwise, we always put it in the global namespace.

            if (cmdName.IndexOf("::") != -1)
            {
                // Java does not support passing an address so we pass
                // an array of size 1 and then assign arr[0] to the value
                NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummyArr = new NamespaceCmd.Namespace[1];
                string[] tailArr = new string[1];

                NamespaceCmd.getNamespaceForQualName(this, cmdName, null, TCL.VarFlag.CREATE_NS_IF_UNKNOWN, nsArr, dummyArr, dummyArr, tailArr);

                ns = nsArr[0];
                tail = tailArr[0];

                if ((ns == null) || ((System.Object)tail == null))
                {
                    return;
                }
            }
            else
            {
                ns = GlobalNS;
                tail = cmdName;
            }

            cmd = (WrappedCommand)ns.cmdTable[tail];
            if (cmd != null)
            {
                /*
         * Command already exists. If its object-based Tcl_ObjCmdProc is
         * TclInvokeStringCommand, we just set its Tcl_ObjCmdProc to the
         * argument "proc". Otherwise, we delete the old command. 
         */
                if (cmd.objProc != null && cmd.objProc.GetType().Name == "TclInvokeStringCommand")
                {
                    cmd.objProc = proc;
                    cmd.objClientData = clientData;
                    cmd.deleteProc = deleteProc;
                    cmd.deleteData = clientData;
                    return;
                }
                /*
                 * Otherwise, we delete the old command.  Be careful to preserve
                 * any existing import links so we can restore them down below.
                 * That way, you can redefine a command and its import status
                 * will remain intact.
                 */
                oldRef = cmd.ImportRef;
                cmd.ImportRef = null;

                DeleteCommandFromToken(cmd);

                // FIXME : create a test case for this condition!

                cmd = (WrappedCommand)ns.cmdTable[tail];
                if (cmd != null)
                {
                    // If the deletion callback recreated the command, just throw
                    // away the new command (if we try to delete it again, we
                    // could get stuck in an infinite loop).

                    SupportClass.HashtableRemove(cmd.table, cmd.hashKey);
                }
            }

            cmd = new WrappedCommand();
            ns.cmdTable.Add(tail, cmd);
            cmd.table = ns.cmdTable;
            cmd.hashKey = tail;
            cmd.ns = ns;
            cmd.cmd = null;
            cmd.deleted = false;
            // FIXME : import feature not implemented
            //cmd.importRef = null;

            // TODO -- Determine if this is all correct
            cmd.objProc = proc;
            cmd.objClientData = clientData;
            //cmd.proc = TclInvokeObjectCommand;
            cmd.clientData = (object)cmd;
            cmd.deleteProc = deleteProc;
            cmd.deleteData = clientData;
            cmd.flags = 0;


            // Plug in any existing import references found above.  Be sure
            // to update all of these references to point to the new command.

            if (oldRef != null)
            {
                cmd.ImportRef = oldRef;
                while (oldRef != null)
                {
                    refCmd = oldRef.ImportedCmd;
                    data = (ImportedCmdData)refCmd.cmd;
                    data.RealCmd = cmd;
                    oldRef = oldRef.Next;
                }
            }

            // There are no shadowed commands in Jacl because they are only
            // used in the 8.0 compiler

            return;
        }
Example #15
0
        public void CreateCommand(string cmdName, ICommand cmdImpl) // Command object to associate with cmdName.
        {
            ImportRef oldRef = null;
            NamespaceCmd.Namespace ns;
            WrappedCommand cmd, refCmd;
            string tail;
            ImportedCmdData data;
            // The interpreter is being deleted.  Don't create any new commands; it's not safe to muck with the interpreter anymore.
            if (_deleted)
                return;
            // Determine where the command should reside. If its name contains namespace qualifiers, we put it in the specified namespace; 
            // otherwise, we always put it in the global namespace.
            if (cmdName.IndexOf("::") != -1)
            {
                // C# does not support passing an address so we pass an array of size 1 and then assign arr[0] to the value
                NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
                NamespaceCmd.Namespace[] dummyArr = new NamespaceCmd.Namespace[1];
                string[] tailArr = new string[1];
                NamespaceCmd.getNamespaceForQualName(this, cmdName, null, TCL.VarFlag.CREATE_NS_IF_UNKNOWN, nsArr, dummyArr, dummyArr, tailArr);
                ns = nsArr[0];
                tail = tailArr[0];
                if (ns == null || (object)tail == null)
                    return;
            }
            else
            {
                ns = GlobalNS;
                tail = cmdName;
            }
            cmd = (WrappedCommand)ns.cmdTable[tail];
            if (cmd != null)
            {
                // Command already exists. Delete the old one. Be careful to preserve any existing import links so we can
                // restore them down below.  That way, you can redefine a command and its import status will remain intact.
                oldRef = cmd.ImportRef; cmd.ImportRef = null;
                DeleteCommandFromToken(cmd);
                // FIXME : create a test case for this condition!
                cmd = (WrappedCommand)ns.cmdTable[tail];
                // If the deletion callback recreated the command, just throw away the new command (if we try to delete it again, we could get stuck in an infinite loop).
                if (cmd != null)
                    SupportClass.HashtableRemove(cmd.table, cmd.hashKey);
            }

            cmd = new WrappedCommand();
            ns.cmdTable.Add(tail, cmd);
            cmd.table = ns.cmdTable;
            cmd.hashKey = tail;
            cmd.ns = ns;
            cmd.cmd = cmdImpl;
            cmd.deleted = false;
            // FIXME : import feature not implemented
            //cmd.importRef = null;

            // Plug in any existing import references found above.  Be sure
            // to update all of these references to point to the new command.

            if (oldRef != null)
            {
                cmd.ImportRef = oldRef;
                while (oldRef != null)
                {
                    refCmd = oldRef.ImportedCmd;
                    data = (ImportedCmdData)refCmd.cmd;
                    data.RealCmd = cmd;
                    oldRef = oldRef.Next;
                }
            }

            // There are no shadowed commands in Jacl because they are only
            // used in the 8.0 compiler

            return;
        }
Example #16
0
        public override void EventuallyDispose()
        {
            if (_deleted)
                return;
            _deleted = true;
            if (_nestLevel > 0) { } //-- TODO -- Determine why this is an error throw new TclRuntimeError("dispose() called with active evals");
            // Remove our association with the notifer (if we had one).
            if (_notifier != null)
            {
                _notifier.Release(); _notifier = null;
            }
            // Dismantle everything in the global namespace except for the "errorInfo" and "errorCode" variables. These might be needed
            // later on if errors occur while deleting commands. We are careful to destroy and recreate the "errorInfo" and "errorCode"
            // variables, in case they had any traces on them.
            // Dismantle the namespace here, before we clear the assocData. If any background errors occur here, they will be deleted below.
            // FIXME : check impl of TclTeardownNamespace
            NamespaceCmd.TeardownNamespace(GlobalNS);
            // Delete all variables.
            TclObject errorInfoObj = null, errorCodeObj = null;
            try { errorInfoObj = GetVar("errorInfo", null, TCL.VarFlag.GLOBAL_ONLY); }
            catch (TclException) { } // Do nothing when var does not exist.
            if (errorInfoObj != null)
                errorInfoObj.Preserve();
            try { errorCodeObj = GetVar("errorCode", null, TCL.VarFlag.GLOBAL_ONLY); }
            catch (TclException) { } // Do nothing when var does not exist.
            if (errorCodeObj != null)
                errorCodeObj.Preserve();
            Frame = null;
            VarFrame = null;
            try
            {
                if (errorInfoObj != null)
                {
                    SetVar("errorInfo", null, errorInfoObj, TCL.VarFlag.GLOBAL_ONLY);
                    errorInfoObj.Release();
                }
                if (errorCodeObj != null)
                {
                    SetVar("errorCode", null, errorCodeObj, TCL.VarFlag.GLOBAL_ONLY);
                    errorCodeObj.Release();
                }
            }
            catch (TclException) { } // Ignore it -- same behavior as Tcl 8.0.
            // Tear down the math function table.
            _expr = null;
            // Remove all the assoc data tied to this interp and invoke deletion callbacks; note that a callback can create new callbacks, so we iterate.
            if (_assocData != null)
            {
                foreach (IAssocData data in _assocData.Values)
                    data.Dispose(this);
                _assocData.Clear();
            }
            // Close any remaining channels
            for (IDictionaryEnumerator e = _interpChanTable.GetEnumerator(); e.MoveNext(); )
            {
                Object key = e.Key;
                Channel chan = (Channel)e.Value;
                try { chan.Close(); }
                catch (IOException) { } // Ignore any IO errors
            }
            // Finish deleting the global namespace.
            NamespaceCmd.DeleteNamespace(GlobalNS); GlobalNS = null; // FIXME : check impl of Tcl_DeleteNamespace

            // Free up the result *after* deleting variables, since variable deletion could have transferred ownership of the result string to Tcl.
            Frame = null;
            VarFrame = null;
            _resolvers = null;
            ResetResult();
        }
Example #17
0
        /// <summary>
        /// Tcl_ProcObjCmd -> ProcCmd.cmdProc
        ///
        /// Creates a new Tcl procedure.
        ///
        /// </summary>
        /// <param name="interp">the current interpreter.
        /// </param>
        /// <param name="objv">command arguments.
        /// </param>
        /// <exception cref=""> TclException If incorrect number of arguments.
        /// </exception>

        public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv)
        {
            Procedure proc;
            string    fullName, procName;

            NamespaceCmd.Namespace ns, altNs, cxtNs;
            Command       cmd;
            StringBuilder ds;

            if (objv.Length != 4)
            {
                throw new TclNumArgsException(interp, 1, objv, "name args body");
            }

            // Determine the namespace where the procedure should reside. Unless
            // the command name includes namespace qualifiers, this will be the
            // current namespace.


            fullName = objv[1].ToString();

            // Java does not support passing an address so we pass
            // an array of size 1 and then assign arr[0] to the value
            NamespaceCmd.Namespace[] nsArr    = new NamespaceCmd.Namespace[1];
            NamespaceCmd.Namespace[] altNsArr = new NamespaceCmd.Namespace[1];
            NamespaceCmd.Namespace[] cxtNsArr = new NamespaceCmd.Namespace[1];
            string[] procNameArr = new string[1];

            NamespaceCmd.getNamespaceForQualName(interp, fullName, null, 0, nsArr, altNsArr, cxtNsArr, procNameArr);

            // Get the values out of the arrays
            ns       = nsArr[0];
            altNs    = altNsArr[0];
            cxtNs    = cxtNsArr[0];
            procName = procNameArr[0];

            if (ns == null)
            {
                throw new TclException(interp, "can't create procedure \"" + fullName + "\": unknown namespace");
            }
            if ((System.Object)procName == null)
            {
                throw new TclException(interp, "can't create procedure \"" + fullName + "\": bad procedure name");
            }
            // FIXME : could there be a problem with a command named ":command" ?
            if ((ns != NamespaceCmd.getGlobalNamespace(interp)) && ((System.Object)procName != null) && ((procName.Length > 0) && (procName[0] == ':')))
            {
                throw new TclException(interp, "can't create procedure \"" + procName + "\" in non-global namespace with name starting with \":\"");
            }

            //  Create the data structure to represent the procedure.

            proc = new Procedure(interp, ns, procName, objv[2], objv[3], interp.ScriptFile, interp.getArgLineNumber(3));

            // Now create a command for the procedure. This will initially be in
            // the current namespace unless the procedure's name included namespace
            // qualifiers. To create the new command in the right namespace, we
            // generate a fully qualified name for it.

            ds = new StringBuilder();
            if (ns != NamespaceCmd.getGlobalNamespace(interp))
            {
                ds.Append(ns.fullName);
                ds.Append("::");
            }
            ds.Append(procName);

            interp.createCommand(ds.ToString(), proc);

            // Now initialize the new procedure's cmdPtr field. This will be used
            // later when the procedure is called to determine what namespace the
            // procedure will run in. This will be different than the current
            // namespace if the proc was renamed into a different namespace.

            // FIXME : we do not handle renaming into another namespace correctly yet!
            //procPtr->cmdPtr = (Command *) cmd;

            return(TCL.CompletionCode.RETURN);
        }
Example #18
0
        /// <summary> 
        /// Tcl_ProcObjCmd -> ProcCmd.cmdProc
        /// 
        /// Creates a new Tcl procedure.
        /// 
        /// </summary>
        /// <param name="interp">the current interpreter.
        /// </param>
        /// <param name="objv">command arguments.
        /// </param>
        /// <exception cref=""> TclException If incorrect number of arguments.
        /// </exception>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] objv)
        {
            Procedure proc;
            string fullName, procName;
            NamespaceCmd.Namespace ns, altNs, cxtNs;
            ICommand cmd;
            StringBuilder ds;

            if (objv.Length != 4)
            {
                throw new TclNumArgsException(interp, 1, objv, "name args body");
            }

            // Determine the namespace where the procedure should reside. Unless
            // the command name includes namespace qualifiers, this will be the
            // current namespace.


            fullName = objv[1].ToString();

            // Java does not support passing an address so we pass
            // an array of size 1 and then assign arr[0] to the value
            NamespaceCmd.Namespace[] nsArr = new NamespaceCmd.Namespace[1];
            NamespaceCmd.Namespace[] altNsArr = new NamespaceCmd.Namespace[1];
            NamespaceCmd.Namespace[] cxtNsArr = new NamespaceCmd.Namespace[1];
            string[] procNameArr = new string[1];

            NamespaceCmd.getNamespaceForQualName(interp, fullName, null, 0, nsArr, altNsArr, cxtNsArr, procNameArr);

            // Get the values out of the arrays
            ns = nsArr[0];
            altNs = altNsArr[0];
            cxtNs = cxtNsArr[0];
            procName = procNameArr[0];

            if (ns == null)
            {
                throw new TclException(interp, "can't create procedure \"" + fullName + "\": unknown namespace");
            }
            if ((System.Object)procName == null)
            {
                throw new TclException(interp, "can't create procedure \"" + fullName + "\": bad procedure name");
            }
            // FIXME : could there be a problem with a command named ":command" ?
            if ((ns != NamespaceCmd.getGlobalNamespace(interp)) && ((System.Object)procName != null) && ((procName.Length > 0) && (procName[0] == ':')))
            {
                throw new TclException(interp, "can't create procedure \"" + procName + "\" in non-global namespace with name starting with \":\"");
            }

            //  Create the data structure to represent the procedure.

            proc = new Procedure(interp, ns, procName, objv[2], objv[3], interp.ScriptFile, interp.getArgLineNumber(3));

            // Now create a command for the procedure. This will initially be in
            // the current namespace unless the procedure's name included namespace
            // qualifiers. To create the new command in the right namespace, we
            // generate a fully qualified name for it.

            ds = new StringBuilder();
            if (ns != NamespaceCmd.getGlobalNamespace(interp))
            {
                ds.Append(ns.fullName);
                ds.Append("::");
            }
            ds.Append(procName);

            interp.CreateCommand(ds.ToString(), proc);

            // Now initialize the new procedure's cmdPtr field. This will be used
            // later when the procedure is called to determine what namespace the
            // procedure will run in. This will be different than the current
            // namespace if the proc was renamed into a different namespace.

            // FIXME : we do not handle renaming into another namespace correctly yet!
            //procPtr->cmdPtr = (Command *) cmd;

            return TCL.CompletionCode.RETURN;
        }