Source Code Cross Referenced for Util.java in  » Scripting » jacl » tcl » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* 
0002:         * Util.java --
0003:         *
0004:         *	This class provides useful Tcl utility methods.
0005:         *
0006:         * Copyright (c) 1997 Cornell University.
0007:         * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
0008:         *
0009:         * See the file "license.terms" for information on usage and redistribution
0010:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0011:         *
0012:         * RCS: @(#) $Id: Util.java,v 1.26 2006/06/13 06:52:47 mdejong Exp $
0013:         */
0014:
0015:        package tcl.lang;
0016:
0017:        import sunlabs.brazil.util.regexp.Regexp;
0018:
0019:        import java.io.*;
0020:        import java.util.*;
0021:
0022:        public class Util {
0023:
0024:            static final int TCL_DONT_USE_BRACES = 1;
0025:            static final int USE_BRACES = 2;
0026:            static final int BRACES_UNMATCHED = 4;
0027:
0028:            // Some error messages.
0029:
0030:            static final String intTooBigCode = "ARITH IOVERFLOW {integer value too large to represent}";
0031:            static final String fpTooBigCode = "ARITH OVERFLOW {floating-point value too large to represent}";
0032:
0033:            // This table below is used to convert from ASCII digits to a
0034:            // numerical equivalent.  It maps from '0' through 'z' to integers
0035:            // (100 for non-digit characters).
0036:
0037:            static char cvtIn[] = { 0, 1, 2, 3, 4, 5, 6, 7,
0038:                    8,
0039:                    9, // '0' - '9'
0040:                    100, 100, 100, 100, 100,
0041:                    100,
0042:                    100, // punctuation 
0043:                    10, 11, 12, 13, 14, 15, 16, 17,
0044:                    18,
0045:                    19, // 'A' - 'Z' 
0046:                    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
0047:                    35, 100, 100, 100, 100, 100,
0048:                    100, // punctuation 
0049:                    10, 11, 12, 13, 14, 15, 16, 17, 18,
0050:                    19, // 'a' - 'z'
0051:                    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
0052:                    35 };
0053:
0054:            // Largest possible base 10 exponent.  Any
0055:            // exponent larger than this will already
0056:            // produce underflow or overflow, so there's
0057:            // no need to worry about additional digits.
0058:
0059:            static final int maxExponent = 511;
0060:
0061:            // Table giving binary powers of 10. Entry
0062:            // is 10^2^i.  Used to convert decimal
0063:            // exponents into floating-point numbers.
0064:
0065:            static final double powersOf10[] = { 10., 100., 1.0e4, 1.0e8,
0066:                    1.0e16, 1.0e32, 1.0e64, 1.0e128, 1.0e256 };
0067:
0068:            // Default precision for converting floating-point values to strings.
0069:
0070:            static final int DEFAULT_PRECISION = 12;
0071:
0072:            // The following variable determine the precision used when converting
0073:            // floating-point values to strings. This information is linked to all
0074:            // of the tcl_precision variables in all interpreters inside a JVM via 
0075:            // PrecTraceProc.
0076:            //
0077:            // Note: since multiple threads may change precision concurrently, race
0078:            // conditions may occur.
0079:            //
0080:            // It should be modified only by the PrecTraceProc class.
0081:
0082:            static int precision = DEFAULT_PRECISION;
0083:
0084:            /*
0085:             *----------------------------------------------------------------------
0086:             *
0087:             * Util --
0088:             *	Dummy constructor to keep Java from automatically creating a
0089:             *	default public constructor for the Util class.
0090:             *
0091:             * Side effects:
0092:             *	None.
0093:             *
0094:             *----------------------------------------------------------------------
0095:             */
0096:
0097:            private Util() {
0098:                // Do nothing.  This should never be called.
0099:            }
0100:
0101:            /*
0102:             *----------------------------------------------------------------------
0103:             *
0104:             * strtoul --
0105:             *
0106:             *	Implements functionality of the strtoul() function used in the
0107:             *	C Tcl library. This method will parse digits from what
0108:             *	should be a 32-bit (signed) integer and report the index
0109:             *	of the character immediately following the digits.
0110:             *
0111:             *		E.g.:	"0x7fffffff"	->  2147483647
0112:             *			"0x80000000"	-> -2147483648
0113:             *			"0x100000000"	-> errno = TCL.INTEGER_RANGE
0114:             *			"-0xFF"		-> -255
0115:             *
0116:             * 	This method behaves like the strtoul() function in NativeTcl.
0117:             * 	This method will return a signed 64-bit Java long type in
0118:             * 	the strtoulResult argument. This value is used as a signed
0119:             * 	integer in the expr module. A leading signed character like
0120:             * 	'+' or '-' is supported. Leading spaces are skipped.
0121:             *
0122:             * Results:
0123:             *	The strtoulResult argument will be populated with the parsed
0124:             *	value and the index of the character following the digits.
0125:             *	If an error is detected, then the strtoulResult errno value
0126:             *	will be set accordingly.
0127:             *
0128:             * Side effects:
0129:             *	None.
0130:             *
0131:             *----------------------------------------------------------------------
0132:             */
0133:
0134:            static void strtoul(String s, // String of ASCII digits, possibly preceded by
0135:                    // white space.  For bases greater than 10, either
0136:                    // lower- or upper-case digits may be used.
0137:                    int start, // The index of s where the number starts.
0138:                    int base, // Base for conversion.  Must be less than 37.  If 0,
0139:                    // then the base is chosen from the leading characters
0140:                    // of string:  "0x" means hex, "0" means octal, 
0141:                    // anything else means decimal.
0142:                    StrtoulResult strtoulResult) // Location to store results in
0143:            {
0144:                long result = 0;
0145:                int digit;
0146:                boolean anyDigits = false;
0147:                boolean negative = false;
0148:                int len = s.length();
0149:                int i = start;
0150:                char c = '\0';
0151:
0152:                // Skip any leading blanks.
0153:
0154:                while (i < len
0155:                        && (((c = s.charAt(i)) == ' ') || Character
0156:                                .isWhitespace(c))) {
0157:                    i++;
0158:                }
0159:                if (i >= len) {
0160:                    strtoulResult.update(0, 0, TCL.INVALID_INTEGER);
0161:                    return;
0162:                }
0163:
0164:                if (c == '-') {
0165:                    negative = true;
0166:                }
0167:                if (c == '-' || c == '+') {
0168:                    i++;
0169:                    if (i >= len) {
0170:                        strtoulResult.update(0, 0, TCL.INVALID_INTEGER);
0171:                        return;
0172:                    }
0173:                    c = s.charAt(i);
0174:                }
0175:
0176:                // If no base was provided, pick one from the leading characters
0177:                // of the string.
0178:
0179:                if (base == 0) {
0180:                    if (c == '0') {
0181:                        if (i < len - 1) {
0182:                            i++;
0183:                            c = s.charAt(i);
0184:                            if (c == 'x' || c == 'X') {
0185:                                i++;
0186:                                base = 16;
0187:                            }
0188:                        }
0189:                        if (base == 0) {
0190:                            // Must set anyDigits here, otherwise "0" produces a
0191:                            // "no digits" error.
0192:
0193:                            anyDigits = true;
0194:                            base = 8;
0195:                        }
0196:                    } else {
0197:                        base = 10;
0198:                    }
0199:                } else if (base == 16) {
0200:                    if (i < len - 2) {
0201:                        // Skip a leading "0x" from hex numbers.
0202:
0203:                        if ((c == '0') && (s.charAt(i + 1) == 'x')) {
0204:                            i += 2;
0205:                        }
0206:                    }
0207:                }
0208:
0209:                long max = (((long) ((long) 1 << 32)) / ((long) base));
0210:                boolean overflowed = false;
0211:
0212:                for (;; i += 1) {
0213:                    if (i >= len) {
0214:                        break;
0215:                    }
0216:                    digit = s.charAt(i) - '0';
0217:                    if (digit < 0 || digit > ('z' - '0')) {
0218:                        break;
0219:                    }
0220:                    digit = cvtIn[digit];
0221:                    if (digit >= base) {
0222:                        break;
0223:                    }
0224:
0225:                    if (result > max) {
0226:                        overflowed = true;
0227:                    }
0228:
0229:                    result = result * base + digit;
0230:                    anyDigits = true;
0231:                }
0232:
0233:                // See if there were any digits at all.
0234:
0235:                if (!anyDigits) {
0236:                    strtoulResult.update(0, 0, TCL.INVALID_INTEGER);
0237:                } else if (overflowed) {
0238:                    strtoulResult.update(0, i, TCL.INTEGER_RANGE);
0239:                } else {
0240:                    strtoulResult.update((negative ? -result : result), i, 0);
0241:                }
0242:            }
0243:
0244:            /*
0245:             *----------------------------------------------------------------------
0246:             *
0247:             * getInt --
0248:             *
0249:             *	Converts an ASCII string to an integer.
0250:             *
0251:             * Results:
0252:             *	The integer value of the string.
0253:             *
0254:             * Side effects:
0255:             *	None.
0256:             *
0257:             *----------------------------------------------------------------------
0258:             */
0259:
0260:            static int getInt(Interp interp, // The current interpreter. Can be null.
0261:                    String s) // The string to convert from. Must be in valid
0262:                    // Tcl integer format.
0263:                    throws TclException // If the string is not a valid Tcl integer.
0264:            {
0265:                int len = s.length();
0266:                int i = 0;
0267:                char c;
0268:
0269:                StrtoulResult res;
0270:                if (interp == null) {
0271:                    res = new StrtoulResult();
0272:                } else {
0273:                    res = interp.strtoulResult;
0274:                }
0275:                Util.strtoul(s, i, 0, res);
0276:
0277:                if (res.errno < 0) {
0278:                    if (res.errno == TCL.INTEGER_RANGE) {
0279:                        if (interp != null) {
0280:                            interp.setErrorCode(TclString
0281:                                    .newInstance(intTooBigCode));
0282:                        }
0283:                        throw new TclException(interp,
0284:                                "integer value too large to represent");
0285:                    } else {
0286:                        throw new TclException(interp,
0287:                                "expected integer but got \"" + s + "\""
0288:                                        + checkBadOctal(interp, s));
0289:                    }
0290:                } else if (res.index < len) {
0291:                    for (i = res.index; i < len; i++) {
0292:                        if (((c = s.charAt(i)) != ' ')
0293:                                && !Character.isWhitespace(c)) {
0294:                            throw new TclException(interp,
0295:                                    "expected integer but got \"" + s + "\""
0296:                                            + checkBadOctal(interp, s));
0297:                        }
0298:                    }
0299:                }
0300:
0301:                return (int) res.value;
0302:            }
0303:
0304:            /*
0305:             *----------------------------------------------------------------------
0306:             *
0307:             * TclGetIntForIndex -> Util.getIntForIndex
0308:             *
0309:             *	This procedure returns an integer corresponding to the list index
0310:             *	held in a Tcl object. The Tcl object's value is expected to be
0311:             *	either an integer or a string of the form "end([+-]integer)?". 
0312:             *
0313:             * Results:
0314:             *	The return value is the index that is found from the string. If
0315:             *	the Tcl object referenced by tobj has the value "end", the
0316:             *	value stored is endValue. If tobj's value is not of the form
0317:             *	"end([+-]integer)?" and it
0318:             *	can not be converted to an integer, an exception is raised.
0319:             *
0320:             * Side effects:
0321:             *	The object referenced by tobj might be converted to an
0322:             *	integer object.
0323:             *
0324:             *----------------------------------------------------------------------
0325:             */
0326:            static final int getIntForIndex(Interp interp, // Interp object, can be null
0327:                    TclObject tobj, int endValue) throws TclException {
0328:                int length, offset;
0329:
0330:                if (tobj.isIntType()) {
0331:                    return TclInteger.get(interp, tobj);
0332:                }
0333:
0334:                String bytes = tobj.toString();
0335:                length = bytes.length();
0336:
0337:                if ((length == 0)
0338:                        || !"end".regionMatches(0, bytes, 0, (length > 3) ? 3
0339:                                : length)) {
0340:                    try {
0341:                        offset = TclInteger.get(null, tobj);
0342:                    } catch (TclException e) {
0343:                        throw new TclException(interp, "bad index \"" + bytes
0344:                                + "\": must be integer or end?-integer?"
0345:                                + checkBadOctal(interp, bytes));
0346:                    }
0347:                    return offset;
0348:                }
0349:
0350:                if (length <= 3) {
0351:                    return endValue;
0352:                } else if ((length > 4) && (bytes.charAt(3) == '-')) {
0353:                    // This is our limited string expression evaluator
0354:                    // Pass everything after "end-" to then reverse for offset.
0355:
0356:                    try {
0357:                        offset = Util.getInt(interp, bytes.substring(4));
0358:                        offset = -offset;
0359:                        return endValue + offset;
0360:                    } catch (TclException ex) {
0361:                        // Fall through to bad index error
0362:                    }
0363:                }
0364:
0365:                throw new TclException(interp, "bad index \"" + bytes
0366:                        + "\": must be integer or end?-integer?"
0367:                        + checkBadOctal(interp, bytes.substring(3)));
0368:            }
0369:
0370:            /*
0371:             *----------------------------------------------------------------------
0372:             *
0373:             * TclCheckBadOctal ->  Util.checkBadOctal
0374:             *
0375:             *	This procedure checks for a bad octal value and returns a
0376:             *	meaningful error that should be appended to the interp's result.
0377:             *
0378:             * Results:
0379:             *	Returns error message if it was a bad octal.
0380:             *
0381:             * Side effects:
0382:             *	None.
0383:             *
0384:             *----------------------------------------------------------------------
0385:             */
0386:
0387:            static final String checkBadOctal(Interp interp, // Interpreter to use for error reporting.
0388:                    // If NULL, then no error message is returned.
0389:                    String value) {
0390:                int p = 0;
0391:                final int len = value.length();
0392:
0393:                // A frequent mistake is invalid octal values due to an unwanted
0394:                // leading zero. Try to generate a meaningful error message.
0395:
0396:                while (p < len && Character.isWhitespace(value.charAt(p))) {
0397:                    p++;
0398:                }
0399:                if ((p < len)
0400:                        && (value.charAt(p) == '+' || value.charAt(p) == '-')) {
0401:                    p++;
0402:                }
0403:                if ((p < len) && (value.charAt(p) == '0')) {
0404:                    while ((p < len) && Character.isDigit(value.charAt(p))) { // INTL: digit.
0405:                        p++;
0406:                    }
0407:                    while ((p < len) && Character.isWhitespace(value.charAt(p))) { // INTL: ISO space.
0408:                        p++;
0409:                    }
0410:                    if (p >= len) {
0411:                        // Reached end of string
0412:                        if (interp != null) {
0413:                            return " (looks like invalid octal number)";
0414:                        }
0415:                    }
0416:                }
0417:                return "";
0418:            }
0419:
0420:            /*
0421:             *----------------------------------------------------------------------
0422:             *
0423:             * strtod --
0424:             *
0425:             *	Converts the leading decimal digits of a string into double
0426:             * 	and report the index of the character immediately following the
0427:             * 	digits.
0428:             *
0429:             * Results:
0430:             *	Converts the leading decimal digits of a string into double
0431:             * 	and report the index of the character immediately following the
0432:             * 	digits.
0433:             *
0434:             * Side effects:
0435:             *	None.
0436:             *
0437:             *----------------------------------------------------------------------
0438:             */
0439:
0440:            static void strtod(String s, // String of ASCII digits, possibly preceded by
0441:                    // white space.  For bases greater than 10, either lower- or
0442:                    // upper-case digits may be used.
0443:                    final int start, // The index of the string to start on.
0444:                    int len, // The string length, or -1
0445:                    StrtodResult strtodResult) // place to store results
0446:            {
0447:                int decPt = -1; // Number of mantissa digits BEFORE decimal
0448:                // point.
0449:                int si;
0450:                int i = (start < 0 ? 0 : start);
0451:                boolean negative = false;
0452:                char c = '\0';
0453:                String sub;
0454:
0455:                if (len < 0) {
0456:                    len = s.length();
0457:                }
0458:
0459:                // Skip any leading blanks.
0460:
0461:                while (i < len
0462:                        && (((c = s.charAt(i)) == ' ') || Character
0463:                                .isWhitespace(c))) {
0464:                    i++;
0465:                }
0466:                if (i >= len) {
0467:                    strtodResult.update(0, 0, TCL.INVALID_DOUBLE);
0468:                    return;
0469:                }
0470:
0471:                // Return special value for the string "NaN"
0472:
0473:                if (c == 'N' || c == 'n') {
0474:                    sub = (i == 0 ? s : s.substring(i));
0475:                    if (sub.toLowerCase().startsWith("nan")) {
0476:                        strtodResult.update(Double.NaN, i + 3, 0);
0477:                        return;
0478:                    }
0479:                }
0480:
0481:                if (c == '-') {
0482:                    negative = true;
0483:                }
0484:                if (c == '-' || c == '+') {
0485:                    i++;
0486:                    if (i >= len) {
0487:                        strtodResult.update(0, 0, TCL.INVALID_DOUBLE);
0488:                        return;
0489:                    }
0490:                    c = s.charAt(i);
0491:                }
0492:
0493:                // The strings "Inf", "-Inf", "Infinity", and "-Infinity"
0494:                // map to special double values.
0495:
0496:                if (c == 'I') {
0497:                    int infLen = 0;
0498:
0499:                    sub = (i == 0 ? s : s.substring(i));
0500:
0501:                    if (sub.startsWith("Infinity")) {
0502:                        infLen = "Infinity".length();
0503:                    } else if (sub.startsWith("Inf")) {
0504:                        infLen = "Inf".length();
0505:                    }
0506:
0507:                    if (infLen > 0) {
0508:                        strtodResult.update(
0509:                                (negative ? Double.NEGATIVE_INFINITY
0510:                                        : Double.POSITIVE_INFINITY),
0511:                                i + infLen, 0);
0512:                        return;
0513:                    }
0514:                }
0515:
0516:                // Index of first digit now known
0517:
0518:                si = i;
0519:
0520:                // Count the number of digits in the mantissa (including the decimal
0521:                // point), and also locate the decimal point.
0522:
0523:                boolean maybeZero = true;
0524:
0525:                for (int mantSize = 0;; mantSize += 1) {
0526:                    if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
0527:                        // This is a digit
0528:                    } else {
0529:                        if ((c != '.') || (decPt >= 0)) {
0530:                            break;
0531:                        }
0532:                        decPt = mantSize;
0533:                    }
0534:                    if (c != '0' && c != '.') {
0535:                        maybeZero = false; // non zero digit found...
0536:                    }
0537:                    i++;
0538:                    if (i >= len) {
0539:                        break;
0540:                    } else {
0541:                        c = s.charAt(i);
0542:                    }
0543:                }
0544:
0545:                // Skim off the exponent.
0546:
0547:                if (i < len) {
0548:                    if (si != i) { // same c value as when above for loop was entered
0549:                        c = s.charAt(i);
0550:                    }
0551:                    if ((c == 'E') || (c == 'e')) {
0552:                        i++;
0553:                        if (i < len) {
0554:                            c = s.charAt(i);
0555:                            if (c == '-') {
0556:                                i++;
0557:                            } else if (c == '+') {
0558:                                i++;
0559:                            }
0560:
0561:                            boolean notdigit = false;
0562:                            if (i < len) {
0563:                                c = s.charAt(i);
0564:                                if ((c >= '0' && c <= '9')
0565:                                        || Character.isDigit(c)) {
0566:                                    // This is a digit
0567:                                } else {
0568:                                    notdigit = true;
0569:                                }
0570:                            }
0571:
0572:                            if (i >= len || notdigit) {
0573:                                // A number like 1E+ or 1eq2 is not a double
0574:                                // with an exponent part. In this case, return
0575:                                // the number up to the 'E' or 'e'.
0576:                                if (c == '-' || c == '+') {
0577:                                    i--;
0578:                                }
0579:                                i--;
0580:                            } else {
0581:                                for (; i < len; i++) {
0582:                                    c = s.charAt(i);
0583:                                    if ((c >= '0' && c <= '9')
0584:                                            || Character.isDigit(c)) {
0585:                                        // This is a digit
0586:                                    } else {
0587:                                        break;
0588:                                    }
0589:                                }
0590:                            }
0591:                        }
0592:                    }
0593:                }
0594:
0595:                // Avoid pointless substring or NumberFormatException
0596:                // for an empty string or for a string like "abc"
0597:                // that has no digits.
0598:
0599:                if (si == i) {
0600:                    strtodResult.update(0, 0, TCL.INVALID_DOUBLE);
0601:                    return;
0602:                }
0603:
0604:                s = s.substring(si, i);
0605:                double result = 0;
0606:
0607:                try {
0608:                    result = Double.valueOf(s).doubleValue();
0609:                } catch (NumberFormatException e) {
0610:                    strtodResult.update(0, 0, TCL.INVALID_DOUBLE);
0611:                    return;
0612:                }
0613:
0614:                if ((result == Double.NEGATIVE_INFINITY)
0615:                        || (result == Double.POSITIVE_INFINITY)
0616:                        || (result == 0.0 && !maybeZero)) {
0617:                    strtodResult.update(result, i, TCL.DOUBLE_RANGE);
0618:                    return;
0619:                }
0620:
0621:                if (result == Double.NaN) {
0622:                    strtodResult.update(0, 0, TCL.INVALID_DOUBLE);
0623:                    return;
0624:                }
0625:
0626:                strtodResult.update((negative ? -result : result), i, 0);
0627:                return;
0628:            }
0629:
0630:            /*
0631:             *----------------------------------------------------------------------
0632:             *
0633:             * getDouble --
0634:             *
0635:             *	Converts an ASCII string to a double.
0636:             *
0637:             * Results:
0638:             *	The double value of the string.
0639:             *
0640:             * Side effects:
0641:             *	None.
0642:             *
0643:             *----------------------------------------------------------------------
0644:             */
0645:
0646:            static double getDouble(Interp interp, // The current interpreter, can be null.
0647:                    String s) // The string to convert from. Must be in valid
0648:                    // Tcl double format.
0649:                    throws TclException // If the string is not a valid Tcl double.
0650:            {
0651:                int len = s.length();
0652:                int i = 0;
0653:                char c;
0654:
0655:                StrtodResult res;
0656:                if (interp == null) {
0657:                    res = new StrtodResult();
0658:                } else {
0659:                    res = interp.strtodResult;
0660:                }
0661:                Util.strtod(s, i, len, res);
0662:
0663:                if (res.errno != 0) {
0664:                    if (res.errno == TCL.DOUBLE_RANGE) {
0665:                        if (interp != null) {
0666:                            interp.setErrorCode(TclString
0667:                                    .newInstance(fpTooBigCode));
0668:                        }
0669:                        throw new TclException(interp,
0670:                                "floating-point value too large to represent");
0671:                    } else {
0672:                        throw new TclException(interp,
0673:                                "expected floating-point number but got \"" + s
0674:                                        + "\"");
0675:                    }
0676:                } else if (res.index < len) {
0677:                    for (i = res.index; i < len; i++) {
0678:                        if ((c = s.charAt(i)) != ' '
0679:                                && !Character.isWhitespace(c)) {
0680:                            throw new TclException(interp,
0681:                                    "expected floating-point number but got \""
0682:                                            + s + "\"");
0683:                        }
0684:                    }
0685:                }
0686:
0687:                return res.value;
0688:            }
0689:
0690:            /*
0691:             *----------------------------------------------------------------------
0692:             *
0693:             * Tcl_ConcatObj -> concat
0694:             *
0695:             *	Concatenate the strings from a set of objects into a single string
0696:             *	object with spaces between the original strings.
0697:             *
0698:             * Results:
0699:             *	The return value is a new string object containing a concatenation
0700:             *	of the strings in objv. Its ref count is zero.
0701:             *
0702:             * Side effects:
0703:             *	None.
0704:             *
0705:             *----------------------------------------------------------------------
0706:             */
0707:
0708:            static TclObject concat(int from, // The starting index.
0709:                    int to, // The ending index (inclusive).
0710:                    TclObject[] objv) // Array of objects to concatenate.
0711:                    throws TclException {
0712:                int allocSize, elemLength, i, j;
0713:                String element;
0714:                StringBuffer concatStr;
0715:                TclObject obj, tlist;
0716:                boolean allList;
0717:
0718:                if (from > objv.length) {
0719:                    return TclString.newInstance("");
0720:                }
0721:                if (to <= objv.length) {
0722:                    to = objv.length - 1;
0723:                }
0724:
0725:                // Check first to see if all the items are of list type.  If so,
0726:                // we will concat them together as lists, and return a list object.
0727:                // This is only valid when the lists have no current string
0728:                // representation, since we don't know what the original type was.
0729:                // An original string rep may have lost some whitespace info when
0730:                // converted which could be important.
0731:
0732:                allList = true;
0733:                for (i = from; i <= to; i++) {
0734:                    obj = objv[i];
0735:                    if (obj.hasNoStringRep() && obj.isListType()) {
0736:                        // A pure list element
0737:                    } else {
0738:                        allList = false;
0739:                        break;
0740:                    }
0741:                }
0742:                if (allList) {
0743:                    tlist = TclList.newInstance();
0744:                    for (i = from; i <= to; i++) {
0745:                        // Tcl_ListObjAppendList could be used here, but this saves
0746:                        // us a bit of type checking (since we've already done it)
0747:                        // Use of MAX_VALUE tells us to always put the new stuff on
0748:                        // the end.  It will be set right in Tcl_ListObjReplace.
0749:
0750:                        obj = objv[i];
0751:                        TclObject[] elements = TclList.getElements(null, obj);
0752:                        TclList.replace(null, tlist, Integer.MAX_VALUE, 0,
0753:                                elements, 0, elements.length - 1);
0754:                    }
0755:                    return tlist;
0756:                }
0757:
0758:                allocSize = 0;
0759:                for (i = from; i <= to; i++) {
0760:                    obj = objv[i];
0761:                    element = obj.toString();
0762:                    elemLength = element.length();
0763:                    if ((element != null) && (elemLength > 0)) {
0764:                        allocSize += (elemLength + 1);
0765:                    }
0766:                }
0767:                if (allocSize == 0) {
0768:                    allocSize = 1;
0769:                }
0770:
0771:                // Allocate storage for the concatenated result.
0772:
0773:                concatStr = new StringBuffer(allocSize);
0774:
0775:                // Now concatenate the elements. Clip white space off the front and back
0776:                // to generate a neater result, and ignore any empty elements.
0777:
0778:                for (i = from; i <= to; i++) {
0779:                    obj = objv[i];
0780:                    element = obj.toString();
0781:                    element = TrimLeft(element, " ");
0782:                    elemLength = element.length();
0783:
0784:                    // Trim trailing white space.  But, be careful not to trim
0785:                    // a space character if it is preceded by a backslash: in
0786:                    // this case it could be significant.
0787:
0788:                    for (j = elemLength - 1; j >= 0; j--) {
0789:                        char c = element.charAt(j);
0790:                        if (c == ' ' || Character.isWhitespace(c)) {
0791:                            // A whitespace char
0792:                            if (j > 0 && element.charAt(j - 1) == '\\') {
0793:                                // Don't trim backslash space
0794:                                break;
0795:                            }
0796:                        } else {
0797:                            // Not a whitespace char
0798:                            break;
0799:                        }
0800:                    }
0801:                    if (j != (elemLength - 1)) {
0802:                        element = element.substring(0, j + 1);
0803:                    }
0804:                    if (element.length() == 0) {
0805:                        /* Don't leave extra space in the buffer */
0806:                        if (i == to && (concatStr.length() > 0)) {
0807:                            concatStr.setLength(concatStr.length() - 1);
0808:                        }
0809:                        continue;
0810:                    }
0811:                    concatStr.append(element);
0812:                    if (i < to) {
0813:                        concatStr.append(' ');
0814:                    }
0815:                }
0816:
0817:                return TclString.newInstance(concatStr);
0818:            }
0819:
0820:            /*
0821:             *----------------------------------------------------------------------
0822:             *
0823:             * stringMatch --
0824:             *
0825:             *	 See if a particular string matches a particular pattern. The
0826:             * 	 matching operation permits the following special characters in
0827:             *	 the pattern: *?\[] (see the manual entry for details on what
0828:             *	 these mean).
0829:             *
0830:             * Results:
0831:             *	True if the string matches with the pattern.
0832:             *
0833:             * Side effects:
0834:             *	None.
0835:             *
0836:             *----------------------------------------------------------------------
0837:             */
0838:
0839:            public static final boolean stringMatch(String str, //String to compare pattern against.
0840:                    String pat) //Pattern which may contain special characters.
0841:            {
0842:                char[] strArr = str.toCharArray();
0843:                char[] patArr = pat.toCharArray();
0844:                int strLen = str.length(); // Cache the len of str.
0845:                int patLen = pat.length(); // Cache the len of pat.
0846:                int pIndex = 0; // Current index into patArr.
0847:                int sIndex = 0; // Current index into patArr.
0848:                char strch; // Stores current char in string.
0849:                char ch1; // Stores char after '[' in pat.
0850:                char ch2; // Stores look ahead 2 char in pat.
0851:                boolean incrIndex = false; // If true it will incr both p/sIndex.
0852:
0853:                while (true) {
0854:
0855:                    if (incrIndex == true) {
0856:                        pIndex++;
0857:                        sIndex++;
0858:                        incrIndex = false;
0859:                    }
0860:
0861:                    // See if we're at the end of both the pattern and the string.
0862:                    // If so, we succeeded.  If we're at the end of the pattern
0863:                    // but not at the end of the string, we failed.
0864:
0865:                    if (pIndex == patLen) {
0866:                        return sIndex == strLen;
0867:                    }
0868:                    if ((sIndex == strLen) && (patArr[pIndex] != '*')) {
0869:                        return false;
0870:                    }
0871:
0872:                    // Check for a "*" as the next pattern character.  It matches
0873:                    // any substring.  We handle this by calling ourselves
0874:                    // recursively for each postfix of string, until either we
0875:                    // match or we reach the end of the string.
0876:
0877:                    if (patArr[pIndex] == '*') {
0878:                        pIndex++;
0879:                        if (pIndex == patLen) {
0880:                            return true;
0881:                        }
0882:                        while (true) {
0883:                            if (stringMatch(str.substring(sIndex), pat
0884:                                    .substring(pIndex))) {
0885:                                return true;
0886:                            }
0887:                            if (sIndex == strLen) {
0888:                                return false;
0889:                            }
0890:                            sIndex++;
0891:                        }
0892:                    }
0893:
0894:                    // Check for a "?" as the next pattern character.  It matches
0895:                    // any single character.
0896:
0897:                    if (patArr[pIndex] == '?') {
0898:                        incrIndex = true;
0899:                        continue;
0900:                    }
0901:
0902:                    // Check for a "[" as the next pattern character.  It is followed
0903:                    // by a list of characters that are acceptable, or by a range
0904:                    // (two characters separated by "-").
0905:
0906:                    if (patArr[pIndex] == '[') {
0907:                        pIndex++;
0908:                        while (true) {
0909:                            if ((pIndex == patLen) || (patArr[pIndex] == ']')) {
0910:                                return false;
0911:                            }
0912:                            if (sIndex == strLen) {
0913:                                return false;
0914:                            }
0915:                            ch1 = patArr[pIndex];
0916:                            strch = strArr[sIndex];
0917:                            if (((pIndex + 1) != patLen)
0918:                                    && (patArr[pIndex + 1] == '-')) {
0919:                                if ((pIndex += 2) == patLen) {
0920:                                    return false;
0921:                                }
0922:                                ch2 = patArr[pIndex];
0923:                                if (((ch1 <= strch) && (ch2 >= strch))
0924:                                        || ((ch1 >= strch) && (ch2 <= strch))) {
0925:                                    break;
0926:                                }
0927:                            } else if (ch1 == strch) {
0928:                                break;
0929:                            }
0930:                            pIndex++;
0931:                        }
0932:
0933:                        for (pIndex++; ((pIndex != patLen) && (patArr[pIndex] != ']')); pIndex++) {
0934:                        }
0935:                        if (pIndex == patLen) {
0936:                            pIndex--;
0937:                        }
0938:                        incrIndex = true;
0939:                        continue;
0940:                    }
0941:
0942:                    // If the next pattern character is '\', just strip off the '\'
0943:                    // so we do exact matching on the character that follows.
0944:
0945:                    if (patArr[pIndex] == '\\') {
0946:                        pIndex++;
0947:                        if (pIndex == patLen) {
0948:                            return false;
0949:                        }
0950:                    }
0951:
0952:                    // There's no special character.  Just make sure that the next
0953:                    // characters of each string match.
0954:
0955:                    if ((sIndex == strLen)
0956:                            || (patArr[pIndex] != strArr[sIndex])) {
0957:                        return false;
0958:                    }
0959:                    incrIndex = true;
0960:                }
0961:            }
0962:
0963:            /*
0964:             *----------------------------------------------------------------------
0965:             *
0966:             * Tcl_UtfToTitle -> toTitle --
0967:             *
0968:             *	Changes the first character of a string to title case or
0969:             *	uppercase and the rest of the string to lowercase.
0970:             *
0971:             * Results:
0972:             *	Returns the generated string.
0973:             *
0974:             * Side effects:
0975:             *	None.
0976:             *
0977:             *----------------------------------------------------------------------
0978:             */
0979:
0980:            static String toTitle(String str) // String to convert in place.
0981:            {
0982:                // Capitalize the first character and then lowercase the rest of the
0983:                // characters until we get to the end of string.
0984:
0985:                int length = str.length();
0986:                if (length == 0) {
0987:                    return "";
0988:                }
0989:                StringBuffer buf = new StringBuffer(length);
0990:                buf.append(Character.toTitleCase(str.charAt(0)));
0991:                buf.append(str.substring(1).toLowerCase());
0992:                return buf.toString();
0993:            }
0994:
0995:            /*
0996:             *-----------------------------------------------------------------------------
0997:             *
0998:             * regExpMatch --
0999:             *
1000:             *	See if a string matches a regular expression.
1001:             *
1002:             * Results:
1003:             *	Returns a boolean whose value depends on whether a match was made.
1004:             *
1005:             * Side effects:
1006:             *	None.
1007:             *
1008:             *-----------------------------------------------------------------------------
1009:             */
1010:
1011:            static final boolean regExpMatch(Interp interp, // Current interpreter.
1012:                    String string, // The string to match.
1013:                    TclObject pattern) // The regular expression.
1014:                    throws TclException {
1015:                Regexp r = TclRegexp.compile(interp, pattern, false);
1016:                return r.match(string, (String[]) null);
1017:            }
1018:
1019:            /*
1020:             *-----------------------------------------------------------------------------
1021:             *
1022:             * appendElement --
1023:             *
1024:             *	Append a string to the string buffer.  If the string buffer is not
1025:             *	empty, append a space before appending "s".
1026:             *
1027:             * Results:
1028:             *	None.
1029:             *
1030:             * Side effects:
1031:             *	The value of "sbuf" is changesd.
1032:             *
1033:             *-----------------------------------------------------------------------------
1034:             */
1035:
1036:            static final void appendElement(Interp interp, // Current interpreter.
1037:                    StringBuffer sbuf, // The buffer to append to. 
1038:                    String s) // The string to append.
1039:                    throws TclException {
1040:                if (sbuf.length() > 0) {
1041:                    sbuf.append(' ');
1042:                }
1043:
1044:                int flags = scanElement(interp, s);
1045:                convertElement(s, flags, sbuf);
1046:            }
1047:
1048:            /*
1049:             *----------------------------------------------------------------------
1050:             *
1051:             * findElement --
1052:             *
1053:             *	Given a String that contains a Tcl list, locate the first (or next)
1054:             *	element in the list.
1055:             *
1056:             * Results:
1057:             *	This method returns true and populates the FindElemResult if an
1058:             *	element was found. If no element was found, false will be returned.
1059:             *	The FindElemResult contains the index of the first and last characters
1060:             *	of the element and the string value of the element.
1061:             *
1062:             * Side effects:
1063:             *	None.
1064:             *
1065:             *----------------------------------------------------------------------
1066:             */
1067:
1068:            static final boolean findElement(Interp interp, // Current interpreter. If non-null, is used
1069:                    // to store error messages.
1070:                    String s, // The string to locate an element.
1071:                    int i, // The index inside s to start locating an
1072:                    // element.
1073:                    int len, // The length of the string.
1074:                    FindElemResult fer) // The result object to populate.
1075:                    throws TclException {
1076:                int openBraces = 0;
1077:                boolean inQuotes = false;
1078:                char c = '\0';
1079:                int elemStart, elemEnd;
1080:                int size = 0;
1081:
1082:                while (i < len
1083:                        && (((c = s.charAt(i)) == ' ') || Character
1084:                                .isWhitespace(c))) {
1085:                    i++;
1086:                }
1087:                if (i >= len) {
1088:                    return false;
1089:                }
1090:                if (c == '{') {
1091:                    openBraces = 1;
1092:                    i++;
1093:                } else if (c == '"') {
1094:                    inQuotes = true;
1095:                    i++;
1096:                }
1097:
1098:                // An element typically consist of a range of characters
1099:                // that are a substring of the string s, so s.substring()
1100:                // can be used in most cases. If an element requires
1101:                // backslashes then use a StringBuffer.
1102:
1103:                StringBuffer sbuf = null;
1104:                int simpleStart, simpleEnd = -1;
1105:                String elem;
1106:
1107:                elemStart = i;
1108:                simpleStart = i;
1109:
1110:                while (true) {
1111:                    if (i >= len) {
1112:                        elemEnd = i;
1113:                        size = (elemEnd - elemStart);
1114:                        if (openBraces != 0) {
1115:                            throw new TclException(interp,
1116:                                    "unmatched open brace in list");
1117:                        } else if (inQuotes) {
1118:                            throw new TclException(interp,
1119:                                    "unmatched open quote in list");
1120:                        }
1121:                        if (sbuf == null) {
1122:                            elem = s.substring(elemStart, elemEnd);
1123:                        } else {
1124:                            sbuf.append(s.substring(simpleStart, elemEnd));
1125:                            elem = sbuf.toString();
1126:                        }
1127:                        fer.update(elemStart, elemEnd, elem, size);
1128:                        return true;
1129:                    }
1130:
1131:                    c = s.charAt(i);
1132:                    switch (c) {
1133:                    // Open brace: don't treat specially unless the element is
1134:                    // in braces.  In this case, keep a nesting count.
1135:
1136:                    case '{':
1137:                        if (openBraces != 0) {
1138:                            openBraces++;
1139:                        }
1140:                        i++;
1141:                        break;
1142:
1143:                    // Close brace: if element is in braces, keep nesting
1144:                    // count and quit when the last close brace is seen.
1145:
1146:                    case '}':
1147:                        if (openBraces == 1) {
1148:                            elemEnd = i;
1149:                            size = (elemEnd - elemStart);
1150:                            if (i == len - 1
1151:                                    || Character.isWhitespace(s.charAt(i + 1))) {
1152:                                if (sbuf == null) {
1153:                                    elem = s.substring(elemStart, elemEnd);
1154:                                } else {
1155:                                    sbuf.append(s.substring(simpleStart,
1156:                                            elemEnd));
1157:                                    elem = sbuf.toString();
1158:                                }
1159:                                fer.update(elemStart, elemEnd + 1, elem, size);
1160:                                return true;
1161:                            } else {
1162:                                int errEnd;
1163:                                for (errEnd = i + 1; errEnd < len; errEnd++) {
1164:                                    if (Character
1165:                                            .isWhitespace(s.charAt(errEnd))) {
1166:                                        break;
1167:                                    }
1168:                                }
1169:                                throw new TclException(interp,
1170:                                        "list element in braces followed by \""
1171:                                                + s.substring(i + 1, errEnd)
1172:                                                + "\" instead of space");
1173:                            }
1174:                        } else if (openBraces != 0) {
1175:                            openBraces--;
1176:                        }
1177:                        i++;
1178:                        break;
1179:
1180:                    // Backslash:  skip over everything up to the end of the
1181:                    // backslash sequence.
1182:
1183:                    case '\\':
1184:                        BackSlashResult bs = Interp.backslash(s, i, len);
1185:                        if (openBraces > 0) {
1186:                            // Backslashes are ignored in brace-quoted stuff
1187:
1188:                        } else {
1189:                            if (sbuf == null) {
1190:                                sbuf = new StringBuffer();
1191:                            }
1192:                            sbuf.append(s.substring(simpleStart, i));
1193:                            sbuf.append(bs.c);
1194:                            simpleStart = bs.nextIndex;
1195:                        }
1196:                        i = bs.nextIndex;
1197:
1198:                        break;
1199:
1200:                    // Space: ignore if element is in braces or quotes;  otherwise
1201:                    // terminate element.
1202:
1203:                    case ' ':
1204:                    case '\f':
1205:                    case '\n':
1206:                    case '\r':
1207:                    case '\t':
1208:                        if ((openBraces == 0) && !inQuotes) {
1209:                            elemEnd = i;
1210:                            size = (elemEnd - elemStart);
1211:                            if (sbuf == null) {
1212:                                elem = s.substring(elemStart, elemEnd);
1213:                            } else {
1214:                                sbuf.append(s.substring(simpleStart, elemEnd));
1215:                                elem = sbuf.toString();
1216:                            }
1217:                            fer.update(elemStart, elemEnd, elem, size);
1218:                            return true;
1219:                        } else {
1220:                            i++;
1221:                        }
1222:                        break;
1223:
1224:                    // Double-quote:  if element is in quotes then terminate it.
1225:
1226:                    case '"':
1227:                        if (inQuotes) {
1228:                            elemEnd = i;
1229:                            size = (elemEnd - elemStart);
1230:                            if (i == len - 1
1231:                                    || Character.isWhitespace(s.charAt(i + 1))) {
1232:                                if (sbuf == null) {
1233:                                    elem = s.substring(elemStart, elemEnd);
1234:                                } else {
1235:                                    sbuf.append(s.substring(simpleStart,
1236:                                            elemEnd));
1237:                                    elem = sbuf.toString();
1238:                                }
1239:                                fer.update(elemStart, elemEnd + 1, elem, size);
1240:                                return true;
1241:                            } else {
1242:                                int errEnd;
1243:                                for (errEnd = i + 1; errEnd < len; errEnd++) {
1244:                                    if (Character
1245:                                            .isWhitespace(s.charAt(errEnd))) {
1246:                                        break;
1247:                                    }
1248:                                }
1249:                                throw new TclException(interp,
1250:                                        "list element in quotes followed by \""
1251:                                                + s.substring(i + 1, errEnd)
1252:                                                + "\" instead of space");
1253:                            }
1254:                        } else {
1255:                            i++;
1256:                        }
1257:                        break;
1258:
1259:                    default:
1260:                        i++;
1261:                    }
1262:                }
1263:            }
1264:
1265:            /*
1266:             *----------------------------------------------------------------------
1267:             *
1268:             *  Tcl_ScanElement -> scanElement
1269:             *
1270:             *	This procedure is a companion procedure to convertElement.
1271:             *	It scans a string to see what needs to be done to it (e.g.
1272:             * 	add backslashes or enclosing braces) to make the string into
1273:             *	a valid Tcl list element.
1274:             *
1275:             * Results:
1276:             *	The flags needed by Tcl_ConvertElement when doing the actual
1277:             * 	conversion.
1278:             *
1279:             * Side effects:
1280:             *	None.
1281:             *
1282:             *----------------------------------------------------------------------
1283:             */
1284:
1285:            static int scanElement(Interp interp, // The current interpreter.
1286:                    String string) // The String to scan.
1287:                    throws TclException {
1288:                int flags, nestingLevel;
1289:                char c;
1290:                int len;
1291:                int i;
1292:
1293:                // This procedure and Tcl_ConvertElement together do two things:
1294:                //
1295:                // 1. They produce a proper list, one that will yield back the
1296:                // argument strings when evaluated or when disassembled with
1297:                // Tcl_SplitList.  This is the most important thing.
1298:                // 
1299:                // 2. They try to produce legible output, which means minimizing the
1300:                // use of backslashes (using braces instead).  However, there are
1301:                // some situations where backslashes must be used (e.g. an element
1302:                // like "{abc": the leading brace will have to be backslashed.  For
1303:                // each element, one of three things must be done:
1304:                //
1305:                // (a) Use the element as-is (it doesn't contain anything special
1306:                // characters).  This is the most desirable option.
1307:                //
1308:                // (b) Enclose the element in braces, but leave the contents alone.
1309:                // This happens if the element contains embedded space, or if it
1310:                // contains characters with special interpretation ($, [, ;, or \),
1311:                // or if it starts with a brace or double-quote, or if there are
1312:                // no characters in the element.
1313:                //
1314:                // (c) Don't enclose the element in braces, but add backslashes to
1315:                // prevent special interpretation of special characters.  This is a
1316:                // last resort used when the argument would normally fall under case
1317:                // (b) but contains unmatched braces.  It also occurs if the last
1318:                // character of the argument is a backslash or if the element contains
1319:                // a backslash followed by newline.
1320:                //
1321:                // The procedure figures out how many bytes will be needed to store
1322:                // the result (actually, it overestimates).  It also collects
1323:                // information about the element in the form of a flags word.
1324:
1325:                final boolean debug = false;
1326:
1327:                nestingLevel = 0;
1328:                flags = 0;
1329:
1330:                i = 0;
1331:                len = string.length();
1332:                if (len == 0) {
1333:                    string = String.valueOf('\0');
1334:
1335:                    // FIXME : pizza compiler workaround
1336:                    // We really should be able to use the "\0" form but there
1337:                    // is a nasty bug in the pizza compiler shipped with kaffe
1338:                    // that causes "\0" to be read as the empty string.
1339:
1340:                    //string = "\0";
1341:                }
1342:
1343:                if (debug) {
1344:                    System.out.println("scanElement string is \"" + string
1345:                            + "\"");
1346:                }
1347:
1348:                c = string.charAt(i);
1349:                if ((c == '{') || (c == '"') || (c == '\0')) {
1350:                    flags |= USE_BRACES;
1351:                }
1352:                for (; i < len; i++) {
1353:                    if (debug) {
1354:                        System.out.println("getting char at index " + i);
1355:                        System.out
1356:                                .println("char is '" + string.charAt(i) + "'");
1357:                    }
1358:
1359:                    c = string.charAt(i);
1360:                    switch (c) {
1361:                    case '{':
1362:                        nestingLevel++;
1363:                        break;
1364:                    case '}':
1365:                        nestingLevel--;
1366:                        if (nestingLevel < 0) {
1367:                            flags |= TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
1368:                        }
1369:                        break;
1370:                    case '[':
1371:                    case '$':
1372:                    case ';':
1373:                    case ' ':
1374:                    case '\f':
1375:                    case '\n':
1376:                    case '\r':
1377:                    case '\t':
1378:                    case 0x0b:
1379:
1380:                        // 0x0b is the character '\v' -- this escape sequence is
1381:                        // not available in Java, so we hard-code it. We need to
1382:                        // support \v to provide compatibility with native Tcl.
1383:
1384:                        flags |= USE_BRACES;
1385:                        break;
1386:                    case '\\':
1387:                        if ((i >= len - 1) || (string.charAt(i + 1) == '\n')) {
1388:                            flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
1389:                        } else {
1390:                            BackSlashResult bs = Interp.backslash(string, i,
1391:                                    len);
1392:
1393:                            // Subtract 1 because the for loop will automatically
1394:                            // add one on the next iteration.
1395:
1396:                            i = (bs.nextIndex - 1);
1397:                            flags |= USE_BRACES;
1398:                        }
1399:                        break;
1400:                    }
1401:                }
1402:                if (nestingLevel != 0) {
1403:                    flags = TCL_DONT_USE_BRACES | BRACES_UNMATCHED;
1404:                }
1405:
1406:                return flags;
1407:            }
1408:
1409:            /*
1410:             *----------------------------------------------------------------------
1411:             *
1412:             * Tcl_ConvertElement -> convertElement
1413:             *
1414:             *	This is a companion procedure to scanElement.  Given the
1415:             * 	information produced by scanElement, this procedure converts
1416:             * 	a string to a list element equal to that string.
1417:             *
1418:             * Results:
1419:             *	Conterts a string so to a new string so that Tcl List information
1420:             *	is not lost.
1421:             *
1422:             * Side effects:
1423:             *	None.
1424:             *
1425:             *----------------------------------------------------------------------
1426:             */
1427:
1428:            static void convertElement(String s, // Source information for list element.
1429:                    int flags, // Flags produced by scanElement
1430:                    StringBuffer sbuf) // Buffer to write element to
1431:            {
1432:                int i = 0;
1433:                char c;
1434:                int len = s.length();
1435:
1436:                // See the comment block at the beginning of the ScanElement
1437:                // code for details of how this works.
1438:
1439:                if ((s == null) || (s.length() == 0) || (s.charAt(0) == '\0')) {
1440:                    sbuf.append("{}");
1441:                    return;
1442:                }
1443:
1444:                if (((flags & USE_BRACES) != 0)
1445:                        && ((flags & TCL_DONT_USE_BRACES) == 0)) {
1446:                    sbuf.append('{');
1447:                    sbuf.append(s);
1448:                    sbuf.append('}');
1449:                } else {
1450:                    c = s.charAt(0);
1451:                    if (c == '{') {
1452:                        // Can't have a leading brace unless the whole element is
1453:                        // enclosed in braces.  Add a backslash before the brace.
1454:                        // Furthermore, this may destroy the balance between open
1455:                        // and close braces, so set BRACES_UNMATCHED.
1456:
1457:                        sbuf.append('\\');
1458:                        sbuf.append('{');
1459:                        i++;
1460:                        flags |= BRACES_UNMATCHED;
1461:                    }
1462:
1463:                    for (; i < len; i++) {
1464:                        c = s.charAt(i);
1465:                        switch (c) {
1466:                        case ']':
1467:                        case '[':
1468:                        case '$':
1469:                        case ';':
1470:                        case ' ':
1471:                        case '\\':
1472:                        case '"':
1473:                            sbuf.append('\\');
1474:                            break;
1475:
1476:                        case '{':
1477:                        case '}':
1478:                            // It may not seem necessary to backslash braces, but
1479:                            // it is.  The reason for this is that the resulting
1480:                            // list element may actually be an element of a sub-list
1481:                            // enclosed in braces (e.g. if Tcl_DStringStartSublist
1482:                            // has been invoked), so there may be a brace mismatch
1483:                            // if the braces aren't backslashed.
1484:
1485:                            if ((flags & BRACES_UNMATCHED) != 0) {
1486:                                sbuf.append('\\');
1487:                            }
1488:                            break;
1489:
1490:                        case '\f':
1491:                            sbuf.append('\\');
1492:                            sbuf.append('f');
1493:                            continue;
1494:
1495:                        case '\n':
1496:                            sbuf.append('\\');
1497:                            sbuf.append('n');
1498:                            continue;
1499:
1500:                        case '\r':
1501:                            sbuf.append('\\');
1502:                            sbuf.append('r');
1503:                            continue;
1504:
1505:                        case '\t':
1506:                            sbuf.append('\\');
1507:                            sbuf.append('t');
1508:                            continue;
1509:                        case 0x0b:
1510:                            // 0x0b is the character '\v' -- this escape sequence is
1511:                            // not available in Java, so we hard-code it. We need to
1512:                            // support \v to provide compatibility with native Tcl.
1513:
1514:                            sbuf.append('\\');
1515:                            sbuf.append('v');
1516:                            continue;
1517:                        }
1518:
1519:                        sbuf.append(c);
1520:                    }
1521:                }
1522:
1523:                return;
1524:            }
1525:
1526:            /*
1527:             *----------------------------------------------------------------------
1528:             *
1529:             * TrimLeft --
1530:             *
1531:             *	Trim characters in "pattern" off the left of a string
1532:             * 	If pattern isn't supplied, whitespace is trimmed
1533:             *
1534:             * Results:
1535:             *	|>None.<|
1536:             *
1537:             * Side effects:
1538:             *	|>None.<|
1539:             *
1540:             *----------------------------------------------------------------------
1541:             */
1542:
1543:            static String TrimLeft(String str, String pattern) {
1544:                int i, j;
1545:                char c, p;
1546:                char[] strArray = str.toCharArray();
1547:                char[] patternArray = pattern.toCharArray();
1548:                final int strLen = strArray.length;
1549:                final int patLen = patternArray.length;
1550:                boolean done;
1551:
1552:                for (i = 0; i < strLen; i++) {
1553:                    c = str.charAt(i);
1554:                    done = true;
1555:                    for (j = 0; j < patLen; j++) {
1556:                        p = pattern.charAt(j);
1557:                        if (c == p || (p == ' ' && Character.isWhitespace(c))) {
1558:                            done = false;
1559:                            break;
1560:                        }
1561:                    }
1562:                    if (done) {
1563:                        break;
1564:                    }
1565:                }
1566:                return str.substring(i, strLen);
1567:            }
1568:
1569:            /*
1570:             *----------------------------------------------------------------------
1571:             *
1572:             * TrimLeft --
1573:             *
1574:             *	|>description<|
1575:             *
1576:             * Results:
1577:             *	|>None.<|
1578:             *
1579:             * Side effects:
1580:             *	|>None.<|
1581:             *
1582:             *----------------------------------------------------------------------
1583:             */
1584:
1585:            static String TrimLeft(String str) {
1586:                return TrimLeft(str, " \n\t\r");
1587:            }
1588:
1589:            /*
1590:             *----------------------------------------------------------------------
1591:             *
1592:             * TrimRight --
1593:             *
1594:             *	Trim characters in "pattern" off the right of a string
1595:             * 	If pattern isn't supplied, whitespace is trimmed
1596:             *
1597:             * Results:
1598:             *	|>None.<|
1599:             *
1600:             * Side effects:
1601:             *	|>None.<|
1602:             *
1603:             *----------------------------------------------------------------------
1604:             */
1605:
1606:            static String TrimRight(String str, String pattern) {
1607:                char[] strArray = str.toCharArray();
1608:                char[] patternArray = pattern.toCharArray();
1609:                final int patLen = patternArray.length;
1610:                char c, p;
1611:                int j;
1612:                boolean done;
1613:                int last = strArray.length - 1;
1614:
1615:                // Remove trailing characters...
1616:
1617:                while (last >= 0) {
1618:                    c = strArray[last];
1619:                    done = true;
1620:                    for (j = 0; j < patLen; j++) {
1621:                        p = patternArray[j];
1622:                        if (c == p || (p == ' ' && Character.isWhitespace(c))) {
1623:                            done = false;
1624:                            break;
1625:                        }
1626:                    }
1627:                    if (done) {
1628:                        break;
1629:                    }
1630:                    last--;
1631:                }
1632:                return str.substring(0, last + 1);
1633:            }
1634:
1635:            static String TrimRight(String str) {
1636:                return TrimRight(str, " \n\t\r");
1637:            }
1638:
1639:            /*
1640:             *----------------------------------------------------------------------
1641:             *
1642:             * getBoolean --
1643:             *
1644:             *	Given a string, return a boolean value corresponding
1645:             *	to the string.
1646:             *
1647:             * Results:
1648:             *	
1649:             *
1650:             * Side effects:
1651:             *	None.
1652:             *
1653:             *----------------------------------------------------------------------
1654:             */
1655:
1656:            static boolean getBoolean(Interp interp, // The current interpreter.
1657:                    String string) // The string representation of the boolean.
1658:                    throws TclException // For malformed boolean values.
1659:            {
1660:                String s = string.toLowerCase();
1661:
1662:                // The length of 's' needs to be > 1 if it begins with 'o', 
1663:                // in order to compare between "on" and "off".
1664:
1665:                int slen = s.length();
1666:
1667:                if (slen > 0) {
1668:                    char c = s.charAt(0);
1669:                    switch (c) {
1670:                    case '0':
1671:                        if (slen == 1) {
1672:                            return false;
1673:                        }
1674:                        break;
1675:                    case '1':
1676:                        if (slen == 1) {
1677:                            return true;
1678:                        }
1679:                        break;
1680:                    case 'f':
1681:                        if ("false".startsWith(s)) {
1682:                            return false;
1683:                        }
1684:                        break;
1685:                    case 'o':
1686:                        if (slen > 1 && "on".startsWith(s)) {
1687:                            return true;
1688:                        }
1689:                        if (slen > 1 && "off".startsWith(s)) {
1690:                            return false;
1691:                        }
1692:                        break;
1693:                    case 'n':
1694:                        if ("no".startsWith(s)) {
1695:                            return false;
1696:                        }
1697:                        break;
1698:                    case 't':
1699:                        if ("true".startsWith(s)) {
1700:                            return true;
1701:                        }
1702:                        break;
1703:                    case 'y':
1704:                        if ("yes".startsWith(s)) {
1705:                            return true;
1706:                        }
1707:                        break;
1708:                    }
1709:                }
1710:
1711:                throw new TclException(interp,
1712:                        "expected boolean value but got \"" + string + "\"");
1713:            }
1714:
1715:            /*
1716:             *-----------------------------------------------------------------------------
1717:             *
1718:             * getActualPlatform -- 
1719:             *
1720:             *	This static procedure returns the integer code for the actuall platform
1721:             *	on which Jacl is running.
1722:             *
1723:             * Results:
1724:             *	Returns and integer.
1725:             *
1726:             * Side effects:
1727:             *	None.
1728:             *
1729:             *-----------------------------------------------------------------------------
1730:             */
1731:
1732:            final static int getActualPlatform() {
1733:                if (Util.isWindows()) {
1734:                    return JACL.PLATFORM_WINDOWS;
1735:                }
1736:                if (Util.isMac()) {
1737:                    return JACL.PLATFORM_MAC;
1738:                }
1739:                return JACL.PLATFORM_UNIX;
1740:            }
1741:
1742:            /*
1743:             *----------------------------------------------------------------------
1744:             *
1745:             * isUnix --
1746:             *
1747:             *	Returns true if running on a Unix platform.
1748:             *
1749:             * Results:
1750:             *	Returns a boolean.
1751:             *
1752:             * Side effects:
1753:             *	 None.
1754:             *
1755:             *----------------------------------------------------------------------
1756:             */
1757:
1758:            final static boolean isUnix() {
1759:                if (isMac() || isWindows()) {
1760:                    return false;
1761:                }
1762:                return true;
1763:            }
1764:
1765:            /*
1766:             *----------------------------------------------------------------------
1767:             *
1768:             * isMac --
1769:             *
1770:             *	Returns true if running on a Mac platform. Note that
1771:             *	this method returns false for Mac OSX.
1772:             *
1773:             * Results:
1774:             *	Returns a boolean.
1775:             *
1776:             * Side effects:
1777:             *	 None.
1778:             *
1779:             *----------------------------------------------------------------------
1780:             */
1781:
1782:            final static boolean isMac() {
1783:                String os = System.getProperty("os.name").toLowerCase();
1784:                if (os.startsWith("mac") && !os.endsWith("x")) {
1785:                    return true;
1786:                }
1787:                return false;
1788:            }
1789:
1790:            /*
1791:             *----------------------------------------------------------------------
1792:             *
1793:             * isWindows --
1794:             *
1795:             *	Returns true if running on a Windows platform.
1796:             *
1797:             * Results:
1798:             *	Returns a boolean.
1799:             *
1800:             * Side effects:
1801:             *	 None.
1802:             *
1803:             *----------------------------------------------------------------------
1804:             */
1805:
1806:            final static boolean isWindows() {
1807:                String os = System.getProperty("os.name");
1808:                if (os.toLowerCase().startsWith("win")) {
1809:                    return true;
1810:                }
1811:                return false;
1812:            }
1813:
1814:            /*
1815:             *----------------------------------------------------------------------
1816:             *
1817:             * isJacl --
1818:             *
1819:             *	Returns true if running in Jacl. This method is used
1820:             *	by conditional logic in the tcljava module.
1821:             *
1822:             * Results:
1823:             *	Returns a boolean.
1824:             *
1825:             * Side effects:
1826:             *	 None.
1827:             *
1828:             *----------------------------------------------------------------------
1829:             */
1830:
1831:            static boolean isJacl() {
1832:                return true;
1833:            }
1834:
1835:            /*
1836:             *----------------------------------------------------------------------
1837:             *
1838:             * looksLikeInt --
1839:             *
1840:             *	Returns true when isJacl() is true and this string looks
1841:             *	like an integer.
1842:             *
1843:             * Results:
1844:             *	Returns a boolean.
1845:             *
1846:             * Side effects:
1847:             *	 None.
1848:             *
1849:             *----------------------------------------------------------------------
1850:             */
1851:
1852:            static boolean looksLikeInt(String s) {
1853:                return Expression.looksLikeInt(s, s.length(), 0, true);
1854:            }
1855:
1856:            /*
1857:             *----------------------------------------------------------------------
1858:             *
1859:             * setupPrecisionTrace --
1860:             *
1861:             *	Sets up the variable trace of the tcl_precision variable.
1862:             *
1863:             * Results:
1864:             *	None.
1865:             *
1866:             * Side effects:
1867:             *	A variable trace is set up for the tcl_precision global
1868:             *	variable.
1869:             *
1870:             *----------------------------------------------------------------------
1871:             */
1872:
1873:            static void setupPrecisionTrace(Interp interp) // Current interpreter.
1874:            {
1875:                try {
1876:                    interp.traceVar("tcl_precision", new PrecTraceProc(),
1877:                            TCL.GLOBAL_ONLY | TCL.TRACE_WRITES
1878:                                    | TCL.TRACE_READS | TCL.TRACE_UNSETS);
1879:                } catch (TclException e) {
1880:                    throw new TclRuntimeError("unexpected TclException: " + e);
1881:                }
1882:            }
1883:
1884:            /*
1885:             *----------------------------------------------------------------------
1886:             *
1887:             * printDouble --
1888:             *
1889:             *	Returns the string form of a double number. The exact formatting
1890:             *	of the string depends on the tcl_precision variable.
1891:             *
1892:             * Results:
1893:             * 	Returns the string form of double number.
1894:             *
1895:             * Side effects:
1896:             *	None.
1897:             *
1898:             *----------------------------------------------------------------------
1899:             */
1900:
1901:            static String printDouble(double number) // The number to format into a string.
1902:            {
1903:                String s = FormatCmd.toString(number, precision, 10);
1904:                int length = s.length();
1905:                for (int i = 0; i < length; i++) {
1906:                    if ((s.charAt(i) == '.') || Character.isLetter(s.charAt(i))) {
1907:                        return s;
1908:                    }
1909:                }
1910:                return s + ".0";
1911:            }
1912:
1913:            /*
1914:             *----------------------------------------------------------------------
1915:             *
1916:             * tryGetSystemProperty --
1917:             *
1918:             *	Tries to get a system property. If it fails because of security
1919:             *	exceptions, then return the default value.
1920:             *
1921:             * Results:
1922:             *	The value of the system property. If it fails because of security
1923:             *	exceptions, then return the default value.
1924:             *
1925:             * Side effects:
1926:             *	None.
1927:             *
1928:             *----------------------------------------------------------------------
1929:             */
1930:
1931:            static String tryGetSystemProperty(String propName, // Name of the property
1932:                    String defautlValue) // Default value.
1933:            {
1934:                try {
1935:                    return System.getProperty(propName);
1936:                } catch (SecurityException e) {
1937:                    return defautlValue;
1938:                }
1939:            }
1940:
1941:        } // end Util
1942:
1943:        /* 
1944:         *----------------------------------------------------------------------
1945:         *
1946:         * PrecTraceProc.java --
1947:         *
1948:         *	 The PrecTraceProc class is used to implement variable traces for
1949:         * 	the tcl_precision variable to control precision used when
1950:         * 	converting floating-point values to strings.
1951:         *
1952:         *----------------------------------------------------------------------
1953:         */
1954:
1955:        final class PrecTraceProc implements  VarTrace {
1956:
1957:            // Maximal precision supported by Tcl.
1958:
1959:            static final int TCL_MAX_PREC = 17;
1960:
1961:            /*
1962:             *----------------------------------------------------------------------
1963:             *
1964:             * traceProc --
1965:             *
1966:             *	This function gets called when the tcl_precision variable is
1967:             *	accessed in the given interpreter.
1968:             *
1969:             * Results:
1970:             *	None.
1971:             *
1972:             * Side effects:
1973:             *	If the new value doesn't make sense then this procedure undoes
1974:             *	the effect of the variable modification. Otherwise it modifies
1975:             *	Util.precision that's used by Util.printDouble().
1976:             *
1977:             *----------------------------------------------------------------------
1978:             */
1979:
1980:            public void traceProc(Interp interp, // Interpreter containing variable.
1981:                    String name1, // Name of variable.
1982:                    String name2, // Second part of variable name.
1983:                    int flags) // Information about what happened.
1984:                    throws TclException // If the action is a TCL.TRACES_WRITE and
1985:            // the new value doesn't make sense.
1986:            {
1987:                // If the variable is unset, then recreate the trace and restore
1988:                // the default value of the format string.
1989:
1990:                if ((flags & TCL.TRACE_UNSETS) != 0) {
1991:                    if (((flags & TCL.TRACE_DESTROYED) != 0)
1992:                            && ((flags & TCL.INTERP_DESTROYED) == 0)) {
1993:                        interp.traceVar(name1, name2, new PrecTraceProc(),
1994:                                TCL.GLOBAL_ONLY | TCL.TRACE_WRITES
1995:                                        | TCL.TRACE_READS | TCL.TRACE_UNSETS);
1996:                        Util.precision = Util.DEFAULT_PRECISION;
1997:                    }
1998:                    return;
1999:                }
2000:
2001:                // When the variable is read, reset its value from our shared
2002:                // value. This is needed in case the variable was modified in
2003:                // some other interpreter so that this interpreter's value is
2004:                // out of date.
2005:
2006:                if ((flags & TCL.TRACE_READS) != 0) {
2007:                    interp.setVar(name1, name2, Util.precision, flags
2008:                            & TCL.GLOBAL_ONLY);
2009:                    return;
2010:                }
2011:
2012:                // The variable is being written. Check the new value and disallow
2013:                // it if it isn't reasonable.
2014:                //
2015:                // (ToDo) Disallow it if this is a safe interpreter (we don't want
2016:                // safe interpreters messing up the precision of other
2017:                // interpreters).
2018:
2019:                TclObject tobj = null;
2020:                try {
2021:                    tobj = interp.getVar(name1, name2,
2022:                            (flags & TCL.GLOBAL_ONLY));
2023:                } catch (TclException e) {
2024:                    // Do nothing when var does not exist.
2025:                }
2026:
2027:                String value;
2028:
2029:                if (tobj != null) {
2030:                    value = tobj.toString();
2031:                } else {
2032:                    value = "";
2033:                }
2034:
2035:                StrtoulResult r = interp.strtoulResult;
2036:                Util.strtoul(value, 0, 10, r);
2037:
2038:                if ((r.value <= 0) || (r.value > TCL_MAX_PREC)
2039:                        || (r.value > 100) || (r.index == 0)
2040:                        || (r.index != value.length())) {
2041:                    interp
2042:                            .setVar(name1, name2, Util.precision,
2043:                                    TCL.GLOBAL_ONLY);
2044:                    throw new TclException(interp,
2045:                            "improper value for precision");
2046:                }
2047:
2048:                Util.precision = (int) r.value;
2049:            }
2050:
2051:        } // end PrecTraceProc
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.