Пример #1
0
        /// <summary> TCL.Tcl_GetIntFromObj -> TclInteger.get
        ///
        /// Returns the integer value of the object.
        ///
        /// </summary>
        /// <param name="interp">current interpreter.
        /// </param>
        /// <param name="tobj">the object to operate on.
        /// </param>
        /// <returns> the integer value of the object.
        /// </returns>

        public static int Get(Interp interp, TclObject tobj)
        {
            setIntegerFromAny(interp, tobj);
            TclInteger tint = (TclInteger)tobj.InternalRep;

            return(tint.value);
        }
Пример #2
0
        /// <summary> This procedure is invoked to process the "seek" Tcl command.
        /// See the user documentation for details on what it does.
        /// </summary>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            Channel chan; /* The channel being operated on this method */
            int     mode; /* Stores the search mode, either beg, cur or end
                           * of file.  See the TclIO class for more info */

            if (argv.Length != 3 && argv.Length != 4)
            {
                throw new TclNumArgsException(interp, 1, argv, "channelId offset ?origin?");
            }

            // default is the beginning of the file

            mode = TclIO.SEEK_SET;
            if (argv.Length == 4)
            {
                int index = TclIndex.Get(interp, argv[3], validOrigins, "origin", 0);

                switch (index)
                {
                case OPT_START:
                {
                    mode = TclIO.SEEK_SET;
                    break;
                }

                case OPT_CURRENT:
                {
                    mode = TclIO.SEEK_CUR;
                    break;
                }

                case OPT_END:
                {
                    mode = TclIO.SEEK_END;
                    break;
                }
                }
            }


            chan = TclIO.getChannel(interp, argv[1].ToString());
            if (chan == null)
            {
                throw new TclException(interp, "can not find channel named \"" + argv[1].ToString() + "\"");
            }
            long offset = TclInteger.Get(interp, argv[2]);

            try
            {
                chan.seek(interp, offset, mode);
            }
            catch (IOException e)
            {
                // FIXME: Need to figure out Tcl specific error conditions.
                // Should we also wrap an IOException in a ReflectException?
                throw new TclRuntimeError("SeekCmd.cmdProc() Error: IOException when seeking " + chan.ChanName + ":" + e.Message);
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #3
0
        /// <summary> This procedure is invoked to process the "eof" Tcl command.
        /// See the user documentation for details on what it does.
        ///
        /// </summary>
        /// <param name="interp">the current interpreter.
        /// </param>
        /// <param name="argv">command arguments.
        /// </param>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            Channel chan; /* The channel being operated on this method */

            if (argv.Length != 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "channelId");
            }


            chan = TclIO.getChannel(interp, argv[1].ToString());
            if (chan == null)
            {
                throw new TclException(interp, "can not find channel named \"" + argv[1].ToString() + "\"");
            }

            if (chan.eof())
            {
                interp.SetResult(TclInteger.NewInstance(1));
            }
            else
            {
                interp.SetResult(TclInteger.NewInstance(0));
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #4
0
        /// <summary> See Tcl user documentation for details.</summary>
        /// <exception cref=""> TclException If incorrect number of arguments.
        /// </exception>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            if (argv.Length != 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "list");
            }
            interp.SetResult(TclInteger.NewInstance(TclList.getLength(interp, argv[1])));
            return(TCL.CompletionCode.RETURN);
        }
Пример #5
0
 internal static int FormatNumber(Interp interp, char type, TclObject src, byte[] resultBytes, int cursor)
 {
     if (type == 'd')
     {
         double       dvalue = TclDouble.Get(interp, src);
         MemoryStream ms     = new MemoryStream(resultBytes, cursor, 8);
         BinaryWriter writer = new BinaryWriter(ms);
         writer.Write(dvalue);
         cursor += 8;
         writer.Close();
         ms.Close();
     }
     else if (type == 'f')
     {
         float        fvalue = (float)TclDouble.Get(interp, src);
         MemoryStream ms     = new MemoryStream(resultBytes, cursor, 4);
         BinaryWriter writer = new BinaryWriter(ms);
         writer.Write(fvalue);
         cursor += 4;
         writer.Close();
         ms.Close();
     }
     else
     {
         int value = TclInteger.Get(interp, src);
         if (type == 'c')
         {
             resultBytes[cursor++] = (byte)value;
         }
         else if (type == 's')
         {
             resultBytes[cursor++] = (byte)value;
             resultBytes[cursor++] = (byte)(value >> 8);
         }
         else if (type == 'S')
         {
             resultBytes[cursor++] = (byte)(value >> 8);
             resultBytes[cursor++] = (byte)value;
         }
         else if (type == 'i')
         {
             resultBytes[cursor++] = (byte)value;
             resultBytes[cursor++] = (byte)(value >> 8);
             resultBytes[cursor++] = (byte)(value >> 16);
             resultBytes[cursor++] = (byte)(value >> 24);
         }
         else if (type == 'I')
         {
             resultBytes[cursor++] = (byte)(value >> 24);
             resultBytes[cursor++] = (byte)(value >> 16);
             resultBytes[cursor++] = (byte)(value >> 8);
             resultBytes[cursor++] = (byte)value;
         }
     }
     return(cursor);
 }
Пример #6
0
        /*
         *----------------------------------------------------------------------
         *
         * InfoLevelCmd --
         *
         *      Called to implement the "info level" command that returns
         *      information about the call stack. Handles the following syntax:
         *
         *          info level ?number?
         *
         * Results:
         *      Returns if successful, raises TclException otherwise.
         *
         * Side effects:
         *      Returns a result in the interpreter's result object.
         *
         *----------------------------------------------------------------------
         */

        private static void InfoLevelCmd(Interp interp, TclObject[] objv)
        {
            int       level;
            CallFrame frame;
            TclObject list;

            if (objv.Length == 2)
            {
                // just "info level"
                if (interp.VarFrame == null)
                {
                    interp.SetResult(0);
                }
                else
                {
                    interp.SetResult(interp.VarFrame.Level);
                }
                return;
            }
            else if (objv.Length == 3)
            {
                level = TclInteger.Get(interp, objv[2]);

                if (level <= 0)
                {
                    if (interp.VarFrame == null)
                    {
                        throw new TclException(interp, "bad level \"" + objv[2].ToString() + "\"");
                    }

                    level += interp.VarFrame.Level;
                }

                for (frame = interp.VarFrame; frame != null; frame = frame.CallerVar)
                {
                    if (frame.Level == level)
                    {
                        break;
                    }
                }
                if ((frame == null) || frame.Objv == null)
                {
                    throw new TclException(interp, "bad level \"" + objv[2].ToString() + "\"");
                }

                list = TclList.NewInstance();
                for (int i = 0; i < frame.Objv.Length; i++)
                {
                    TclList.Append(interp, list, TclString.NewInstance(frame.Objv[i]));
                }
                interp.SetResult(list);
                return;
            }

            throw new TclNumArgsException(interp, 2, objv, "?number?");
        }
Пример #7
0
 public static void Tcl_SetIntObj(TclObject to, int result
                                  )
 {
     while (to.Shared)
     {
         to.Release();
     }
     TclInteger.set(to, result);
     to.Preserve();
 }
Пример #8
0
        private static TclObject ScanNumber(byte[] src, int pos, int type) // Format character from "binary scan"
        {
            switch (type)
            {
            case 'c':
            {
                return(TclInteger.NewInstance((sbyte)src[pos]));
            }

            case 's':
            {
                short value = (short)((src[pos] & 0xff) + ((src[pos + 1] & 0xff) << 8));
                return(TclInteger.NewInstance((int)value));
            }

            case 'S':
            {
                short value = (short)((src[pos + 1] & 0xff) + ((src[pos] & 0xff) << 8));
                return(TclInteger.NewInstance((int)value));
            }

            case 'i':
            {
                int value = (src[pos] & 0xff) + ((src[pos + 1] & 0xff) << 8) + ((src[pos + 2] & 0xff) << 16) + ((src[pos + 3] & 0xff) << 24);
                return(TclInteger.NewInstance(value));
            }

            case 'I':
            {
                int value = (src[pos + 3] & 0xff) + ((src[pos + 2] & 0xff) << 8) + ((src[pos + 1] & 0xff) << 16) + ((src[pos] & 0xff) << 24);
                return(TclInteger.NewInstance(value));
            }

            case 'f':
            {
                MemoryStream ms     = new MemoryStream(src, pos, 4, false);
                BinaryReader reader = new BinaryReader(ms);
                double       fvalue = reader.ReadSingle();
                reader.Close();
                ms.Close();
                return(TclDouble.NewInstance(fvalue));
            }

            case 'd':
            {
                MemoryStream ms     = new MemoryStream(src, pos, 8, false);
                BinaryReader reader = new BinaryReader(ms);
                double       dvalue = reader.ReadDouble();
                reader.Close();
                ms.Close();
                return(TclDouble.NewInstance(dvalue));
            }
            }
            return(null);
        }
Пример #9
0
 public static int Tcl_GetIntFromObj(Interp interp, TclObject to, out int value)
 {
     try
     {
         value = TclInteger.Get(interp, to);
         return(TCL.TCL_OK);
     }
     catch
     {
         value = 0;
         return(TCL.TCL_ERROR);
     }
 }
Пример #10
0
 public static bool Tcl_GetInt(Interp interp, TclObject to, out u32 value)
 {
     try
     {
         value = (u32)TclInteger.Get(interp, to);
         return(false);
     }
     catch
     {
         value = 0;
         return(true);
     }
 }
