コード例 #1
0
        internal static int FormatNumber(Interp interp, char type, TclObject src, byte[] resultBytes, int cursor)
        {
            if (type == 'd')
            {
                double dvalue                 = TclDouble.get(interp, src);
                System.IO.MemoryStream ms     = new System.IO.MemoryStream(resultBytes, cursor, 8);
                System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms);
                writer.Write(dvalue);
                cursor += 8;
                writer.Close();
                ms.Close();
            }
            else if (type == 'f')
            {
                float fvalue = (float)TclDouble.get(interp, src);
                System.IO.MemoryStream ms     = new System.IO.MemoryStream(resultBytes, cursor, 4);
                System.IO.BinaryWriter writer = new System.IO.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);
        }
コード例 #2
0
 public static bool Tcl_GetDouble(Interp interp, TclObject to, out double value)
 {
     try
     {
         value = TclDouble.get(interp, to);
         return(false);
     }
     catch
     {
         value = 0;
         return(true);
     }
 }
コード例 #3
0
 public static bool Tcl_GetDoubleFromObj(Interp interp, TclObject to, ref double value)
 {
     try
     {
         if (to.ToString() == "NaN")
         {
             value = Double.NaN;
         }
         else
         {
             value = TclDouble.get(interp, to);
         }
         return(false);
     }
     catch { return(true); }
 }
コード例 #4
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)
        {
            System.Text.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 System.Text.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);
        }
コード例 #5
0
ファイル: LsearchCmd.cs プロジェクト: ekicyou/pasta
        /*
         *-----------------------------------------------------------------------------
         *
         * 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);
        }
コード例 #6
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:
                System.Text.StringBuilder sbuf = new System.Text.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);
            }
        }