Source Code Cross Referenced for ScanCmd.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) 


001:        /*
002:         * ScanCmd.java
003:         *
004:         * Copyright (c) 1997 Sun Microsystems, Inc.
005:         *
006:         * See the file "license.terms" for information on usage and
007:         * redistribution of this file, and for a DISCLAIMER OF ALL
008:         * WARRANTIES.
009:         * 
010:         * RCS: @(#) $Id: ScanCmd.java,v 1.5 2006/05/22 21:23:35 mdejong Exp $
011:         *
012:         */
013:
014:        package tcl.lang;
015:
016:        import java.util.*;
017:
018:        /**
019:         * This class implements the built-in "scan" command in Tcl.
020:         * 
021:         */
022:
023:        class ScanCmd implements  Command {
024:            /**
025:             * This procedure is invoked to process the "scan" Tcl command.
026:             * See the user documentation for details on what it does.
027:             *
028:             * Each iteration of the cmdProc compares the scanArr's current index to 
029:             * the frmtArr's index.  If the chars are equal then the indicies are
030:             * incremented.  If a '%' is found in the frmtArr, the formatSpecifier 
031:             * is parced from the frmtArr, the corresponding value is extracted from 
032:             * the scanArr, and that value is set in the Tcl Interp.
033:             * 
034:             * If the chars are not equal, or the conversion fails, the boolean 
035:             * scanArrDone is set to true, indicating the scanArr is not to be 
036:             * parced and no new values are to be set.  However the frmtArr is still 
037:             * parced because of the priority of error messages.  In the C version 
038:             * of Tcl, bad format specifiers throw errors before incorrect argument 
039:             * input or other scan errors.  Thus we need to parce the entire frmtArr 
040:             * to verify correct formating.  This is dumb and inefficient but it is 
041:             * consistent w/ the current C-version of Tcl.
042:             */
043:
044:            public void cmdProc(Interp interp, TclObject argv[])
045:                    throws TclException {
046:
047:                if (argv.length < 3) {
048:                    throw new TclNumArgsException(interp, 1, argv,
049:                            "string format ?varName varName ...?");
050:                }
051:                ;
052:
053:                StrtoulResult strul; // Return value for parcing the scanArr when
054:                // extracting integers/longs
055:                StrtodResult strd; // Return value for parcing the scanArr when
056:                // extracting doubles
057:                char[] scanArr; // Array containing parce info
058:                char[] frmtArr; // Array containing info on how to 
059:                // parse the scanArr
060:                int scanIndex; // Index into the scan array
061:                int frmtIndex; // Index into the frmt array
062:                int tempIndex; // Temporary index holder
063:                int argIndex; // Index into the current arg
064:                int width; // Stores the user specified result width 
065:                int base; // Base of the integer being converted
066:                int numUnMatched; // Number of fields actually set.
067:                int numMatched; // Number of fields actually matched.
068:                int i; // Generic variable
069:                char ch; // Generic variable
070:                boolean cont; // Used in loops to indicate when to stop
071:                boolean scanOK; // Set to false if strtoul/strtod fails
072:                boolean scanArrDone; // Set to false if strtoul/strtod fails
073:                boolean widthFlag; // True is width is specified
074:                boolean discardFlag; // If a "%*" is in the formatString dont 
075:                // write output to arg
076:
077:                scanArr = argv[1].toString().toCharArray();
078:                frmtArr = argv[2].toString().toCharArray();
079:                width = base = numMatched = numUnMatched = 0;
080:                scanIndex = frmtIndex = 0;
081:                scanOK = true;
082:                scanArrDone = false;
083:                argIndex = 3;
084:
085:                // Skip all (if any) of the white space before getting to a char
086:
087:                frmtIndex = skipWhiteSpace(frmtArr, frmtIndex);
088:
089:                // Search through the frmtArr.  If the next char is a '%' parse the
090:                // next chars and determine the type (if any) of the format specifier.
091:                // If the scanArr has been fully searched, do nothing but incerment
092:                // "numUnMatched".  The reason to continue the frmtArr search is for 
093:                // consistency in output.  Previously scan format errors were reported
094:                // before arg input mismatch, so this maintains the same level of error
095:                // checking.
096:
097:                while (frmtIndex < frmtArr.length) {
098:                    discardFlag = widthFlag = false;
099:                    cont = true;
100:
101:                    // Parce the format array and read in the correct value from the 
102:                    // scan array.  When the correct value is retrieved, set the 
103:                    // variable (from argv) in the interp.
104:
105:                    if (frmtArr[frmtIndex] == '%') {
106:
107:                        frmtIndex++;
108:                        checkOverFlow(interp, frmtArr, frmtIndex);
109:
110:                        // Two '%'s in a row, do nothing...
111:
112:                        if (frmtArr[frmtIndex] == '%') {
113:                            frmtIndex++;
114:                            scanIndex++;
115:                            continue;
116:                        }
117:
118:                        // Check for a discard field flag
119:
120:                        if (frmtArr[frmtIndex] == '*') {
121:                            discardFlag = true;
122:                            frmtIndex++;
123:                            checkOverFlow(interp, frmtArr, frmtIndex);
124:                        }
125:
126:                        // Check for a width field and accept the 'h', 'l', 'L'
127:                        // characters, but do nothing with them.
128:                        //
129:                        // Note: The order of the width specifier and the other
130:                        // chars is unordered, so we need to iterate until all
131:                        // of the specifiers are identified.
132:
133:                        while (cont) {
134:                            cont = false;
135:
136:                            switch (frmtArr[frmtIndex]) {
137:                            case 'h':
138:                            case 'l':
139:                            case 'L': {
140:                                // Just ignore these values
141:
142:                                frmtIndex++;
143:                                cont = true;
144:                                break;
145:                            }
146:                            default: {
147:                                if (Character.isDigit(frmtArr[frmtIndex])) {
148:                                    strul = interp.strtoulResult;
149:                                    Util.strtoul(new String(frmtArr),
150:                                            frmtIndex, base, strul);
151:                                    width = (int) strul.value;
152:                                    frmtIndex = strul.index;
153:                                    widthFlag = true;
154:                                    cont = true;
155:                                    strul = null;
156:                                }
157:                            }
158:                            }
159:                            checkOverFlow(interp, frmtArr, frmtIndex);
160:                        }
161:
162:                        // On all conversion specifiers except 'c', move the
163:                        // scanIndex to the next non-whitespace.
164:
165:                        ch = frmtArr[frmtIndex];
166:                        if ((ch != 'c') && (ch != '[') && !scanArrDone) {
167:                            scanIndex = skipWhiteSpace(scanArr, scanIndex);
168:                        }
169:                        if (scanIndex >= scanArr.length) {
170:                            scanArrDone = true;
171:                        }
172:
173:                        if ((scanIndex < scanArr.length) && (ch != 'c')
174:                                && (ch != '[')) {
175:                            // The width+scanIndex might be greater than
176:                            // the scanArr so we need to re-adjust when this
177:                            // happens.
178:
179:                            if (widthFlag
180:                                    && (width + scanIndex > scanArr.length)) {
181:                                width = scanArr.length - scanIndex;
182:                            }
183:                        }
184:
185:                        if (scanIndex >= scanArr.length) {
186:                            scanArrDone = true;
187:                        }
188:
189:                        // Foreach iteration we want strul and strd to be
190:                        // null since we error check on this case.
191:
192:                        strul = null;
193:                        strd = null;
194:
195:                        switch (ch) {
196:                        case 'd':
197:                        case 'o':
198:                        case 'x': {
199:
200:                            if (!scanArrDone) {
201:
202:                                if (ch == 'd') {
203:                                    base = 10;
204:                                } else if (ch == 'o') {
205:                                    base = 8;
206:                                } else {
207:                                    base = 16;
208:                                }
209:
210:                                // If the widthFlag is set then convert only 
211:                                // "width" characters to an ascii representation, 
212:                                // else read in until the end of the integer.  The 
213:                                // scanIndex is moved to the point where we stop
214:                                // reading in.
215:
216:                                strul = interp.strtoulResult;
217:                                if (widthFlag) {
218:                                    Util.strtoul(new String(scanArr, 0, width
219:                                            + scanIndex), scanIndex, base,
220:                                            strul);
221:                                } else {
222:                                    Util.strtoul(new String(scanArr),
223:                                            scanIndex, base, strul);
224:                                }
225:                                if (strul.errno != 0) {
226:                                    scanOK = false;
227:                                    break;
228:                                }
229:                                scanIndex = strul.index;
230:
231:                                if (!discardFlag) {
232:                                    i = (int) strul.value;
233:                                    testAndSetVar(interp, argv, argIndex++,
234:                                            TclInteger.newInstance(i));
235:                                }
236:                            }
237:                            break;
238:                        }
239:                        case 'c': {
240:                            if (widthFlag) {
241:                                errorCharFieldWidth(interp);
242:                            }
243:                            if (!discardFlag && !scanArrDone) {
244:                                testAndSetVar(
245:                                        interp,
246:                                        argv,
247:                                        argIndex++,
248:                                        TclInteger
249:                                                .newInstance(scanArr[scanIndex++]));
250:                            }
251:                            break;
252:                        }
253:                        case 's': {
254:                            if (!scanArrDone) {
255:                                // If the widthFlag is set then read only "width"
256:                                // characters into the string, else read in until 
257:                                // the first whitespace or endArr is found.  The 
258:                                // scanIndex is moved to the point where we stop 
259:                                // reading in.
260:
261:                                tempIndex = scanIndex;
262:                                if (!widthFlag) {
263:                                    width = scanArr.length;
264:                                }
265:                                for (i = 0; (scanIndex < scanArr.length)
266:                                        && (i < width); i++) {
267:                                    ch = scanArr[scanIndex];
268:                                    if ((ch == ' ') || (ch == '\n')
269:                                            || (ch == '\r') || (ch == '\t')
270:                                            || (ch == '\f')) {
271:                                        break;
272:                                    }
273:                                    scanIndex++;
274:                                }
275:
276:                                if (!discardFlag) {
277:                                    String str = new String(scanArr, tempIndex,
278:                                            scanIndex - tempIndex);
279:                                    testAndSetVar(interp, argv, argIndex++,
280:                                            TclString.newInstance(str));
281:                                }
282:                            }
283:                            break;
284:                        }
285:                        case 'e':
286:                        case 'f':
287:                        case 'g': {
288:                            if (!scanArrDone) {
289:                                // If the wisthFlag is set then read only "width"
290:                                // characters into the string, else read in until 
291:                                // the first whitespace or endArr is found.  The 
292:                                // scanIndex is moved to the point where we stop 
293:                                // reading in.
294:
295:                                if (widthFlag) {
296:                                    strd = interp.strtodResult;
297:                                    Util.strtod(new String(scanArr, 0, width
298:                                            + scanIndex), scanIndex, -1, strd);
299:                                } else {
300:                                    strd = interp.strtodResult;
301:                                    Util.strtod(new String(scanArr), scanIndex,
302:                                            -1, strd);
303:                                }
304:                                if (strd.errno != 0) {
305:                                    scanOK = false;
306:                                    break;
307:                                }
308:                                scanIndex = strd.index;
309:
310:                                if (!discardFlag) {
311:                                    double d = strd.value;
312:                                    testAndSetVar(interp, argv, argIndex++,
313:                                            TclDouble.newInstance(d));
314:                                }
315:                            }
316:                            break;
317:                        }
318:                        case '[': {
319:                            boolean charMatchFound = false;
320:                            boolean charNotMatch = false;
321:                            char[] tempArr;
322:                            int startIndex;
323:                            int endIndex;
324:                            String unmatched = "unmatched [ in format string";
325:
326:                            if ((++frmtIndex) >= frmtArr.length) {
327:                                throw new TclException(interp, unmatched);
328:                            }
329:
330:                            if (frmtArr[frmtIndex] == '^') {
331:                                charNotMatch = true;
332:                                frmtIndex += 2;
333:                            } else {
334:                                frmtIndex++;
335:                            }
336:                            tempIndex = frmtIndex - 1;
337:
338:                            if (frmtIndex >= frmtArr.length) {
339:                                throw new TclException(interp, unmatched);
340:                            }
341:
342:                            // Extract the list of chars for matching.
343:
344:                            while (frmtArr[frmtIndex] != ']') {
345:                                if ((++frmtIndex) >= frmtArr.length) {
346:                                    throw new TclException(interp, unmatched);
347:                                }
348:                            }
349:                            tempArr = new String(frmtArr, tempIndex, frmtIndex
350:                                    - tempIndex).toCharArray();
351:
352:                            startIndex = scanIndex;
353:                            if (charNotMatch) {
354:                                // Format specifier contained a '^' so interate
355:                                // until one of the chars in tempArr is found.
356:
357:                                while (scanOK && !charMatchFound) {
358:                                    if (scanIndex >= scanArr.length) {
359:                                        scanOK = false;
360:                                        break;
361:                                    }
362:                                    for (i = 0; i < tempArr.length; i++) {
363:                                        if (tempArr[i] == scanArr[scanIndex]) {
364:                                            charMatchFound = true;
365:                                            break;
366:                                        }
367:                                    }
368:                                    if (widthFlag
369:                                            && ((scanIndex - startIndex) >= width)) {
370:                                        break;
371:                                    }
372:                                    if (!charMatchFound) {
373:                                        scanIndex++;
374:                                    }
375:                                }
376:                            } else {
377:                                // Iterate until the char in the scanArr is not 
378:                                // in the tempArr.
379:
380:                                charMatchFound = true;
381:                                while (scanOK && charMatchFound) {
382:                                    if (scanIndex >= scanArr.length) {
383:                                        scanOK = false;
384:                                        break;
385:                                    }
386:                                    charMatchFound = false;
387:                                    for (i = 0; i < tempArr.length; i++) {
388:                                        if (tempArr[i] == scanArr[scanIndex]) {
389:                                            charMatchFound = true;
390:                                            break;
391:                                        }
392:                                    }
393:                                    if (widthFlag
394:                                            && (scanIndex - startIndex) >= width) {
395:                                        break;
396:                                    }
397:                                    if (charMatchFound) {
398:                                        scanIndex++;
399:                                    }
400:
401:                                }
402:                            }
403:
404:                            // Indicates nothing was found.
405:
406:                            endIndex = scanIndex - startIndex;
407:                            if (endIndex <= 0) {
408:                                scanOK = false;
409:                                break;
410:                            }
411:
412:                            if (!discardFlag) {
413:                                String str = new String(scanArr, startIndex,
414:                                        endIndex);
415:                                testAndSetVar(interp, argv, argIndex++,
416:                                        TclString.newInstance(str));
417:                            }
418:                            break;
419:                        }
420:                        default: {
421:                            errorBadField(interp, ch);
422:                        }
423:                        }
424:
425:                        // As long as the scan was successful (scanOK), the format
426:                        // specifier did not contain a '*' (discardFlag), and
427:                        // we are not at the end of the scanArr (scanArrDone);
428:                        // increment the num of vars set in the interp.  Otherwise
429:                        // increment the number of valid format specifiers.
430:
431:                        if (scanOK && !discardFlag && !scanArrDone) {
432:                            numMatched++;
433:                        } else if ((scanArrDone || !scanOK) && !discardFlag) {
434:                            numUnMatched++;
435:                        }
436:                        frmtIndex++;
437:
438:                    } else if (scanIndex < scanArr.length
439:                            && scanArr[scanIndex] == frmtArr[frmtIndex]) {
440:                        // No '%' was found, but the characters matched
441:
442:                        scanIndex++;
443:                        frmtIndex++;
444:
445:                    } else {
446:                        // No '%' found and the characters int frmtArr & scanArr
447:                        // did not match.
448:
449:                        frmtIndex++;
450:
451:                    }
452:
453:                }
454:
455:                // The numMatched is the return value: a count of the num of vars set.
456:                // While the numUnMatched is the number of formatSpecifiers that
457:                // passed the parsing stage, but did not match anything in the scanArr.
458:
459:                if ((numMatched + numUnMatched) != (argv.length - 3)) {
460:                    errorDiffVars(interp);
461:                }
462:                interp.setResult(numMatched);
463:
464:            }
465:
466:            /**
467:             * Given an array and an index into it, move the index forward
468:             * until a non-whitespace char is found.
469:             *
470:             * @param arr   - the array to search
471:             * @param index - where to begin the search
472:             * @return The index value where the whitespace ends.
473:             */
474:
475:            private int skipWhiteSpace(char[] arr, int index) {
476:                boolean cont;
477:                do {
478:                    if (index >= arr.length) {
479:                        return index;
480:                    }
481:                    cont = false;
482:                    switch (arr[index]) {
483:                    case '\t':
484:                    case '\n':
485:                    case '\r':
486:                    case '\f':
487:                    case ' ': {
488:                        cont = true;
489:                        index++;
490:                    }
491:                    }
492:                } while (cont);
493:
494:                return index;
495:            }
496:
497:            /**
498:             * Called whenever the cmdProc wants to set an interp value.  
499:             * This method <ol>
500:             * <li> verifies that there exisits a varName from the argv array, 
501:             * <li> that the variable either dosent exisit or is of type scalar
502:             * <li> set the variable in interp if (1) and (2) are OK
503:             * </ol>
504:             * 
505:             * @param interp   - the Tcl interpreter
506:             * @param argv     - the argument array
507:             * @param argIndex - the current index into the argv array
508:             * @param tobj     - the TclObject that the varName equals
509:             * 
510:             */
511:
512:            private static void testAndSetVar(Interp interp, TclObject[] argv,
513:                    int argIndex, TclObject tobj) throws TclException {
514:                if (argIndex < argv.length) {
515:                    try {
516:                        interp.setVar(argv[argIndex].toString(), tobj, 0);
517:                    } catch (TclException e) {
518:                        throw new TclException(interp,
519:                                "couldn't set variable \""
520:                                        + argv[argIndex].toString() + "\"");
521:                    }
522:                } else {
523:                    errorDiffVars(interp);
524:                }
525:            }
526:
527:            /**
528:             * Called whenever the frmtIndex in the cmdProc is changed.  It verifies
529:             * the the array index is still within the bounds of the array.  If no
530:             * throw error.
531:             * @param interp  - The TclInterp which called the cmdProc method .
532:             * @param arr     - The array to be checked.
533:             * @param index   - The new value for the array index.
534:             */
535:
536:            private static final void checkOverFlow(Interp interp, char[] arr,
537:                    int index) throws TclException {
538:                if ((index >= arr.length) || (index < 0)) {
539:                    throw new TclException(interp,
540:                            "\"%n$\" argument index out of range");
541:                }
542:            }
543:
544:            /**
545:             * Called whenever the number of varName args do not match the number
546:             * of found and valid formatSpecifiers (matched and unmatched).
547:             *
548:             * @param interp  - The TclInterp which called the cmdProc method .
549:             */
550:
551:            private static final void errorDiffVars(Interp interp)
552:                    throws TclException {
553:
554:                throw new TclException(interp,
555:                        "different numbers of variable names and field specifiers");
556:            }
557:
558:            /**
559:             * Called whenever the current char in the frmtArr is erroneous
560:             *
561:             * @param interp  - The TclInterp which called the cmdProc method .
562:             * @param fieldSpecifier  - The erroneous character
563:             */
564:
565:            private static final void errorBadField(Interp interp,
566:                    char fieldSpecifier) throws TclException {
567:                throw new TclException(interp,
568:                        "bad scan conversion character \"" + fieldSpecifier
569:                                + "\"");
570:            }
571:
572:            /**
573:             * Called whenever the a width field is used in a char ('c') format 
574:             * specifier
575:             *
576:             * @param interp  - The TclInterp which called the cmdProc method .
577:             */
578:
579:            private static final void errorCharFieldWidth(Interp interp)
580:                    throws TclException {
581:                throw new TclException(interp,
582:                        "field width may not be specified in %c conversion");
583:            }
584:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.