Пример #11
0
        /// <summary> This procedure is invoked to process the "incr" Tcl command.
        /// See the user documentation for details on what it does.
        /// </summary>
        /// <exception cref=""> TclException if wrong # of args or increment is not an
        /// integer.
        /// </exception>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] objv)
        {
            int       incrAmount;
            TclObject newValue;

            if ((objv.Length != 2) && (objv.Length != 3))
            {
                throw new TclNumArgsException(interp, 1, objv, "varName ?increment?");
            }

            // Calculate the amount to increment by.

            if (objv.Length == 2)
            {
                incrAmount = 1;
            }
            else
            {
                try
                {
                    incrAmount = TclInteger.Get(interp, objv[2]);
                }
                catch (TclException e)
                {
                    interp.AddErrorInfo("\n    (reading increment)");
                    throw;
                }
            }

            // Increment the variable's value.

            newValue = Var.incrVar(interp, objv[1], null, incrAmount, TCL.VarFlag.LEAVE_ERR_MSG);

            // FIXME: we need to look at this exception throwing problem again

            /*
             * if (newValue == null) {
             * return TCL_ERROR;
             * }
             */

            // Set the interpreter's object result to refer to the variable's new
            // value object.

            interp.SetResult(newValue);
            return(TCL.CompletionCode.RETURN);
        }
Пример #12
0
        internal static int getIntForIndex(Interp interp, TclObject tobj, int endValue)
        {
            int length, offset;

            if (tobj.InternalRep is TclInteger)
            {
                return(TclInteger.Get(interp, tobj));
            }


            string bytes = tobj.ToString();

            length = bytes.Length;

            string intforindex_error = "bad index \"" + bytes + "\": must be integer or end?-integer?" + checkBadOctal(interp, bytes);

            // FIXME : should we replace this call to regionMatches with a generic strncmp?
            if (!(String.Compare("end", 0, bytes, 0, (length > 3) ? 3 : length) == 0))
            {
                try
                {
                    offset = TclInteger.Get(null, tobj);
                }
                catch (TclException e)
                {
                    throw new TclException(interp, "bad index \"" + bytes + "\": must be integer or end?-integer?" + checkBadOctal(interp, bytes));
                }
                return(offset);
            }

            if (length <= 3)
            {
                return(endValue);
            }
            else if (bytes[3] == '-')
            {
                // This is our limited string expression evaluator

                offset = Util.getInt(interp, bytes.Substring(3));
                return(endValue + offset);
            }
            else
            {
                throw new TclException(interp, "bad index \"" + bytes + "\": must be integer or end?-integer?" + checkBadOctal(interp, bytes.Substring(3)));
            }
        }
Пример #13
0
        /// <summary> See Tcl user documentation for details.</summary>
        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            int code;

            if (argv.Length > 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "?returnCode?");
            }
            if (argv.Length == 2)
            {
                code = TclInteger.Get(interp, argv[1]);
            }
            else
            {
                code = 0;
            }
            return(TCL.CompletionCode.EXIT);
        }
Пример #14
0
        private static void setDoubleFromAny(Interp interp, TclObject tobj)
        {
            IInternalRep rep = tobj.InternalRep;

            if (rep is TclDouble)
            {
                /*
                 * Do nothing.
                 */
            }
            else if (rep is TclBoolean)
            {
                /*
                 * Short-cut.
                 */

                bool b = TclBoolean.get(interp, tobj);
                if (b)
                {
                    tobj.InternalRep = new TclDouble(1.0);
                }
                else
                {
                    tobj.InternalRep = new TclDouble(0.0);
                }
            }
            else if (rep is TclInteger)
            {
                /*
                 * Short-cut.
                 */

                int i = TclInteger.Get(interp, tobj);
                tobj.InternalRep = new TclDouble(i);
            }
            else
            {
                tobj.InternalRep = new TclDouble(interp, tobj.ToString());
            }
        }
Пример #15
0
        /// <summary> This procedure is invoked to process the "catch" Tcl command.
        /// See the user documentation for details on what it does.
        ///
        /// </summary>
        /// <param name="interp">the current interpreter.
        /// </param>
        /// <param name="argv">command arguments.
        /// </param>
        /// <exception cref=""> TclException if wrong number of arguments.
        /// </exception>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            if (argv.Length != 2 && argv.Length != 3)
            {
                throw new TclNumArgsException(interp, 1, argv, "command ?varName?");
            }

            TclObject result;

            TCL.CompletionCode code = TCL.CompletionCode.OK;

            try
            {
                interp.Eval(argv[1], 0);
            }
            catch (TclException e)
            {
                code = e.GetCompletionCode();
            }

            result = interp.GetResult();

            if (argv.Length == 3)
            {
                try
                {
                    interp.SetVar(argv[2], result, 0);
                }
                catch (TclException e)
                {
                    throw new TclException(interp, "couldn't save command result in variable");
                }
            }

            interp.ResetResult();
            interp.SetResult(TclInteger.NewInstance((int)code));
            return(TCL.CompletionCode.RETURN);
        }
Пример #16
0
        /// <summary> Called to convert the other object's internal rep to boolean.
        ///
        /// </summary>
        /// <param name="interp">current interpreter.
        /// </param>
        /// <param name="tobj">the TclObject to convert to use the
        /// representation provided by this class.
        /// </param>
        private static void setBooleanFromAny(Interp interp, TclObject tobj)
        {
            IInternalRep rep = tobj.InternalRep;

            if (rep is TclBoolean)
            {
                /*
                 * Do nothing.
                 */
            }
            else if (rep is TclInteger)
            {
                int i = TclInteger.Get(interp, tobj);
                tobj.InternalRep = new TclBoolean(i != 0);
            }
            else
            {
                /*
                 * (ToDo) other short-cuts
                 */
                tobj.InternalRep = new TclBoolean(interp, tobj.ToString());
            }
        }
