001: /*
002: * GlobCmd.java
003: *
004: * This file contains the Jacl implementation of the built-in Tcl "glob"
005: * command.
006: *
007: * Copyright (c) 1997-1998 Sun Microsystems, Inc.
008: *
009: * See the file "license.terms" for information on usage and
010: * redistribution of this file, and for a DISCLAIMER OF ALL
011: * WARRANTIES.
012: *
013: * RCS: @(#) $Id: GlobCmd.java,v 1.6 2006/02/08 23:53:47 mdejong Exp $
014: *
015: */
016:
017: package tcl.lang;
018:
019: import java.util.*;
020: import java.io.File;
021: import java.lang.reflect.Array;
022:
023: /*
024: * This class implements the built-in "glob" command in Tcl.
025: */
026:
027: class GlobCmd implements Command {
028:
029: /*
030: * Special characters that are used for string matching.
031: */
032:
033: private static final char[] specCharArr = { '*', '[', ']', '?',
034: '\\' };
035:
036: /*
037: * Options to the glob command.
038: */
039:
040: static final private String validOptions[] = { "-nocomplain", "--" };
041: static final private int OPT_NOCOMPLAIN = 0;
042: static final private int OPT_LAST = 1;
043:
044: /*
045: *-----------------------------------------------------------------------------
046: *
047: * cmdProc --
048: *
049: * This procedure is invoked to process the "glob" Tcl command.
050: * See the user documentation for details on what it does.
051: *
052: * Results:
053: * None.
054: *
055: * Side effects:
056: * See the user documentation.
057: *
058: *-----------------------------------------------------------------------------
059: */
060:
061: public void cmdProc(Interp interp, // Current interp to eval the file cmd.
062: TclObject argv[]) // Args passed to the glob command.
063: throws TclException {
064: boolean noComplain = false; // If false, error msg will be returned
065: int index; // index of the char just after the end
066: // of the user name
067: int firstArg = 1; // index of the first non-switch arg
068: int i; // generic index
069: String arg; // generic arg string
070: String head = ""; // abs path of user name if provided
071: String tail = ""; // the remaining file path and pattern
072: TclObject resultList; // list of files that match the pattern
073:
074: for (boolean last = false; (firstArg < argv.length) && (!last); firstArg++) {
075:
076: if (!argv[firstArg].toString().startsWith("-")) {
077: break;
078: }
079: int opt = TclIndex.get(interp, argv[firstArg],
080: validOptions, "switch", 1);
081: switch (opt) {
082: case OPT_NOCOMPLAIN:
083: noComplain = true;
084: break;
085: case OPT_LAST:
086: last = true;
087: break;
088: default:
089: throw new TclException(interp,
090: "GlobCmd.cmdProc: bad option " + opt
091: + " index to validOptions");
092: }
093: }
094:
095: if (firstArg >= argv.length) {
096: throw new TclNumArgsException(interp, 1, argv,
097: "?switches? name ?name ...?");
098: }
099:
100: resultList = TclList.newInstance();
101: resultList.preserve();
102:
103: for (i = firstArg; i < argv.length; i++) {
104: arg = argv[i].toString();
105:
106: String separators; // The system-specific file separators
107: switch (JACL.PLATFORM) {
108: case JACL.PLATFORM_WINDOWS:
109: separators = "/\\:";
110: break;
111: case JACL.PLATFORM_MAC:
112: if (arg.indexOf(':') == -1) {
113: separators = "/";
114: } else {
115: separators = ":";
116: }
117: break;
118: default:
119: separators = "/";
120: }
121:
122: // Perform tilde substitution, if needed.
123:
124: index = 0;
125: if (arg.startsWith("~")) {
126: // Find the first path separator after the tilde.
127:
128: for (; index < arg.length(); index++) {
129: char c = arg.charAt(index);
130: if (c == '\\') {
131: if (separators.indexOf(arg.charAt(index + 1)) != -1) {
132: break;
133: }
134: } else if (separators.indexOf(c) != -1) {
135: break;
136: }
137: }
138:
139: // Determine the home directory for the specified user. Note
140: // that we don't allow special characters in the user name.
141:
142: if (strpbrk(arg.substring(1, index).toCharArray(),
143: specCharArr) < 0) {
144: try {
145: head = FileUtil.doTildeSubst(interp, arg
146: .substring(1, index));
147: } catch (TclException e) {
148: if (noComplain) {
149: head = null;
150: } else {
151: throw new TclException(interp, e
152: .getMessage());
153: }
154: }
155: } else {
156: if (!noComplain) {
157: throw new TclException(interp,
158: "globbing characters not supported in user names");
159: }
160: head = null;
161: }
162:
163: if (head == null) {
164: if (noComplain) {
165: interp.setResult("");
166: return;
167: } else {
168: return;
169: }
170: }
171: if (index != arg.length()) {
172: index++;
173: }
174: }
175:
176: tail = arg.substring(index);
177:
178: try {
179: doGlob(interp, separators, new StringBuffer(head),
180: tail, resultList);
181: } catch (TclException e) {
182: if (noComplain) {
183: continue;
184: } else {
185: throw new TclException(interp, e.getMessage());
186: }
187: }
188: }
189:
190: // If the list is empty and the nocomplain switch was not set then
191: // generate and throw an exception. Always release the TclList upon
192: // completion.
193:
194: try {
195: if ((TclList.getLength(interp, resultList) == 0)
196: && !noComplain) {
197: String sep = "";
198: StringBuffer ret = new StringBuffer();
199:
200: ret.append("no files matched glob pattern");
201: ret.append((argv.length == 2) ? " \"" : "s \"");
202:
203: for (i = firstArg; i < argv.length; i++) {
204: ret.append(sep + argv[i].toString());
205: if (i == firstArg) {
206: sep = " ";
207: }
208: }
209: ret.append("\"");
210: throw new TclException(interp, ret.toString());
211: } else if (TclList.getLength(interp, resultList) > 0) {
212: interp.setResult(resultList);
213: }
214: } finally {
215: resultList.release();
216: }
217: }
218:
219: /*
220: *-----------------------------------------------------------------------------
221: *
222: * SkipToChar --
223: *
224: * This function traverses a glob pattern looking for the next
225: * unquoted occurance of the specified character at the same braces
226: * nesting level.
227: *
228: * Results:
229: * Returns -1 if no match is made. Otherwise returns the index in str in
230: * which the match is found.
231: *
232: * Side effects:
233: * None.
234: *
235: *-----------------------------------------------------------------------------
236: */
237:
238: private static int SkipToChar(String str, // Strubg to check.
239: int sIndex, // Index in str to begin search.
240: char match) // Ccharacter to find.
241: {
242: int level, length, i;
243: boolean quoted = false;
244: char c;
245:
246: level = 0;
247:
248: for (i = sIndex, length = str.length(); i < length; i++) {
249: if (quoted) {
250: quoted = false;
251: continue;
252: }
253: c = str.charAt(i);
254: if ((level == 0) && (c == match)) {
255: return i;
256: }
257: if (c == '{') {
258: level++;
259: } else if (c == '}') {
260: level--;
261: } else if (c == '\\') {
262: quoted = true;
263: }
264: }
265: return -1;
266: }
267:
268: /*
269: *-----------------------------------------------------------------------------
270: *
271: * TclDoGlob --
272: *
273: * This recursive procedure forms the heart of the globbing
274: * code. It performs a depth-first traversal of the tree
275: * given by the path name to be globbed. The directory and
276: * remainder are assumed to be native format paths.
277: *
278: * Results:
279: * None.
280: *
281: * Side effects:
282: * None.
283: *
284: *-----------------------------------------------------------------------------
285: */
286:
287: private static final void doGlob(Interp interp, // Interpreter to use for error reporting
288: String separators, // String containing separator characters
289: StringBuffer headBuf, // Completely expanded prefix.
290: String tail, // The unexpanded remainder of the path.
291: TclObject resultList) // list of files that match the pattern
292: throws TclException {
293: int count = 0; // Counts the number of leading file
294: // spearators for the tail.
295: int pIndex; // Current index into tail
296: int tailIndex; // First char after initial file
297: // separators of the tail
298: int tailLen = tail.length(); // Cache the length of the tail
299: int headLen = headBuf.length(); // Cache the length of the head
300: int baseLen; // Len of the substring from tailIndex
301: // to the current specChar []*?{}\\
302: int openBraceIndex; // Index of the current open brace
303: int closeBraceIndex; // Index of the current closed brace
304: int firstSpecCharIndex; // Index of the FSC, if any
305: char lastChar = 0; // Used to see if last char is a file
306: // separator.
307: char ch; // Generic storage variable
308: boolean quoted; // True if a char is '\\'
309:
310: if (headLen > 0) {
311: lastChar = headBuf.charAt(headLen - 1);
312: }
313:
314: // Consume any leading directory separators, leaving tailIndex
315: // just past the last initial separator.
316:
317: String name = tail;
318: for (tailIndex = 0; tailIndex < tailLen; tailIndex++) {
319: char c = tail.charAt(tailIndex);
320: if ((c == '\\')
321: && ((tailIndex + 1) < tailLen)
322: && (separators.indexOf(tail.charAt(tailIndex + 1)) != -1)) {
323: tailIndex++;
324: } else if (separators.indexOf(c) == -1) {
325: break;
326: }
327: count++;
328: }
329:
330: // Deal with path separators. On the Mac, we have to watch out
331: // for multiple separators, since they are special in Mac-style
332: // paths.
333:
334: switch (JACL.PLATFORM) {
335: case JACL.PLATFORM_MAC:
336:
337: if (separators.charAt(0) == '/') {
338: if (((headLen == 0) && (count == 0))
339: || ((headLen > 0) && (lastChar != ':'))) {
340: headBuf.append(":");
341: }
342: } else {
343: if (count == 0) {
344: if ((headLen > 0) && (lastChar != ':')) {
345: headBuf.append(":");
346: }
347: } else {
348: if (lastChar == ':') {
349: count--;
350: }
351: while (count-- > 0) {
352: headBuf.append(":");
353: }
354: }
355: }
356: break;
357:
358: case JACL.PLATFORM_WINDOWS:
359: // If this is a drive relative path, add the colon and the
360: // trailing slash if needed. Otherwise add the slash if
361: // this is the first absolute element, or a later relative
362: // element. Add an extra slash if this is a UNC path.
363: if (name.startsWith(":")) {
364: headBuf.append(":");
365: if (count > 1) {
366: headBuf.append("/");
367: }
368: } else if ((tailIndex < tailLen)
369: && (((headLen > 0) && (separators.indexOf(lastChar) == -1)) || ((headLen == 0) && (count > 0)))) {
370: headBuf.append("/");
371: if ((headLen == 0) && (count > 1)) {
372: headBuf.append("/");
373: }
374: }
375: break;
376: default:
377: // Add a separator if this is the first absolute element, or
378: // a later relative element.
379:
380: if ((tailIndex < tailLen)
381: && (((headLen > 0) && (separators.indexOf(lastChar) == -1)) || ((headLen == 0) && (count > 0)))) {
382: headBuf.append("/");
383: }
384: }
385:
386: // Look for the first matching pair of braces or the first
387: // directory separator that is not inside a pair of braces.
388:
389: openBraceIndex = closeBraceIndex = -1;
390: quoted = false;
391:
392: for (pIndex = tailIndex; pIndex != tailLen; pIndex++) {
393: ch = tail.charAt(pIndex);
394: if (quoted) {
395: quoted = false;
396: } else if (ch == '\\') {
397: quoted = true;
398: if (((pIndex + 1) < tailLen)
399: && (separators.indexOf(tail.charAt(pIndex + 1)) != -1)) {
400: // Quoted directory separator.
401:
402: break;
403: }
404: } else if (separators.indexOf(ch) != -1) {
405: // Unquoted directory separator.
406:
407: break;
408: } else if (ch == '{') {
409: openBraceIndex = pIndex;
410: pIndex++;
411: if ((closeBraceIndex = SkipToChar(tail, pIndex, '}')) != -1) {
412: break;
413: }
414: throw new TclException(interp,
415: "unmatched open-brace in file name");
416: } else if (ch == '}') {
417: throw new TclException(interp,
418: "unmatched close-brace in file name");
419: }
420: }
421:
422: // Substitute the alternate patterns from the braces and recurse.
423:
424: if (openBraceIndex != -1) {
425: int nextIndex;
426: StringBuffer baseBuf = new StringBuffer();
427:
428: // For each element within in the outermost pair of braces,
429: // append the element and the remainder to the fixed portion
430: // before the first brace and recursively call doGlob.
431:
432: baseBuf.append(tail.substring(tailIndex, openBraceIndex));
433: baseLen = baseBuf.length();
434: headLen = headBuf.length();
435:
436: for (pIndex = openBraceIndex; pIndex < closeBraceIndex;) {
437: pIndex++;
438: nextIndex = SkipToChar(tail, pIndex, ',');
439: if (nextIndex == -1 || nextIndex > closeBraceIndex) {
440: nextIndex = closeBraceIndex;
441: }
442:
443: headBuf.setLength(headLen);
444: baseBuf.setLength(baseLen);
445:
446: baseBuf.append(tail.substring(pIndex, nextIndex));
447: baseBuf.append(tail.substring(closeBraceIndex + 1));
448:
449: pIndex = nextIndex;
450: doGlob(interp, separators, headBuf, baseBuf.toString(),
451: resultList);
452: }
453: return;
454: }
455:
456: // At this point, there are no more brace substitutions to perform on
457: // this path component. The variable p is pointing at a quoted or
458: // unquoted directory separator or the end of the string. So we need
459: // to check for special globbing characters in the current pattern.
460: // We avoid modifying tail if p is pointing at the end of the string.
461:
462: if (pIndex < tailLen) {
463: firstSpecCharIndex = strpbrk(tail.substring(0, pIndex)
464: .toCharArray(), specCharArr);
465: } else {
466: firstSpecCharIndex = strpbrk(tail.substring(tailIndex)
467: .toCharArray(), specCharArr);
468: }
469:
470: if (firstSpecCharIndex != -1) {
471: // Look for matching files in the current directory. matchFiles
472: // may recursively call TclDoGlob. For each file that matches,
473: // it will add the match onto the interp->result, or call TclDoGlob
474: // if there are more characters to be processed.
475:
476: matchFiles(interp, separators, headBuf.toString(), tail
477: .substring(tailIndex), (pIndex - tailIndex),
478: resultList);
479: return;
480: }
481: headBuf.append(tail.substring(tailIndex, pIndex));
482: if (pIndex < tailLen) {
483: doGlob(interp, separators, headBuf, tail.substring(pIndex),
484: resultList);
485: return;
486: }
487:
488: // There are no more wildcards in the pattern and no more unprocessed
489: // characters in the tail, so now we can construct the path and verify
490: // the existence of the file.
491:
492: String head;
493: switch (JACL.PLATFORM) {
494: case JACL.PLATFORM_MAC:
495: if (headBuf.toString().indexOf(':') == -1) {
496: headBuf.append(":");
497: }
498: head = headBuf.toString();
499: break;
500: case JACL.PLATFORM_WINDOWS:
501: if (headBuf.length() == 0) {
502: if (((name.length() > 1) && (name.charAt(0) == '\\') && ((name
503: .charAt(1) == '/') || (name.charAt(1) == '\\')))
504: || ((name.length() > 0) && (name.charAt(0) == '/'))) {
505: headBuf.append("\\");
506: } else {
507: headBuf.append(".");
508: }
509: }
510: head = headBuf.toString().replace('\\', '/');
511: break;
512: default:
513: if (headBuf.length() == 0) {
514: if (name.startsWith("\\/") || name.startsWith("/")) {
515: headBuf.append("/");
516: } else {
517: headBuf.append(".");
518: }
519: }
520: head = headBuf.toString();
521: }
522: addFileToResult(interp, head, separators, resultList);
523: }
524:
525: /*
526: *-----------------------------------------------------------------------------
527: *
528: * matchFiles --
529: *
530: * This routine is used by the globbing code to search a
531: * directory for all files which match a given pattern.
532: * This is a routine contains platform-specific code.
533: *
534: * Results:
535: * If the tail argument is NULL, then the matching files are
536: * added to the result list. Otherwise, TclDoGlob is called
537: * recursively for each matching subdirectory.
538: *
539: * Side effects:
540: * None.
541: *
542: *-----------------------------------------------------------------------------
543: */
544:
545: private static final void matchFiles(Interp interp, // Interpreter to use for error reporting
546: String separators, // String containing separator characters
547: String dirName, // Path of directory to search.
548: String pattern, // Pattern to match against.
549: int pIndex, // Index of end of pattern.
550: TclObject resultList) // list of files that match the pattern
551: throws TclException {
552: boolean matchHidden; // True if were matching hidden file
553: int patternEnd = pIndex; // Stores end index of the pattern
554: int dirLen = dirName.length(); // Caches the len of the dirName
555: int patLen = pattern.length(); // Caches the len of the pattern
556: String[] dirListing; // Listing of files in dirBuf
557: File dirObj; // File object of dirBuf
558: StringBuffer dirBuf = new StringBuffer();
559: // Converts the dirName to string
560: // buffer or initializes it with '.'
561:
562: switch (JACL.PLATFORM) {
563: case JACL.PLATFORM_WINDOWS:
564: // Convert the path to normalized form since some interfaces only
565: // accept backslashes. Also, ensure that the directory ends with
566: // a separator character.
567:
568: if (dirLen == 0) {
569: dirBuf.append("./");
570: } else {
571: dirBuf.append(dirName);
572: char c = dirBuf.charAt(dirLen - 1);
573: if (((c == ':') && (dirLen == 2))
574: || (separators.indexOf(c) == -1)) {
575: dirBuf.append("/");
576: }
577: }
578:
579: // All comparisons should be case insensitive on Windows.
580:
581: pattern = pattern.toLowerCase();
582: break;
583: case JACL.PLATFORM_MAC:
584: // Fall through to unix case--mac is not yet implemented.
585:
586: default:
587: // Make sure that the directory part of the name really is a
588: // directory. If the directory name is "", use the name "."
589: // instead, because some UNIX systems don't treat "" like "."
590: // automatically. Keep the "" for use in generating file names,
591: // otherwise "glob foo.c" would return "./foo.c".
592:
593: if (dirLen == 0) {
594: dirBuf.append(".");
595: } else {
596: dirBuf.append(dirName);
597: }
598: }
599:
600: dirObj = createAbsoluteFileObj(interp, dirBuf.toString());
601: if (!dirObj.isDirectory()) {
602: return;
603: }
604:
605: // Check to see if the pattern needs to compare with hidden files.
606: // Get a list of the directory's contents.
607:
608: if (pattern.startsWith(".") || pattern.startsWith("\\.")) {
609: matchHidden = true;
610: dirListing = addHiddenToDirList(dirObj);
611: } else {
612: matchHidden = false;
613: dirListing = dirObj.list();
614: }
615:
616: // Iterate over the directory's contents.
617:
618: if (dirListing.length == 0) {
619: // Strip off a trailing '/' if necessary, before reporting
620: // the error.
621:
622: if (dirName.endsWith("/")) {
623: dirName = dirName.substring(0, (dirLen - 1));
624: }
625: }
626:
627: // Clean up the end of the pattern and the tail pointer. Leave
628: // the tail pointing to the first character after the path
629: // separator following the pattern, or NULL. Also, ensure that
630: // the pattern is null-terminated.
631:
632: if ((pIndex < patLen) && (pattern.charAt(pIndex) == '\\')) {
633: pIndex++;
634: }
635: if (pIndex < (patLen - 1)) {
636: pIndex++;
637: }
638:
639: for (int i = 0; i < dirListing.length; i++) {
640: // Don't match names starting with "." unless the "." is
641: // present in the pattern.
642:
643: if (!matchHidden && (dirListing[i].startsWith("."))) {
644: continue;
645: }
646:
647: // Now check to see if the file matches. If there are more
648: // characters to be processed, then ensure matching files are
649: // directories before calling TclDoGlob. Otherwise, just add
650: // the file to the resultList.
651:
652: String tmp = dirListing[i];
653: if (JACL.PLATFORM == JACL.PLATFORM_WINDOWS) {
654: tmp = tmp.toLowerCase();
655: }
656: if (Util.stringMatch(tmp, pattern.substring(0, patternEnd))) {
657:
658: dirBuf.setLength(dirLen);
659: dirBuf.append(dirListing[i]);
660: if (pIndex == pattern.length()) {
661: addFileToResult(interp, dirBuf.toString(),
662: separators, resultList);
663: } else {
664: dirObj = createAbsoluteFileObj(interp, dirBuf
665: .toString());
666: if (dirObj.isDirectory()) {
667: dirBuf.append("/");
668: doGlob(interp, separators, dirBuf, pattern
669: .substring(patternEnd + 1), resultList);
670: }
671: }
672: }
673: }
674: }
675:
676: /*
677: *-----------------------------------------------------------------------------
678: *
679: * strpbrk --
680: *
681: * Returns the index into src of the first occurrence in
682: * array src of any character from the array matches, or
683: * a -1 if no character from matches exists in src.
684: *
685: * Results:
686: * Returns the index of first occurence of a match or -1 if no match
687: * found.
688: *
689: * Side effects:
690: * None.
691: *
692: *-----------------------------------------------------------------------------
693: */
694:
695: private static final int strpbrk(char[] src, // The char array to search.
696: char[] matches) // The chars to search for in src.
697: {
698: for (int i = 0; i < src.length; i++) {
699: for (int j = 0; j < matches.length; j++) {
700: if (src[i] == matches[j]) {
701: return (i);
702: }
703: }
704: }
705: return -1;
706: }
707:
708: /*
709: *-----------------------------------------------------------------------------
710: *
711: * addHiddenToDirList --
712: *
713: * The method dirObj.list() returns a list of files in the directory.
714: * This method adds the files "." and ".." to create a full list.
715: *
716: * Results:
717: * Retruns the full list of files in the directory dirObj.
718: *
719: * Side effects:
720: * None.
721: *
722: *-----------------------------------------------------------------------------
723: */
724:
725: private static final String[] addHiddenToDirList(File dirObj) // File object to list contents of
726: {
727: String[] dirListing; // Listing of files in dirObj
728: String[] fullListing; // dirListing + .. and .
729: int i, arrayLen;
730:
731: dirListing = dirObj.list();
732: arrayLen = Array.getLength(dirListing);
733:
734: try {
735: fullListing = (String[]) Array.newInstance(String.class,
736: arrayLen + 2);
737: } catch (Exception e) {
738: return dirListing;
739: }
740: for (i = 0; i < arrayLen; i++) {
741: fullListing[i] = dirListing[i];
742: }
743: fullListing[arrayLen] = ".";
744: fullListing[arrayLen + 1] = "..";
745:
746: return fullListing;
747: }
748:
749: /*
750: *-----------------------------------------------------------------------------
751: *
752: * addFileToResult --
753: *
754: * This recursive procedure forms the heart of the globbing
755: * code. It performs a depth-first traversal of the tree
756: * given by the path name to be globbed. The directory and
757: * remainder are assumed to be native format paths.
758: *
759: * Results:
760: * None.
761: *
762: * Side effects:
763: * Appends a string to TclObject resultList.
764: *
765: *-----------------------------------------------------------------------------
766: */
767:
768: private static void addFileToResult(Interp interp, // Interpreter to use for error reporting
769: String fileName, // Name of file to add to result list
770: String separators, // String containing separator characters
771: TclObject resultList) // list of files that match the pattern
772:
773: throws TclException {
774: String prettyFileName = fileName;
775: int prettyLen = fileName.length();
776:
777: // Java IO reuqires Windows volumes [A-Za-z]: to be followed by '\\'.
778:
779: if ((JACL.PLATFORM == JACL.PLATFORM_WINDOWS)
780: && (prettyLen >= 2) && (fileName.charAt(1) == ':')) {
781: if (prettyLen == 2) {
782: fileName = fileName + '\\';
783: } else if (fileName.charAt(2) != '\\') {
784: fileName = fileName.substring(0, 2) + '\\'
785: + fileName.substring(2);
786: }
787: }
788:
789: TclObject arrayObj[] = TclList.getElements(interp, FileUtil
790: .splitAndTranslate(interp, fileName));
791: fileName = FileUtil.joinPath(interp, arrayObj, 0,
792: arrayObj.length);
793:
794: File f;
795: if (FileUtil.getPathType(fileName) == FileUtil.PATH_ABSOLUTE) {
796: f = FileUtil.getNewFileObj(interp, fileName);
797: } else {
798: f = new File(interp.getWorkingDir(), fileName);
799: }
800:
801: // If the last character is a spearator, make sure the file is an
802: // existing directory, otherwise check that the file exists.
803:
804: if ((prettyLen > 0)
805: && (separators.indexOf(prettyFileName
806: .charAt(prettyLen - 1)) != -1)) {
807: if (f.isDirectory()) {
808: TclList.append(interp, resultList, TclString
809: .newInstance(prettyFileName));
810: }
811: } else if (f.exists()) {
812: TclList.append(interp, resultList, TclString
813: .newInstance(prettyFileName));
814: }
815: }
816:
817: /*
818: *-----------------------------------------------------------------------------
819: *
820: * createAbsoluteFileObj --
821: *
822: * Creates and returns a File object from the String fileName. If
823: * fileName is not null, it verifies that the file path is absolute,
824: * setting it if it is not.
825: *
826: * Results:
827: * Returns the fully qualified File object.
828: *
829: * Side effects:
830: * None.
831: *
832: *-----------------------------------------------------------------------------
833: */
834:
835: private static final File createAbsoluteFileObj(Interp interp, // Interpreter for error reports.
836: String fileName) // Name of file.
837: throws TclException {
838: if (fileName.equals("")) {
839: return (interp.getWorkingDir());
840: }
841:
842: if ((JACL.PLATFORM == JACL.PLATFORM_WINDOWS)
843: && (fileName.length() >= 2)
844: && (fileName.charAt(1) == ':')) {
845: String tmp = null;
846: if (fileName.length() == 2) {
847: tmp = fileName.substring(0, 2) + '\\';
848: } else if (fileName.charAt(2) != '\\') {
849: tmp = fileName.substring(0, 2) + '\\'
850: + fileName.substring(2);
851: }
852: if (tmp != null) {
853: return FileUtil.getNewFileObj(interp, tmp);
854: }
855: }
856:
857: return FileUtil.getNewFileObj(interp, fileName);
858: }
859:
860: } // end GlobCmd class
|