Пример #17
0
        /// <summary> See Tcl user documentation for details.</summary>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            if ((argv.Length < 2) || (argv.Length > 3))
            {
                throw new TclNumArgsException(interp, 1, argv, "script ?count?");
            }

            int count;

            if (argv.Length == 2)
            {
                count = 1;
            }
            else
            {
                count = TclInteger.Get(interp, argv[2]);
            }

            long startTime = System.DateTime.Now.Ticks;

            for (int i = 0; i < count; i++)
            {
                interp.Eval(argv[1], 0);
            }
            long endTime = System.DateTime.Now.Ticks;
            long uSecs   = (((endTime - startTime) / 10) / count);

            if (uSecs == 1)
            {
                interp.SetResult(TclString.NewInstance("1 microsecond per iteration"));
            }
            else
            {
                interp.SetResult(TclString.NewInstance(uSecs + " microseconds per iteration"));
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #18
0
        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            int firstWord;            /* Index to the first non-switch arg */
            int argLen = argv.Length; /* No of args to copy to argStrs     */
            int exit;                 /* denotes exit status of process    */
            int errorBytes = 0;       /* number of bytes of process stderr */

            //bool background; /* Indicates a bg process            */
            //bool keepNewline; /* Retains newline in pipline output */
            System.Diagnostics.Process p; /* The exec-ed process               */
            string        argStr;         /* Conversion of argv to a string    */
            StringBuilder sbuf;

            /*
             * Check for a leading "-keepnewline" argument.
             */

            for (firstWord = 1; firstWord < argLen; firstWord++)
            {
                argStr = argv[firstWord].ToString();
                if ((argStr.Length > 0) && (argStr[0] == '-'))
                {
                    //if (argStr.Equals("-keepnewline"))
                    //{
                    //  keepNewline = true;
                    //}
                    //else
                    if (argStr.Equals("--"))
                    {
                        firstWord++;
                        break;
                    }
                    else
                    {
                        throw new TclException(interp, "bad switch \"" + argStr + "\": must be -keepnewline or --");
                    }
                }
            }

            if (argLen <= firstWord)
            {
                throw new TclNumArgsException(interp, 1, argv, "?switches? arg ?arg ...?");
            }


            /*
             * See if the command is to be run in background.
             * Currently this does nothing, it is just for compatibility
             */


            //if (argv[argLen - 1].ToString().Equals("&"))
            //{
            //  argLen--;
            //  background = true;
            //}

            try
            {
                /*
                 * It is necessary to perform system specific
                 * operations before calling exec.  For now Solaris
                 * and Windows execs are somewhat supported, in all other cases
                 * we simply call exec and give it our "best shot"
                 */

                if (execMethod != null)
                {
                    p = execReflection(interp, argv, firstWord, argLen);
                }
                else if (Util.Unix)
                {
                    p = execUnix(interp, argv, firstWord, argLen);
                }
                else if (Util.Windows)
                {
                    p = execWin(interp, argv, firstWord, argLen);
                }
                else
                {
                    p = execDefault(interp, argv, firstWord, argLen);
                }


                //note to self : buffer reading should be done in
                //a separate thread and not by calling waitFor()
                //because a process that is waited for can block


                //Wait for the process to finish running,
                try
                {
                    p.Start();
                    p.WaitForExit();
                    exit = p.ExitCode;
                }
                catch (Exception e)
                {
                    throw new TclException(interp, "exception in exec process: " + e.Message);
                }


                //Make buffer for the results of the subprocess execution
                sbuf = new StringBuilder();

                //read data on stdout stream into  result buffer
                readStreamIntoBuffer(p.StandardOutput.BaseStream, sbuf);

                //if there is data on the stderr stream then append
                //this data onto the result StringBuffer
                //check for the special case where there is no error
                //data but the process returns an error result

                errorBytes = readStreamIntoBuffer(p.StandardError.BaseStream, sbuf);

                if ((errorBytes == 0) && (exit != 0))
                {
                    sbuf.Append("child process exited abnormally");
                }

                //If the last character of the result buffer is a newline, then
                //remove the newline character (the newline would just confuse
                //things).  Finally, we set pass the result to the interpreter.



                // Tcl supports lots of child status conditions.
                // Unfortunately, we can only find the child's
                // exit status using the Java API

                if (exit != 0)
                {
                    TclObject childstatus = TclList.NewInstance();
                    TclList.Append(interp, childstatus, TclString.NewInstance("CHILDSTATUS"));

                    // We don't know how to find the child's pid
                    TclList.Append(interp, childstatus, TclString.NewInstance("?PID?"));

                    TclList.Append(interp, childstatus, TclInteger.NewInstance(exit));

                    interp.SetErrorCode(childstatus);
                }

                //when the subprocess writes to its stderr stream or returns
                //a non zero result we generate an error
                if ((exit != 0) || (errorBytes != 0))
                {
                    throw new TclException(interp, sbuf.ToString());
                }

                //otherwise things went well so set the result
                interp.SetResult(sbuf.ToString());
            }
            catch (IOException e)
            {
                //if exec fails we end up catching the exception here


                throw new TclException(interp, "couldn't execute \"" + argv[firstWord].ToString() + "\": no such file or directory");
            }
            catch (System.Threading.ThreadInterruptedException e)
            {
                /*
                 * Do Nothing...
                 */
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #19
0
        private static void getAndStoreStatData(Interp interp, string fileName, string varName)
        {
            FileInfo fileObj = FileUtil.getNewFileObj(interp, fileName);

            bool tmpBool;

            if (File.Exists(fileObj.FullName))
            {
                tmpBool = true;
            }
            else
            {
                tmpBool = Directory.Exists(fileObj.FullName);
            }
            if (!tmpBool)
            {
                throw new TclPosixException(interp, TclPosixException.ENOENT, true, "could not read \"" + fileName + "\"");
            }

            try
            {
                int       mtime    = getMtime(interp, fileName, fileObj);
                TclObject mtimeObj = TclInteger.NewInstance(mtime);
                TclObject atimeObj = TclInteger.NewInstance(mtime);
                TclObject ctimeObj = TclInteger.NewInstance(mtime);
                interp.SetVar(varName, "atime", atimeObj, 0);
                interp.SetVar(varName, "ctime", ctimeObj, 0);
                interp.SetVar(varName, "mtime", mtimeObj, 0);
            }
            catch (System.Security.SecurityException e)
            {
                throw new TclException(interp, e.Message);
            }
            catch (TclException e)
            {
                throw new TclException(interp, "can't set \"" + varName + "(dev)\": variable isn't array");
            }

            try
            {
                TclObject sizeObj = TclInteger.NewInstance((int)SupportClass.FileLength(fileObj));
                interp.SetVar(varName, "size", sizeObj, 0);
            }
            catch (System.Exception e)
            {
                // Do nothing.
            }

            try
            {
                TclObject typeObj = TclString.NewInstance(getType(interp, fileName, fileObj));
                interp.SetVar(varName, "type", typeObj, 0);
            }
            catch (System.Exception e)
            {
            }

            try
            {
                TclObject uidObj = TclBoolean.newInstance(isOwner(interp, fileObj));
                interp.SetVar(varName, "uid", uidObj, 0);
            }
            catch (TclException e)
            {
                // Do nothing.
            }
        }
Пример #20
0
        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            int      i;
            Notifier notifier = (Notifier)interp.GetNotifier();
            Object   info;

            if (_assocData == null)
            {
                // Create the "after" information associated for this interpreter, if it doesn't already exist.
                _assocData = (AfterAssocData)interp.GetAssocData("tclAfter");
                if (_assocData == null)
                {
                    _assocData = new AfterAssocData(this);
                    interp.SetAssocData("tclAfter", _assocData);
                }
            }
            if (argv.Length < 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "option ?arg arg ...?");
            }
            // First lets see if the command was passed a number as the first argument.
            bool isNumber = false;
            int  ms       = 0;

            if (argv[1].InternalRep is TclInteger)
            {
                ms       = TclInteger.Get(interp, argv[1]);
                isNumber = true;
            }
            else
            {
                string s = argv[1].ToString();
                if (s.Length > 0 && char.IsDigit(s[0]))
                {
                    ms       = TclInteger.Get(interp, argv[1]);
                    isNumber = true;
                }
            }
            if (isNumber)
            {
                if (ms < 0)
                {
                    ms = 0;
                }
                if (argv.Length == 2)
                {
                    // Sleep for at least the given milliseconds and return.
                    long endTime = DateTime.Now.Ticks / 10000 + ms;
                    while (true)
                    {
                        try
                        {
                            Thread.Sleep(ms);
                            return(TCL.CompletionCode.RETURN);
                        }
                        catch (ThreadInterruptedException e)
                        {
                            // We got interrupted. Sleep again if we havn't slept long enough yet.
                            long sysTime = System.DateTime.Now.Ticks / 10000;
                            if (sysTime >= endTime)
                            {
                                return(TCL.CompletionCode.RETURN);
                            }
                            ms = (int)(endTime - sysTime);
                            continue;
                        }
                    }
                }
                TclObject cmd = GetCmdObject(argv);
                cmd.Preserve();
                _assocData.LastAfterId++;
                TimerInfo timerInfo = new TimerInfo(this, notifier, ms);
                timerInfo.Interp  = interp;
                timerInfo.Command = cmd;
                timerInfo.Id      = _assocData.LastAfterId;
                _assocData.Handlers.Add(timerInfo);
                interp.SetResult("after#" + timerInfo.Id);
                return(TCL.CompletionCode.RETURN);
            }

            // If it's not a number it must be a subcommand.
            int index;

            try { index = TclIndex.Get(interp, argv[1], _validOpts, "option", 0); }
            catch (TclException e) { throw new TclException(interp, "bad argument \"" + argv[1] + "\": must be cancel, idle, info, or a number"); }

            switch (index)
            {
            case OPT_CANCEL:
                if (argv.Length < 3)
                {
                    throw new TclNumArgsException(interp, 2, argv, "id|command");
                }
                TclObject arg = GetCmdObject(argv);
                arg.Preserve();
                // Search the timer/idle handler by id or by command.
                info = null;
                for (i = 0; i < _assocData.Handlers.Count; i++)
                {
                    Object obj = _assocData.Handlers[i];
                    if (obj is TimerInfo)
                    {
                        TclObject cmd = ((TimerInfo)obj).Command;
                        if (cmd == arg || cmd.ToString().Equals(arg.ToString()))
                        {
                            info = obj;
                            break;
                        }
                    }
                    else
                    {
                        TclObject cmd = ((IdleInfo)obj).Command;
                        if (cmd == arg || cmd.ToString().Equals(arg.ToString()))
                        {
                            info = obj;
                            break;
                        }
                    }
                }
                if (info == null)
                {
                    info = GetAfterEvent(arg.ToString());
                }
                arg.Release();
                // Cancel the handler.
                if (info != null)
                {
                    if (info is TimerInfo)
                    {
                        ((TimerInfo)info).Cancel();
                        ((TimerInfo)info).Command.Release();
                    }
                    else
                    {
                        ((IdleInfo)info).Cancel();
                        ((IdleInfo)info).Command.Release();
                    }
                    SupportClass.VectorRemoveElement(_assocData.Handlers, info);
                }
                break;

            case OPT_IDLE:
                if (argv.Length < 3)
                {
                    throw new TclNumArgsException(interp, 2, argv, "script script ...");
                }
                TclObject cmd2 = GetCmdObject(argv);
                cmd2.Preserve();
                _assocData.LastAfterId++;
                IdleInfo idleInfo = new IdleInfo(this, notifier);
                idleInfo.Interp  = interp;
                idleInfo.Command = cmd2;
                idleInfo.Id      = _assocData.LastAfterId;
                _assocData.Handlers.Add(idleInfo);
                interp.SetResult("after#" + idleInfo.Id);
                break;

            case OPT_INFO:
                if (argv.Length == 2)
                {
                    // No id is given. Return a list of current after id's.
                    TclObject list = TclList.NewInstance();
                    for (i = 0; i < _assocData.Handlers.Count; i++)
                    {
                        int    id;
                        Object obj = _assocData.Handlers[i];
                        if (obj is TimerInfo)
                        {
                            id = ((TimerInfo)obj).Id;
                        }
                        else
                        {
                            id = ((IdleInfo)obj).Id;
                        }
                        TclList.Append(interp, list, TclString.NewInstance("after#" + id));
                    }
                    interp.ResetResult();
                    interp.SetResult(list);
                    return(TCL.CompletionCode.RETURN);
                }
                if (argv.Length != 3)
                {
                    throw new TclNumArgsException(interp, 2, argv, "?id?");
                }
                // Return command and type of the given after id.
                info = GetAfterEvent(argv[2].ToString());
                if (info == null)
                {
                    throw new TclException(interp, "event \"" + argv[2] + "\" doesn't exist");
                }
                TclObject list2 = TclList.NewInstance();
                TclList.Append(interp, list2, ((info is TimerInfo) ? ((TimerInfo)info).Command : ((IdleInfo)info).Command));
                TclList.Append(interp, list2, TclString.NewInstance((info is TimerInfo) ? "timer" : "idle"));
                interp.ResetResult();
                interp.SetResult(list2);
                break;
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #21
0
        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            interp._errorCode = null;
            interp._errorInfo = null;
            TCL.CompletionCode returnCode;
            int i;

            /*
             * Note: returnCode is the value given by the -code option. Don't
             * confuse this value with the compCode variable of the
             * TclException thrown by this method, which is always TCL.CompletionCode.RETURN.
             */

            returnCode = TCL.CompletionCode.OK;
            for (i = 1; i < argv.Length - 1; i += 2)
            {
                if (argv[i].ToString().Equals("-code"))
                {
                    if (argv[i + 1].ToString().Equals("ok"))
                    {
                        returnCode = TCL.CompletionCode.OK;
                    }
                    else
                    {
                        if (argv[i + 1].ToString().Equals("error"))
                        {
                            returnCode = TCL.CompletionCode.ERROR;
                        }
                        else
                        {
                            if (argv[i + 1].ToString().Equals("return"))
                            {
                                returnCode = TCL.CompletionCode.RETURN;
                            }
                            else
                            {
                                if (argv[i + 1].ToString().Equals("break"))
                                {
                                    returnCode = TCL.CompletionCode.BREAK;
                                }
                                else
                                {
                                    if (argv[i + 1].ToString().Equals("continue"))
                                    {
                                        returnCode = TCL.CompletionCode.CONTINUE;
                                    }
                                    else
                                    {
                                        try
                                        {
                                            returnCode = (TCL.CompletionCode)TclInteger.Get(interp, argv[i + 1]);
                                        }
                                        catch (TclException e)
                                        {
                                            throw new TclException(interp, "bad completion code \"" + argv[i + 1] + "\": must be ok, error, return, break, " + "continue, or an integer");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (argv[i].ToString().Equals("-errorcode"))
                    {
                        interp._errorCode = argv[i + 1].ToString();
                    }
                    else
                    {
                        if (argv[i].ToString().Equals("-errorinfo"))
                        {
                            interp._errorInfo = argv[i + 1].ToString();
                        }
                        else
                        {
                            throw new TclException(interp, "bad option \"" + argv[i] + "\": must be -code, -errorcode, or -errorinfo");
                        }
                    }
                }
            }
            if (i != argv.Length)
            {
                interp.SetResult(argv[argv.Length - 1]);
            }

            interp._returnCode = returnCode;
            throw new TclException(TCL.CompletionCode.RETURN);
        }
Пример #22
0
        /// <summary> This procedure is invoked to process the "scan" Tcl command.
        /// See the user documentation for details on what it does.
        ///
        /// Each iteration of the cmdProc compares the scanArr's current index to
        /// the frmtArr's index.  If the chars are equal then the indicies are
        /// incremented.  If a '%' is found in the frmtArr, the formatSpecifier
        /// is parced from the frmtArr, the corresponding value is extracted from
        /// the scanArr, and that value is set in the Tcl Interp.
        ///
        /// If the chars are not equal, or the conversion fails, the boolean
        /// scanArrDone is set to true, indicating the scanArr is not to be
        /// parced and no new values are to be set.  However the frmtArr is still
        /// parced because of the priority of error messages.  In the C version
        /// of Tcl, bad format specifiers throw errors before incorrect argument
        /// input or other scan errors.  Thus we need to parce the entire frmtArr
        /// to verify correct formating.  This is dumb and inefficient but it is
        /// consistent w/ the current C-version of Tcl.
        /// </summary>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            if (argv.Length < 3)
            {
                throw new TclNumArgsException(interp, 1, argv, "string format ?varName varName ...?");
            }
            ;

            StrtoulResult strul; // Return value for parcing the scanArr when
            // extracting integers/longs
            StrtodResult strd;

            ;                  // Return value for parcing the scanArr when
            // extracting doubles
            char[] scanArr;    // Array containing parce info
            char[] frmtArr;    // Array containing info on how to
            // parse the scanArr
            int  scanIndex;    // Index into the scan array
            int  frmtIndex;    // Index into the frmt array
            int  tempIndex;    // Temporary index holder
            int  argIndex;     // Index into the current arg
            int  width;        // Stores the user specified result width
            int  base_;        // Base of the integer being converted
            int  numUnMatched; // Number of fields actually set.
            int  numMatched;   // Number of fields actually matched.
            int  negateScan;   // Mult by result, set to -1 if true
            int  i;            // Generic variable
            char ch;           // Generic variable
            bool cont;         // Used in loops to indicate when to stop
            bool scanOK;       // Set to false if strtoul/strtod fails
            bool scanArrDone;  // Set to false if strtoul/strtod fails
            bool widthFlag;    // True is width is specified
            bool discardFlag;  // If a "%*" is in the formatString dont

            // write output to arg


            scanArr = argv[1].ToString().ToCharArray();

            frmtArr     = argv[2].ToString().ToCharArray();
            width       = base_ = numMatched = numUnMatched = 0;
            scanIndex   = frmtIndex = 0;
            scanOK      = true;
            scanArrDone = false;
            argIndex    = 3;

            // Skip all (if any) of the white space before getting to a char

            frmtIndex = skipWhiteSpace(frmtArr, frmtIndex);

            // Search through the frmtArr.  If the next char is a '%' parse the
            // next chars and determine the type (if any) of the format specifier.
            // If the scanArr has been fully searched, do nothing but incerment
            // "numUnMatched".  The reason to continue the frmtArr search is for
            // consistency in output.  Previously scan format errors were reported
            // before arg input mismatch, so this maintains the same level of error
            // checking.

            while (frmtIndex < frmtArr.Length)
            {
                discardFlag = widthFlag = false;
                negateScan  = 1;
                cont        = true;

                // Parce the format array and read in the correct value from the
                // scan array.  When the correct value is retrieved, set the
                // variable (from argv) in the interp.

                if (frmtArr[frmtIndex] == '%')
                {
                    frmtIndex++;
                    checkOverFlow(interp, frmtArr, frmtIndex);

                    // Two '%'s in a row, do nothing...

                    if (frmtArr[frmtIndex] == '%')
                    {
                        frmtIndex++;
                        scanIndex++;
                        continue;
                    }

                    // Check for a discard field flag

                    if (frmtArr[frmtIndex] == '*')
                    {
                        discardFlag = true;
                        frmtIndex++;
                        checkOverFlow(interp, frmtArr, frmtIndex);
                    }

                    // Check for a width field and accept the 'h', 'l', 'L'
                    // characters, but do nothing with them.
                    //
                    // Note: The order of the width specifier and the other
                    // chars is unordered, so we need to iterate until all
                    // of the specifiers are identified.

                    while (cont)
                    {
                        cont = false;

                        switch (frmtArr[frmtIndex])
                        {
                        case 'h':
                        case 'l':
                        case 'L':
                        {
                            // Just ignore these values

                            frmtIndex++;
                            cont = true;
                            break;
                        }

                        default:
                        {
                            if (System.Char.IsDigit(frmtArr[frmtIndex]))
                            {
                                strul     = Util.Strtoul(new string(frmtArr), frmtIndex, base_);
                                frmtIndex = strul.Index;
                                width     = (int)strul.value;
                                widthFlag = true;
                                cont      = true;
                            }
                        }
                        break;
                        }
                        checkOverFlow(interp, frmtArr, frmtIndex);
                    }

                    // On all conversion specifiers except 'c', move the
                    // scanIndex to the next non-whitespace.

                    ch = frmtArr[frmtIndex];
                    if ((ch != 'c') && (ch != '[') && !scanArrDone)
                    {
                        scanIndex = skipWhiteSpace(scanArr, scanIndex);
                    }
                    if (scanIndex >= scanArr.Length)
                    {
                        scanArrDone = true;
                    }

                    if ((scanIndex < scanArr.Length) && (ch != 'c') && (ch != '['))
                    {
                        // Since strtoul dosent take signed numbers, make the
                        // value positive and store the sign.

                        if (scanArr[scanIndex] == '-')
                        {
                            negateScan = -1;
                            scanIndex++;
                            width--;
                        }
                        else if (scanArr[scanIndex] == '+')
                        {
                            scanIndex++;
                            width--;
                        }

                        // The width+scanIndex might be greater than
                        // the scanArr so we need to re-adjust when this
                        // happens.

                        if (widthFlag && (width + scanIndex > scanArr.Length))
                        {
                            width = scanArr.Length - scanIndex;
                        }
                    }

                    if (scanIndex >= scanArr.Length)
                    {
                        scanArrDone = true;
                    }

                    // Foreach iteration we want strul and strd to be
                    // null since we error check on this case.

                    strul = null;
                    strd  = null;

                    switch (ch)
                    {
                    case 'd':
                    case 'o':
                    case 'x':
                    {
                        if (!scanArrDone)
                        {
                            if (ch == 'd')
                            {
                                base_ = 10;
                            }
                            else if (ch == 'o')
                            {
                                base_ = 8;
                            }
                            else
                            {
                                base_ = 16;
                            }

                            // If the widthFlag is set then convert only
                            // "width" characters to an ascii representation,
                            // else read in until the end of the integer.  The
                            // scanIndex is moved to the point where we stop
                            // reading in.

                            if (widthFlag)
                            {
                                strul = Util.Strtoul(new string(scanArr, 0, width + scanIndex), scanIndex, base_);
                            }
                            else
                            {
                                strul = Util.Strtoul(new string(scanArr), scanIndex, base_);
                            }
                            if (strul.errno != 0)
                            {
                                scanOK = false;
                                break;
                            }
                            scanIndex = strul.Index;

                            if (!discardFlag)
                            {
                                i = (int)strul.value * negateScan;
                                if (argIndex == argv.Length)
                                {
                                    numMatched--;
                                }
                                else
                                {
                                    testAndSetVar(interp, argv, argIndex++, TclInteger.NewInstance(i));
                                }
                            }
                        }
                        break;
                    }

                    case 'c':
                    {
                        if (widthFlag)
                        {
                            errorCharFieldWidth(interp);
                        }
                        if (!discardFlag && !scanArrDone)
                        {
                            testAndSetVar(interp, argv, argIndex++, TclInteger.NewInstance(scanArr[scanIndex++]));
                        }
                        break;
                    }

                    case 's':
                    {
                        if (!scanArrDone)
                        {
                            // If the widthFlag is set then read only "width"
                            // characters into the string, else read in until
                            // the first whitespace or endArr is found.  The
                            // scanIndex is moved to the point where we stop
                            // reading in.

                            tempIndex = scanIndex;
                            if (!widthFlag)
                            {
                                width = scanArr.Length;
                            }
                            for (i = 0; (scanIndex < scanArr.Length) && (i < width); i++)
                            {
                                ch = scanArr[scanIndex];
                                if ((ch == ' ') || (ch == '\n') || (ch == '\r') || (ch == '\t') || (ch == '\f'))
                                {
                                    break;
                                }
                                scanIndex++;
                            }

                            if (!discardFlag)
                            {
                                string str = new string(scanArr, tempIndex, scanIndex - tempIndex);
                                testAndSetVar(interp, argv, argIndex++, TclString.NewInstance(str));
                            }
                        }
                        break;
                    }

                    case 'e':
                    case 'f':
                    case 'g':
                    {
                        if (!scanArrDone)
                        {
                            // If the wisthFlag is set then read only "width"
                            // characters into the string, else read in until
                            // the first whitespace or endArr is found.  The
                            // scanIndex is moved to the point where we stop
                            // reading in.

                            if (widthFlag)
                            {
                                strd = Util.Strtod(new string(scanArr, 0, width + scanIndex), scanIndex);
                            }
                            else
                            {
                                strd = Util.Strtod(new string(scanArr), scanIndex);
                            }
                            if (strd.errno != 0)
                            {
                                scanOK = false;
                                break;
                            }
                            scanIndex = strd.index;

                            if (!discardFlag)
                            {
                                double d = strd.value * negateScan;
                                testAndSetVar(interp, argv, argIndex++, TclDouble.NewInstance(d));
                            }
                        }
                        break;
                    }

                    case '[':
                    {
                        bool   charMatchFound = false;
                        bool   charNotMatch   = false;
                        char[] tempArr;
                        int    startIndex;
                        int    endIndex;
                        string unmatched = "unmatched [ in format string";

                        if ((++frmtIndex) >= frmtArr.Length)
                        {
                            throw new TclException(interp, unmatched);
                        }

                        if (frmtArr[frmtIndex] == '^')
                        {
                            charNotMatch = true;
                            frmtIndex   += 2;
                        }
                        else
                        {
                            frmtIndex++;
                        }
                        tempIndex = frmtIndex - 1;

                        if (frmtIndex >= frmtArr.Length)
                        {
                            throw new TclException(interp, unmatched);
                        }

                        // Extract the list of chars for matching.

                        while (frmtArr[frmtIndex] != ']')
                        {
                            if ((++frmtIndex) >= frmtArr.Length)
                            {
                                throw new TclException(interp, unmatched);
                            }
                        }
                        tempArr = new string(frmtArr, tempIndex, frmtIndex - tempIndex).ToCharArray();

                        startIndex = scanIndex;
                        if (charNotMatch)
                        {
                            // Format specifier contained a '^' so interate
                            // until one of the chars in tempArr is found.

                            while (scanOK && !charMatchFound)
                            {
                                if (scanIndex >= scanArr.Length)
                                {
                                    scanOK = false;
                                    break;
                                }
                                for (i = 0; i < tempArr.Length; i++)
                                {
                                    if (tempArr[i] == scanArr[scanIndex])
                                    {
                                        charMatchFound = true;
                                        break;
                                    }
                                }
                                if (widthFlag && ((scanIndex - startIndex) >= width))
                                {
                                    break;
                                }
                                if (!charMatchFound)
                                {
                                    scanIndex++;
                                }
                            }
                        }
                        else
                        {
                            // Iterate until the char in the scanArr is not
                            // in the tempArr.

                            charMatchFound = true;
                            while (scanOK && charMatchFound)
                            {
                                if (scanIndex >= scanArr.Length)
                                {
                                    scanOK = false;
                                    break;
                                }
                                charMatchFound = false;
                                for (i = 0; i < tempArr.Length; i++)
                                {
                                    if (tempArr[i] == scanArr[scanIndex])
                                    {
                                        charMatchFound = true;
                                        break;
                                    }
                                }
                                if (widthFlag && (scanIndex - startIndex) >= width)
                                {
                                    break;
                                }
                                if (charMatchFound)
                                {
                                    scanIndex++;
                                }
                            }
                        }

                        // Indicates nothing was found.

                        endIndex = scanIndex - startIndex;
                        if (endIndex <= 0)
                        {
                            scanOK = false;
                            break;
                        }

                        if (!discardFlag)
                        {
                            string str = new string(scanArr, startIndex, endIndex);
                            testAndSetVar(interp, argv, argIndex++, TclString.NewInstance(str));
                        }
                        break;
                    }

                    default:
                    {
                        errorBadField(interp, ch);
                    }
                    break;
                    }

                    // As long as the scan was successful (scanOK), the format
                    // specifier did not contain a '*' (discardFlag), and
                    // we are not at the end of the scanArr (scanArrDone);
                    // increment the num of vars set in the interp.  Otherwise
                    // increment the number of valid format specifiers.

                    if (scanOK && !discardFlag && !scanArrDone)
                    {
                        numMatched++;
                    }
                    else if ((scanArrDone || !scanOK) && !discardFlag)
                    {
                        numUnMatched++;
                    }
                    frmtIndex++;
                }
                else if (scanIndex < scanArr.Length && scanArr[scanIndex] == frmtArr[frmtIndex])
                {
                    // No '%' was found, but the characters matched

                    scanIndex++;
                    frmtIndex++;
                }
                else
                {
                    // No '%' found and the characters int frmtArr & scanArr
                    // did not match.

                    frmtIndex++;
                }
            }

            // The numMatched is the return value: a count of the num of vars set.
            // While the numUnMatched is the number of formatSpecifiers that
            // passed the parsing stage, but did not match anything in the scanArr.

            if ((numMatched + numUnMatched) != (argv.Length - 3))
            {
                errorDiffVars(interp);
            }
            interp.SetResult(TclInteger.NewInstance(numMatched));
            return(TCL.CompletionCode.RETURN);
        }
Пример #23
0
        /// <summary> Compares the order of two items in the array.
        ///
        /// </summary>
        /// <param name="obj1">first item.
        /// </param>
        /// <param name="obj2">second item.
        /// </param>
        /// <returns> 0 if they are equal, 1 if obj1 > obj2, -1 otherwise.
        ///
        /// </returns>
        /// <exception cref=""> TclException if an error occurs during sorting.
        /// </exception>
        private int compare(TclObject obj1, TclObject obj2)
        {
            int index;
            int code = 0;

            if (sortIndex != -1)
            {
                // The "-index" option was specified.  Treat each object as a
                // list, extract the requested element from each list, and
                // compare the elements, not the lists.  The special index "end"
                // is signaled here with a negative index (other than -1).

                TclObject obj;
                if (sortIndex < -1)
                {
                    index = TclList.getLength(sortInterp, obj1) - 1;
                }
                else
                {
                    index = sortIndex;
                }

                obj = TclList.index(sortInterp, obj1, index);
                if (obj == null)
                {
                    throw new TclException(sortInterp, "element " + index + " missing from sublist \"" + obj1 + "\"");
                }
                obj1 = obj;

                if (sortIndex < -1)
                {
                    index = TclList.getLength(sortInterp, obj2) - 1;
                }
                else
                {
                    index = sortIndex;
                }

                obj = TclList.index(sortInterp, obj2, index);
                if (obj == null)
                {
                    throw new TclException(sortInterp, "element " + index + " missing from sublist \"" + obj2 + "\"");
                }
                obj2 = obj;
            }

            switch (sortMode)
            {
            case ASCII:
                // ATK C# CompareTo use option
                // similar to -dictionary but a > A
                code = System.Globalization.CultureInfo.InvariantCulture.CompareInfo.Compare(obj1.ToString(), obj2.ToString(), System.Globalization.CompareOptions.Ordinal);
                // code = obj1.ToString().CompareTo(obj2.ToString());
                break;

            case DICTIONARY:

                code = doDictionary(obj1.ToString(), obj2.ToString());
                break;

            case INTEGER:
                try
                {
                    int int1 = TclInteger.Get(sortInterp, obj1);
                    int int2 = TclInteger.Get(sortInterp, obj2);

                    if (int1 > int2)
                    {
                        code = 1;
                    }
                    else if (int2 > int1)
                    {
                        code = -1;
                    }
                }
                catch (TclException e1)
                {
                    sortInterp.AddErrorInfo("\n    (converting list element from string to integer)");
                    throw e1;
                }
                break;

            case REAL:
                try
                {
                    double f1 = TclDouble.Get(sortInterp, obj1);
                    double f2 = TclDouble.Get(sortInterp, obj2);

                    if (f1 > f2)
                    {
                        code = 1;
                    }
                    else if (f2 > f1)
                    {
                        code = -1;
                    }
                }
                catch (TclException e2)
                {
                    sortInterp.AddErrorInfo("\n    (converting list element from string to real)");
                    throw e2;
                }
                break;

            case COMMAND:
                StringBuilder sbuf = new StringBuilder(sortCommand);

                Util.appendElement(sortInterp, sbuf, obj1.ToString());

                Util.appendElement(sortInterp, sbuf, obj2.ToString());
                try
                {
                    sortInterp.Eval(sbuf.ToString(), 0);
                }
                catch (TclException e3)
                {
                    sortInterp.AddErrorInfo("\n    (user-defined comparison command)");
                    throw e3;
                }

                try
                {
                    code = TclInteger.Get(sortInterp, sortInterp.GetResult());
                }
                catch (TclException e)
                {
                    sortInterp.ResetResult();
                    TclException e4 = new TclException(sortInterp, "comparison command returned non-numeric result");
                    throw e4;
                }
                break;


            default:

                throw new TclRuntimeError("Unknown sortMode " + sortMode);
            }

            if (sortIncreasing)
            {
                return(code);
            }
            else
            {
                return(-code);
            }
        }
Пример #24
0
        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            bool nocase  = false;
            bool indices = false;

            try
            {
                int i = 1;

                while (argv[i].ToString().StartsWith("-"))
                {
                    int index = TclIndex.Get(interp, argv[i], validOpts, "switch", 0);
                    i++;
                    switch (index)
                    {
                    case OPT_INDICES:
                    {
                        indices = true;
                        break;
                    }

                    case OPT_NOCASE:
                    {
                        nocase = true;
                        break;
                    }

                    case OPT_LAST:
                    {
                        goto opts_brk;
                    }
                    }
                }

opts_brk:
                ;


                TclObject exp = TclString.NewInstance(argv[i++].ToString().Replace("\\d", "[0-9]"));

                string inString = argv[i++].ToString();

                int matches = argv.Length - i;

                Regexp r = TclRegexp.compile(interp, exp, nocase);

                int[] args    = new int[matches * 2];
                bool  matched = r.match(inString, args);
                if (matched)
                {
                    for (int match = 0; i < argv.Length; i++)
                    {
                        TclObject obj;

                        int start = args[match++];
                        int end   = args[match++];
                        if (indices)
                        {
                            if (end >= 0)
                            {
                                end--;
                            }
                            obj = TclList.NewInstance();
                            TclList.Append(interp, obj, TclInteger.NewInstance(start));
                            TclList.Append(interp, obj, TclInteger.NewInstance(end));
                        }
                        else
                        {
                            string range = (start >= 0) ? inString.Substring(start, (end) - (start)) : "";
                            obj = TclString.NewInstance(range);
                        }
                        try
                        {
                            interp.SetVar(argv[i].ToString(), obj, 0);
                        }
                        catch (TclException e)
                        {
                            throw new TclException(interp, "couldn't set variable \"" + argv[i] + "\"");
                        }
                    }
                }
                interp.SetResult(matched);
            }
            catch (System.IndexOutOfRangeException e)
            {
                throw new TclNumArgsException(interp, 1, argv, "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #25
0
        /// <summary> This procedure is invoked to process the "read" Tcl command.
        /// See the user documentation for details on what it does.
        ///
        /// </summary>
        /// <param name="interp">the current interpreter.
        /// </param>
        /// <param name="argv">command arguments.
        /// </param>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            Channel chan;                // The channel being operated on this
            // method
            int       i      = 1;        // Index to the next arg in argv
            int       toRead = 0;        // Number of bytes or chars to read from channel
            int       charactersRead;    // Number of bytes or chars read from channel
            bool      readAll   = true;  // If true read-all else toRead
            bool      noNewline = false; // If true, strip the newline if there
            TclObject result;


            if ((argv.Length != 2) && (argv.Length != 3))
            {
                errorWrongNumArgs(interp, argv[0].ToString());
            }


            if (argv[i].ToString().Equals("-nonewline"))
            {
                noNewline = true;
                i++;
            }

            if (i == argv.Length)
            {
                errorWrongNumArgs(interp, argv[0].ToString());
            }


            chan = TclIO.getChannel(interp, argv[i].ToString());
            if (chan == null)
            {
                throw new TclException(interp, "can not find channel named \"" + argv[i].ToString() + "\"");
            }

            // Consumed channel name.

            i++;

            // Compute how many bytes or chars to read, and see whether the final
            // noNewline should be dropped.

            if (i < argv.Length)
            {
                string arg = argv[i].ToString();

                if (System.Char.IsDigit(arg[0]))
                {
                    toRead  = TclInteger.Get(interp, argv[i]);
                    readAll = false;
                }
                else if (arg.Equals("nonewline"))
                {
                    noNewline = true;
                }
                else
                {
                    throw new TclException(interp, "bad argument \"" + arg + "\": should be \"nonewline\"");
                }
            }

            try
            {
                if ((System.Object)chan.Encoding == null)
                {
                    result = TclByteArray.NewInstance();
                }
                else
                {
                    result = TclString.NewInstance(new StringBuilder(64));
                }
                if (readAll)
                {
                    charactersRead = chan.read(interp, result, TclIO.READ_ALL, 0);

                    // If -nonewline was specified, and we have not hit EOF
                    // and the last char is a "\n", then remove it and return.

                    if (noNewline)
                    {
                        string inStr = result.ToString();
                        if ((charactersRead > 0) && (inStr[charactersRead - 1] == '\n'))
                        {
                            interp.SetResult(inStr.Substring(0, ((charactersRead - 1)) - (0)));
                            return(TCL.CompletionCode.RETURN);
                        }
                    }
                }
                else
                {
                    // FIXME: Bug here, the -nonewline flag must be respected
                    // when reading a set number of bytes
                    charactersRead = chan.read(interp, result, TclIO.READ_N_BYTES, toRead);
                }

                /*
                 * // FIXME: Port this -nonewline logic from the C code.
                 * if (charactersRead < 0) {
                 * Tcl_ResetResult(interp);
                 * Tcl_AppendResult(interp, "error reading \"", name, "\": ",
                 * Tcl_PosixError(interp), (char *) NULL);
                 * Tcl_DecrRefCount(resultPtr);
                 * return TCL_ERROR;
                 * }
                 *
                 * // If requested, remove the last newline in the channel if at EOF.
                 *
                 * if ((charactersRead > 0) && (newline != 0)) {
                 * char *result;
                 * int length;
                 *
                 * result = Tcl_GetStringFromObj(resultPtr, length);
                 * if (result[length - 1] == '\n') {
                 * Tcl_SetObjLength(resultPtr, length - 1);
                 * }
                 * }
                 *
                 */

                interp.SetResult(result);
            }
            catch (IOException e)
            {
                throw new TclRuntimeError("ReadCmd.cmdProc() Error: IOException when reading " + chan.ChanName);
            }
            return(TCL.CompletionCode.RETURN);
        }
Пример #26
0
        private const int GENERIC       = 4; // Floating or exponential,
        // depending on exponent. %g

        /// <summary> This procedure is invoked to process the "format" Tcl command.
        /// See the user documentation for details on what it does.
        ///
        /// The first argument to the cmdProc is the formatString.  The cmdProc
        /// simply copies all the chars into the sbuf until a '%' is found.  At
        /// this point the cmdProc parces the formatString and determines the
        /// format parameters.  The parcing of the formatString can be broken into
        /// six possible phases:
        ///
        /// Phase 0 - Simply Print:            If the next char is %
        /// Phase 1 - XPG3 Position Specifier: If the format [1-n]$ is used
        /// Phase 2 - A Set of Flags:          One or more of the following + -
        /// [space] 0 #
        /// Phase 3 - A Minimun Field Width    Either [integer] or *
        /// Phase 4 - A Precision              If the format .[integer] or .*
        /// Phase 5 - A Length Modifier        If h is present
        /// Phase 6 - A Conversion Character   If one of the following is used
        /// d u i o x X c s f E g G
        ///
        /// Any phase can skip ahead one or more phases, but are not allowed
        /// to move back to previous phases.  Once the parameters are determined
        /// the cmdProc calls one of three private methods that returns a fully
        /// formatted string.  This loop occurs for ever '%' in the formatString.
        /// </summary>

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] argv)
        {
            StringBuilder sbuf;  // Stores the return value of the parsed
            // format string
            StrtoulResult stoul; // A return object to the strtoul call

            char[] format;       // The format argument is converted to a char
            // array and manipulated as such
            int    phase;        // Stores the current phase of the parsing
            int    width;        // Minimum field width
            int    precision;    // Field precision from field specifier
            int    fmtFlags;     // Used to store the format flags ( #,+,etc)
            int    argIndex;     // Index of argument to substitute next.
            int    fmtIndex;     // Used to locate end of the format fields.
            int    endIndex;     // Used to locate end of numerical fields.
            int    intValue;     // Generic storage variable
            long   lngValue;     // Store the TclInteger.get() result
            double dblValue;     // Store the TclDouble.get() result
            bool   noPercent;    // Special case for speed:  indicates there's
            // no field specifier, just a string to copy.
            bool xpgSet;         // Indicates that xpg has been used for the
            // particular format of the main while loop
            bool gotXpg;         // True means that an XPG3 %n$-style
            // specifier has been seen.
            bool gotSequential;  // True means that a regular sequential
            // (non-XPG3) conversion specifier has
            // been seen.
            bool useShort;     // Value to be printed is short
            // (half word).
            bool precisionSet; // Used for f, e, and E conversions
            bool cont;         // Used for phase 3

            if (argv.Length < 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "formatString ?arg arg ...?");
            }

            argIndex = 2;
            fmtIndex = 0;
            gotXpg   = gotSequential = false;

            format = argv[1].ToString().ToCharArray();
            sbuf   = new StringBuilder();

            // So, what happens here is to scan the format string one % group
            // at a time, making many individual appends to the StringBuffer.

            while (fmtIndex < format.Length)
            {
                fmtFlags  = phase = width = 0;
                noPercent = true;
                xpgSet    = precisionSet = useShort = false;
                precision = -1;

                // Append all characters to sbuf that are not used for the
                // format specifier.


                if (format[fmtIndex] != '%')
                {
                    int i;
                    for (i = fmtIndex; (i < format.Length); i++)
                    {
                        if (format[i] == '%')
                        {
                            noPercent = false;
                            break;
                        }
                    }
                    sbuf.Append(new string(format, fmtIndex, i - fmtIndex));
                    fmtIndex = i;
                    if (noPercent)
                    {
                        break;
                    }
                }

                // If true, then a % has been indicated but we are at the end
                // of the format string.  Call function to throw exception.

                if (fmtIndex + 1 >= format.Length)
                {
                    errorEndMiddle(interp);
                }

                // Phase 0:
                // Check for %%.  If true then simply write a single '%'
                // to the list.

                checkOverFlow(interp, format, fmtIndex + 1);
                if (format[fmtIndex + 1] == '%')
                {
                    sbuf.Append("%");
                    fmtIndex += 2;
                    // Re-enter the loop

                    continue;
                }

                fmtIndex++;
                checkOverFlow(interp, format, fmtIndex);
                if (System.Char.IsDigit(format[fmtIndex]))
                {
                    // Parce the format array looking for the end of
                    // the number.

                    stoul    = strtoul(format, fmtIndex);
                    intValue = (int)stoul.value;
                    endIndex = stoul.Index;

                    if (format[endIndex] == '$')
                    {
                        if (intValue == 0)
                        {
                            errorBadIndex(interp, true);
                        }

                        // Phase 1:
                        // Check for an XPG3-style %n$ specification.
                        // Note: there must not be a mixture of XPG3
                        // specs and non-XPG3 specs in the same format string.

                        if (gotSequential)
                        {
                            errorMixedXPG(interp);
                        }
                        gotXpg   = true;
                        xpgSet   = true;
                        phase    = 2;
                        fmtIndex = endIndex + 1;
                        argIndex = intValue + 1;
                        if ((argIndex < 2) || (argIndex >= argv.Length))
                        {
                            errorBadIndex(interp, gotXpg);
                        }
                    }
                    else
                    {
                        // Phase 3:
                        // Format jumped straight to phase 3; Setting
                        // width field.  Again, verify that all format
                        // specifiers are sequential.

                        if (gotXpg)
                        {
                            errorMixedXPG(interp);
                        }
                        gotSequential = true;
                        if (format[fmtIndex] != '0')
                        {
                            fmtIndex = endIndex;
                            width    = intValue;
                            phase    = 4;
                        }
                    }
                }
                else
                {
                    if (gotXpg)
                    {
                        errorMixedXPG(interp);
                    }
                    gotSequential = true;
                }

                // Phase 2:
                // Setting the Format Flags.  At this point the phase value
                // can be either zero or three.  Anything greater is an
                // incorrect format.

                if (phase < 3)
                {
                    checkOverFlow(interp, format, fmtIndex);
                    char ch = format[fmtIndex];
                    cont = true;
                    while (cont)
                    {
                        switch (ch)
                        {
                        case '-':
                        {
                            fmtFlags |= LEFT_JUSTIFY;
                            break;
                        }

                        case '#':
                        {
                            fmtFlags |= ALT_OUTPUT;
                            break;
                        }

                        case '0':
                        {
                            fmtFlags |= PAD_W_ZERO;
                            break;
                        }

                        case ' ':
                        {
                            fmtFlags |= SPACE_OR_SIGN;
                            break;
                        }

                        case '+':
                        {
                            fmtFlags |= SHOW_SIGN;
                            break;
                        }

                        default:
                        {
                            cont = false;
                        }
                        break;
                        }
                        if (cont)
                        {
                            fmtIndex++;
                            checkOverFlow(interp, format, fmtIndex);
                            ch = format[fmtIndex];
                        }
                    }
                    phase = 3;
                }

                // Phase 3:
                // Setting width field.  Partially redundant code from the
                // Phase 1 if/else statement, but this is made to run fast.

                checkOverFlow(interp, format, fmtIndex);
                if (System.Char.IsDigit(format[fmtIndex]))
                {
                    stoul    = strtoul(format, fmtIndex);
                    width    = (int)stoul.value;
                    fmtIndex = stoul.Index;
                }
                else if (format[fmtIndex] == '*')
                {
                    if (argv.Length > argIndex)
                    {
                        width = TclInteger.Get(interp, argv[argIndex]);
                        if (width < 0)
                        {
                            width     = -width;
                            fmtFlags |= LEFT_JUSTIFY;
                        }
                        argIndex++;
                        fmtIndex++;
                    }
                }

                // Phase 4:
                // Setting the precision field.

                checkOverFlow(interp, format, fmtIndex);
                if (format[fmtIndex] == '.')
                {
                    fmtIndex++;
                    checkOverFlow(interp, format, fmtIndex);
                    if (System.Char.IsDigit(format[fmtIndex]))
                    {
                        precisionSet = true;

                        stoul     = strtoul(format, fmtIndex);
                        precision = (int)stoul.value;
                        fmtIndex  = stoul.Index;
                    }
                    else if (format[fmtIndex] == '*')
                    {
                        if (argv.Length > argIndex)
                        {
                            precisionSet = true;
                            precision    = TclInteger.Get(interp, argv[argIndex]);
                            argIndex++;
                            fmtIndex++;
                            checkOverFlow(interp, format, fmtIndex);
                        }
                    }
                    else
                    {
                        // Format field had a '.' without an integer or '*'
                        // preceeding it  (eg  %2.d  or %2.-5d)

                        errorBadField(interp, format[fmtIndex]);
                    }
                }

                // Phase 5:
                // Setting the length modifier.

                if (format[fmtIndex] == 'h')
                {
                    fmtIndex++;
                    checkOverFlow(interp, format, fmtIndex);
                    useShort = true;
                }
                else if (format[fmtIndex] == 'l')
                {
                    fmtIndex++;
                    checkOverFlow(interp, format, fmtIndex);

                    // 'l' is ignored, but should still be processed.
                }

                if ((argIndex < 2) || (argIndex >= argv.Length))
                {
                    errorBadIndex(interp, gotXpg);
                }

                // Phase 6:
                // Setting conversion field.
                // At this point, variables are initialized as follows:
                //
                // width               The specified field width.  This is always
                //                         non-negative.  Zero is the default.
                // precision           The specified precision.  The default
                //                         is -1.
                // argIndex            The argument index from the argv array
                //                         for the appropriate arg.
                // fmtFlags            The format flags are set via bitwise
                //                         operations.  Below are the bits
                //                         and their meanings.

                //     ALT_OUTPUT          set if a '#' is present.
                //     SHOW_SIGN           set if a '+' is present.
                //     SPACE_OR_SIGN       set if a ' ' is present.
                //     LEFT_JUSTIFY        set if a '-' is present or if the
                //                           field width was negative.
                //     PAD_W_ZERO          set if a '0' is present

                string strValue = "";
                char   index    = format[fmtIndex];

                switch (index)
                {
                case 'u':
                case 'd':
                case 'o':
                case 'x':
                case 'X':
                case 'i':
                {
                    if (index == 'u')
                    {
                        // Since Java does not provide unsigned ints we need to
                        // make our own.  If the value is negative we need to
                        // clear out all of the leading bits from the 33rd bit
                        // and on.  The result is a long value equal to that
                        // of an unsigned int.

                        lngValue = (long)TclInteger.Get(interp, argv[argIndex]);
                        if (lngValue < 0)
                        {
                            lngValue = (lngValue << 32);
                            lngValue = (SupportClass.URShift(lngValue, 32));
                        }
                    }
                    else
                    {
                        fmtFlags |= SIGNED_VALUE;
                        lngValue  = (long)TclInteger.Get(interp, argv[argIndex]);
                    }

                    // If the useShort option has been selected, we need
                    // to clear all but the first 16 bits.

                    if (useShort)
                    {
                        lngValue = (lngValue << 48);
                        lngValue = (lngValue >> 48);
                    }

                    if (index == 'o')
                    {
                        sbuf.Append(cvtLngToStr(lngValue, width, precision, fmtFlags, 8, "01234567".ToCharArray(), "0"));
                    }
                    else if (index == 'x')
                    {
                        sbuf.Append(cvtLngToStr(lngValue, width, precision, fmtFlags, 16, "0123456789abcdef".ToCharArray(), "0x"));
                    }
                    else if (index == 'X')
                    {
                        sbuf.Append(cvtLngToStr(lngValue, width, precision, fmtFlags, 16, "0123456789ABCDEF".ToCharArray(), "0X"));
                    }
                    else
                    {
                        sbuf.Append(cvtLngToStr(lngValue, width, precision, fmtFlags, 10, "0123456789".ToCharArray(), ""));
                    }
                    break;
                }

                case 'c':
                {
                    intValue = 0;
                    char[] arr = new char[] { (char)TclInteger.Get(interp, argv[argIndex]) };
                    strValue = new string(arr);
                    sbuf.Append(cvtStrToStr(strValue, width, precision, fmtFlags));
                    break;
                }

                case 's':
                {
                    strValue = argv[argIndex].ToString();
                    sbuf.Append(cvtStrToStr(strValue, width, precision, fmtFlags));
                    break;
                }

                case 'f':
                {
                    dblValue = TclDouble.Get(interp, argv[argIndex]);
                    sbuf.Append(cvtDblToStr(dblValue, width, precision, fmtFlags, 10, "0123456789".ToCharArray(), "", FLOAT));
                    break;
                }

                case 'e':
                {
                    dblValue = TclDouble.Get(interp, argv[argIndex]);
                    sbuf.Append(cvtDblToStr(dblValue, width, precision, fmtFlags, 10, "e".ToCharArray(), "", EXP));
                    break;
                }

                case 'E':
                {
                    dblValue = TclDouble.Get(interp, argv[argIndex]);
                    sbuf.Append(cvtDblToStr(dblValue, width, precision, fmtFlags, 10, "E".ToCharArray(), "", EXP));
                    break;
                }

                case 'g':
                {
                    dblValue = TclDouble.Get(interp, argv[argIndex]);
                    sbuf.Append(cvtDblToStr(dblValue, width, precision, fmtFlags, 10, "e".ToCharArray(), "", GENERIC));
                    break;
                }

                case 'G':
                {
                    dblValue = TclDouble.Get(interp, argv[argIndex]);
                    sbuf.Append(cvtDblToStr(dblValue, width, precision, fmtFlags, 10, "E".ToCharArray(), "", GENERIC));
                    break;
                }

                default:
                {
                    errorBadField(interp, format[fmtIndex]);
                }
                break;
                }
                fmtIndex++;
                argIndex++;
            }
            interp.SetResult(sbuf.ToString());
            return(TCL.CompletionCode.RETURN);
        }
Пример #27
0
 public static TclObject Tcl_NewIntObj(int value)
 {
     return(TclInteger.NewInstance(value));
 }
Пример #28
0
        public TclObject get()
        {
            TclObject obj;
            TclToken  token;
            string    typeString;
            int       nextIndex;
            string    cmd;
            int       i;


            System.Diagnostics.Debug.WriteLine("Entered TclParse.get()");
            System.Diagnostics.Debug.WriteLine("numTokens is " + numTokens);

            obj = TclList.NewInstance();
            try
            {
                if (commentSize > 0)
                {
                    TclList.Append(interp, obj, TclString.NewInstance(new string(inString, commentStart, commentSize)));
                }
                else
                {
                    TclList.Append(interp, obj, TclString.NewInstance("-"));
                }

                if (commandStart >= (endIndex + 1))
                {
                    commandStart = endIndex;
                }
                cmd = new string(inString, commandStart, commandSize);
                TclList.Append(interp, obj, TclString.NewInstance(cmd));
                TclList.Append(interp, obj, TclInteger.NewInstance(numWords));

                for (i = 0; i < numTokens; i++)
                {
                    System.Diagnostics.Debug.WriteLine("processing token " + i);

                    token = tokenList[i];
                    switch (token.type)
                    {
                    case Parser.TCL_TOKEN_WORD:
                        typeString = "word";
                        break;

                    case Parser.TCL_TOKEN_SIMPLE_WORD:
                        typeString = "simple";
                        break;

                    case Parser.TCL_TOKEN_EXPAND_WORD:
                        typeString = "expand";
                        break;

                    case Parser.TCL_TOKEN_TEXT:
                        typeString = "text";
                        break;

                    case Parser.TCL_TOKEN_BS:
                        typeString = "backslash";
                        break;

                    case Parser.TCL_TOKEN_COMMAND:
                        typeString = "command";
                        break;

                    case Parser.TCL_TOKEN_VARIABLE:
                        typeString = "variable";
                        break;

                    default:
                        typeString = "??";
                        break;
                    }

                    System.Diagnostics.Debug.WriteLine("typeString is " + typeString);

                    TclList.Append(interp, obj, TclString.NewInstance(typeString));
                    TclList.Append(interp, obj, TclString.NewInstance(token.TokenString));
                    TclList.Append(interp, obj, TclInteger.NewInstance(token.numComponents));
                }
                nextIndex = commandStart + commandSize;
                TclList.Append(interp, obj, TclString.NewInstance(new string(inString, nextIndex, (endIndex - nextIndex))));
            }
            catch (TclException e)
            {
                // Do Nothing.
            }

            return(obj);
        }
Пример #29
0
 public static void Tcl_BackgroundError(Interp interp)
 {
     interp.SetErrorCode(TclInteger.NewInstance(TCL_ERROR));
     interp.AddErrorInfo("Background Error");
 }
Пример #30
0
        /*
         *-----------------------------------------------------------------------------
         *
         * cmdProc --
         *
         *      This procedure is invoked to process the "lsearch" Tcl command.
         *      See the user documentation for details on what it does.
         *
         * Results:
         *      None.
         *
         * Side effects:
         *      See the user documentation.
         *
         *-----------------------------------------------------------------------------
         */

        public TCL.CompletionCode CmdProc(Interp interp, TclObject[] objv)
        {
            int       mode         = GLOB;
            int       dataType     = ASCII;
            bool      isIncreasing = true;
            TclObject pattern;
            TclObject list;

            if (objv.Length < 3)
            {
                throw new TclNumArgsException(interp, 1, objv, "?options? list pattern");
            }

            for (int i = 1; i < objv.Length - 2; i++)
            {
                switch (TclIndex.Get(interp, objv[i], options, "option", 0))
                {
                case LSEARCH_ASCII:
                    dataType = ASCII;
                    break;

                case LSEARCH_DECREASING:
                    isIncreasing = false;
                    break;

                case LSEARCH_DICTIONARY:
                    dataType = DICTIONARY;
                    break;

                case LSEARCH_EXACT:
                    mode = EXACT;
                    break;

                case LSEARCH_INCREASING:
                    isIncreasing = true;
                    break;

                case LSEARCH_INTEGER:
                    dataType = INTEGER;
                    break;

                case LSEARCH_GLOB:
                    mode = GLOB;
                    break;

                case LSEARCH_REAL:
                    dataType = REAL;
                    break;

                case LSEARCH_REGEXP:
                    mode = REGEXP;
                    break;

                case LSEARCH_SORTED:
                    mode = SORTED;
                    break;
                }
            }

            // Make sure the list argument is a list object and get its length and
            // a pointer to its array of element pointers.

            TclObject[] listv = TclList.getElements(interp, objv[objv.Length - 2]);

            TclObject patObj       = objv[objv.Length - 1];
            string    patternBytes = null;
            int       patInt       = 0;
            double    patDouble    = 0.0;
            int       length       = 0;

            if (mode == EXACT || mode == SORTED)
            {
                switch (dataType)
                {
                case ASCII:
                case DICTIONARY:

                    patternBytes = patObj.ToString();
                    length       = patternBytes.Length;
                    break;

                case INTEGER:
                    patInt = TclInteger.Get(interp, patObj);
                    break;

                case REAL:
                    patDouble = TclDouble.Get(interp, patObj);
                    break;
                }
            }
            else
            {
                patternBytes = patObj.ToString();
                length       = patternBytes.Length;
            }

            // Set default index value to -1, indicating failure; if we find the
            // item in the course of our search, index will be set to the correct
            // value.

            int index = -1;

            if (mode == SORTED)
            {
                // If the data is sorted, we can do a more intelligent search.
                int match = 0;
                int lower = -1;
                int upper = listv.Length;
                while (lower + 1 != upper)
                {
                    int i = (lower + upper) / 2;
                    switch (dataType)
                    {
                    case ASCII:
                    {
                        string bytes = listv[i].ToString();
                        match = patternBytes.CompareTo(bytes);
                        break;
                    }

                    case DICTIONARY:
                    {
                        string bytes = listv[i].ToString();
                        match = DictionaryCompare(patternBytes, bytes);
                        break;
                    }

                    case INTEGER:
                    {
                        int objInt = TclInteger.Get(interp, listv[i]);
                        if (patInt == objInt)
                        {
                            match = 0;
                        }
                        else if (patInt < objInt)
                        {
                            match = -1;
                        }
                        else
                        {
                            match = 1;
                        }
                        break;
                    }

                    case REAL:
                    {
                        double objDouble = TclDouble.Get(interp, listv[i]);
                        if (patDouble == objDouble)
                        {
                            match = 0;
                        }
                        else if (patDouble < objDouble)
                        {
                            match = -1;
                        }
                        else
                        {
                            match = 1;
                        }
                        break;
                    }
                    }
                    if (match == 0)
                    {
                        // Normally, binary search is written to stop when it
                        // finds a match.  If there are duplicates of an element in
                        // the list, our first match might not be the first occurance.
                        // Consider:  0 0 0 1 1 1 2 2 2
                        // To maintain consistancy with standard lsearch semantics,
                        // we must find the leftmost occurance of the pattern in the
                        // list.  Thus we don't just stop searching here.  This
                        // variation means that a search always makes log n
                        // comparisons (normal binary search might "get lucky" with
                        // an early comparison).

                        index = i;
                        upper = i;
                    }
                    else if (match > 0)
                    {
                        if (isIncreasing)
                        {
                            lower = i;
                        }
                        else
                        {
                            upper = i;
                        }
                    }
                    else
                    {
                        if (isIncreasing)
                        {
                            upper = i;
                        }
                        else
                        {
                            lower = i;
                        }
                    }
                }
            }
            else
            {
                for (int i = 0; i < listv.Length; i++)
                {
                    bool match = false;
                    switch (mode)
                    {
                    case SORTED:
                    case EXACT:
                    {
                        switch (dataType)
                        {
                        case ASCII:
                        {
                            string bytes   = listv[i].ToString();
                            int    elemLen = bytes.Length;
                            if (length == elemLen)
                            {
                                match = bytes.Equals(patternBytes);
                            }
                            break;
                        }

                        case DICTIONARY:
                        {
                            string bytes = listv[i].ToString();
                            match = (DictionaryCompare(bytes, patternBytes) == 0);
                            break;
                        }

                        case INTEGER:
                        {
                            int objInt = TclInteger.Get(interp, listv[i]);
                            match = (objInt == patInt);
                            break;
                        }

                        case REAL:
                        {
                            double objDouble = TclDouble.Get(interp, listv[i]);
                            match = (objDouble == patDouble);
                            break;
                        }
                        }
                        break;
                    }

                    case GLOB:
                    {
                        match = Util.StringMatch(listv[i].ToString(), patternBytes);
                        break;
                    }

                    case REGEXP:
                    {
                        match = Util.regExpMatch(interp, listv[i].ToString(), patObj);
                        break;
                    }
                    }
                    if (match)
                    {
                        index = i;
                        break;
                    }
                }
            }
            interp.SetResult(index);
            return(TCL.CompletionCode.RETURN);
        }