KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > Pathname


1 /*
2  * Pathname.java
3  *
4  * Copyright (C) 2003-2004 Peter Graves
5  * $Id: Pathname.java,v 1.68 2004/09/18 02:06:57 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 public class Pathname extends LispObject
30 {
31     protected LispObject host = NIL;
32     protected LispObject device = NIL;
33     protected LispObject directory = NIL;
34     protected LispObject name = NIL;
35
36     // A string, NIL, :wild or :unspecific.
37
protected LispObject type = NIL;
38
39     // A positive integer, or NIL, :WILD, :UNSPECIFIC, or :NEWEST.
40
protected LispObject version = NIL;
41
42     private String JavaDoc namestring;
43
44     protected Pathname()
45     {
46     }
47
48     public Pathname(String JavaDoc s) throws ConditionThrowable
49     {
50         init(s);
51     }
52
53     public Pathname(URL JavaDoc url) throws ConditionThrowable
54     {
55         String JavaDoc protocol = url.getProtocol();
56         if ("jar".equals(protocol)) {
57             String JavaDoc s = url.getPath();
58             if (s.startsWith("file:")) {
59                 int index = s.indexOf("!/");
60                 String JavaDoc container = s.substring(5, index);
61                 if (Utilities.isPlatformWindows()) {
62                     if (container.length() > 0 && container.charAt(0) == '/')
63                         container = container.substring(1);
64                 }
65                 device = new Pathname(container);
66                 s = s.substring(index + 1);
67                 Pathname p = new Pathname(s);
68                 directory = p.directory;
69                 name = p.name;
70                 type = p.type;
71                 return;
72             }
73         } else if ("file".equals(protocol)) {
74             String JavaDoc s = url.getPath();
75             if (s != null && s.startsWith("file:")) {
76                 init(s.substring(5));
77                 return;
78             }
79         }
80         signal(new LispError("Unsupported URL: \"" + url.toString() + '"'));
81     }
82
83     private final void init(String JavaDoc s) throws ConditionThrowable
84     {
85         if (s == null)
86             return;
87         if (Utilities.isPlatformWindows())
88             s = s.replace('/', '\\');
89         // Jar file support.
90
int bang = s.indexOf("!/");
91         if (bang >= 0) {
92             Pathname container = new Pathname(s.substring(0, bang));
93             LispObject containerType = container.type;
94             if (containerType instanceof AbstractString) {
95                 if (containerType.getStringValue().equalsIgnoreCase("jar")) {
96                     device = container;
97                     s = s.substring(bang + 1);
98                     Pathname p = new Pathname(s);
99                     directory = p.directory;
100                     name = p.name;
101                     type = p.type;
102                     return;
103                 }
104             }
105         }
106         if (Utilities.isPlatformUnix()) {
107             if (s.equals("~"))
108                 s = System.getProperty("user.home").concat("/");
109             else if (s.startsWith("~/"))
110                 s = System.getProperty("user.home").concat(s.substring(1));
111         }
112         namestring = s;
113         if (s.equals(".") || s.equals("./")) {
114             directory = new Cons(Keyword.RELATIVE);
115             return;
116         }
117         if (s.equals("..") || s.equals("../")) {
118             directory = list2(Keyword.RELATIVE, Keyword.BACK);
119             return;
120         }
121         if (Utilities.isPlatformWindows()) {
122             if (s.length() >= 2 && s.charAt(1) == ':') {
123                 device = new SimpleString(s.charAt(0));
124                 s = s.substring(2);
125             }
126         }
127         String JavaDoc d = null;
128         // Find last file separator char.
129
if (Utilities.isPlatformWindows()) {
130             for (int i = s.length(); i-- > 0;) {
131                 char c = s.charAt(i);
132                 if (c == '/' || c == '\\') {
133                     d = s.substring(0, i + 1);
134                     s = s.substring(i + 1);
135                     break;
136                 }
137             }
138         } else {
139             for (int i = s.length(); i-- > 0;) {
140                 if (s.charAt(i) == '/') {
141                     d = s.substring(0, i + 1);
142                     s = s.substring(i + 1);
143                     break;
144                 }
145             }
146         }
147         if (d != null) {
148             if (s.equals("..")) {
149                 d = d.concat(s);
150                 s = "";
151             }
152             directory = parseDirectory(d);
153         }
154         if (s.startsWith(".")) {
155             name = new SimpleString(s);
156             return;
157         }
158         int index = s.lastIndexOf('.');
159         String JavaDoc n = null;
160         String JavaDoc t = null;
161         if (index > 0) {
162             n = s.substring(0, index);
163             t = s.substring(index + 1);
164         } else if (s.length() > 0)
165             n = s;
166         if (n != null) {
167             if (n.equals("*"))
168                 name = Keyword.WILD;
169             else
170                 name = new SimpleString(n);
171         }
172         if (t != null) {
173             if (t.equals("*"))
174                 type = Keyword.WILD;
175             else
176                 type = new SimpleString(t);
177         }
178     }
179
180     private static final LispObject parseDirectory(String JavaDoc d)
181         throws ConditionThrowable
182     {
183         if (d.equals("/") || (Utilities.isPlatformWindows() && d.equals("\\")))
184             return new Cons(Keyword.ABSOLUTE);
185         LispObject result;
186         if (d.startsWith("/") || (Utilities.isPlatformWindows() && d.startsWith("\\")))
187             result = new Cons(Keyword.ABSOLUTE);
188         else
189             result = new Cons(Keyword.RELATIVE);
190         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(d, "/\\");
191         while (st.hasMoreTokens()) {
192             String JavaDoc token = st.nextToken();
193             LispObject obj;
194             if (token.equals("*"))
195                 obj = Keyword.WILD;
196             else if (token.equals("**"))
197                 obj = Keyword.WILD_INFERIORS;
198             else if (token.equals("..")) {
199                 if (result.car() instanceof AbstractString) {
200                     result = result.cdr();
201                     continue;
202                 }
203                 obj= Keyword.UP;
204             } else
205                 obj = new SimpleString(token);
206             result = new Cons(obj, result);
207         }
208         return result.nreverse();
209     }
210
211     public LispObject typeOf()
212     {
213         return Symbol.PATHNAME;
214     }
215
216     public LispClass classOf()
217     {
218         return BuiltInClass.PATHNAME;
219     }
220
221     public LispObject typep(LispObject type) throws ConditionThrowable
222     {
223         if (type == Symbol.PATHNAME)
224             return T;
225         if (type == BuiltInClass.PATHNAME)
226             return T;
227         return super.typep(type);
228     }
229
230     public final LispObject getDevice()
231     {
232         return device;
233     }
234
235     public String JavaDoc getNamestring() throws ConditionThrowable
236     {
237         if (namestring != null)
238             return namestring;
239         if (name == NIL && type != NIL) {
240             Debug.assertTrue(namestring == null);
241             return null;
242         }
243         if (directory instanceof AbstractString)
244             Debug.assertTrue(false);
245         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(getDirectoryNamestring());
246         if (name instanceof AbstractString)
247             sb.append(name.getStringValue());
248         else if (name == Keyword.WILD)
249             sb.append('*');
250         if (type != NIL) {
251             sb.append('.');
252             if (type instanceof AbstractString)
253                 sb.append(type.getStringValue());
254             else if (type == Keyword.WILD)
255                 sb.append('*');
256             else
257                 Debug.assertTrue(false);
258         }
259         return namestring = sb.toString();
260     }
261
262     private String JavaDoc getDirectoryNamestring() throws ConditionThrowable
263     {
264         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
265         // "If a pathname is converted to a namestring, the symbols NIL and
266
// :UNSPECIFIC cause the field to be treated as if it were empty. That
267
// is, both NIL and :UNSPECIFIC cause the component not to appear in
268
// the namestring." 19.2.2.2.3.1
269
if (device == NIL)
270             ;
271         else if (device == Keyword.UNSPECIFIC)
272             ;
273         else if (device instanceof AbstractString) {
274             sb.append(device.getStringValue());
275             sb.append(':');
276         } else if (device instanceof Pathname) {
277             sb.append(((Pathname)device).getNamestring());
278             sb.append("!");
279         } else
280             Debug.assertTrue(false);
281         final char separatorChar;
282         if (device instanceof Pathname)
283             separatorChar = '/'; // Jar file.
284
else
285             separatorChar = File.separatorChar;
286         if (directory != NIL) {
287             LispObject temp = directory;
288             LispObject part = temp.car();
289             if (part == Keyword.ABSOLUTE)
290                 sb.append(separatorChar);
291             else if (part == Keyword.RELATIVE)
292                 ;
293             else
294                 signal(new LispError("Unsupported directory component " +
295                                      part.writeToString() + "."));
296             temp = temp.cdr();
297             while (temp != NIL) {
298                 part = temp.car();
299                 if (part instanceof AbstractString)
300                     sb.append(part.getStringValue());
301                 else if (part == Keyword.WILD)
302                     sb.append("*");
303                 else
304                     signal(new LispError("Unsupported directory component " +
305                                          part.writeToString() + "."));
306                 sb.append(separatorChar);
307                 temp = temp.cdr();
308             }
309         }
310         return sb.toString();
311     }
312
313     public boolean equal(LispObject obj) throws ConditionThrowable
314     {
315         if (this == obj)
316             return true;
317         if (obj instanceof Pathname) {
318             Pathname p = (Pathname) obj;
319             if (Utilities.isPlatformWindows()) {
320                 if (!host.equalp(p.host))
321                     return false;
322                 if (!device.equalp(p.device))
323                     return false;
324                 if (!directory.equalp(p.directory))
325                     return false;
326                 if (!name.equalp(p.name))
327                     return false;
328                 if (!type.equalp(p.type))
329                     return false;
330                 if (!version.equalp(p.version))
331                     return false;
332             } else {
333                 // Unix.
334
if (!host.equal(p.host))
335                     return false;
336                 if (!device.equal(p.device))
337                     return false;
338                 if (!directory.equal(p.directory))
339                     return false;
340                 if (!name.equal(p.name))
341                     return false;
342                 if (!type.equal(p.type))
343                     return false;
344                 if (!version.equal(p.version))
345                     return false;
346             }
347             return true;
348         }
349         return false;
350     }
351
352     public boolean equalp(LispObject obj) throws ConditionThrowable
353     {
354         return equal(obj);
355     }
356
357     public int sxhash() throws ConditionThrowable
358     {
359         return ((host.sxhash() ^
360                  device.sxhash() ^
361                  directory.sxhash() ^
362                  name.sxhash() ^
363                  type.sxhash() ^
364                  version.sxhash()) & 0x7fffffff);
365     }
366
367     private boolean matches(Pathname wildcard) throws ConditionThrowable
368     {
369         if (Utilities.isPlatformWindows()) {
370             if (wildcard.device != Keyword.WILD) {
371                 if (!device.equalp(wildcard.device))
372                     return false;
373             }
374             if (wildcard.name != Keyword.WILD) {
375                 if (!name.equalp(wildcard.name))
376                     return false;
377             }
378             if (wildcard.directory != Keyword.WILD) {
379                 if (!directory.equalp(wildcard.directory))
380                     return false;
381             }
382             if (wildcard.type != Keyword.WILD) {
383                 if (!type.equalp(wildcard.type))
384                     return false;
385             }
386         } else {
387             // Unix.
388
if (wildcard.name != Keyword.WILD) {
389                 if (!name.equal(wildcard.name))
390                     return false;
391             }
392             if (wildcard.directory != Keyword.WILD) {
393                 if (!directory.equal(wildcard.directory))
394                     return false;
395             }
396             if (wildcard.type != Keyword.WILD) {
397                 if (!type.equal(wildcard.type))
398                     return false;
399             }
400         }
401         return true;
402     }
403
404     public String JavaDoc writeToString() throws ConditionThrowable
405     {
406         try {
407             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("#P");
408             boolean printReadably = (_PRINT_READABLY_.symbolValue() != NIL);
409             boolean useNamestring;
410             String JavaDoc s = getNamestring();
411             if (s != null) {
412                 useNamestring = true;
413                 if (printReadably) {
414                     // We have a namestring. Check for non-NIL values of pathname
415
// components that can't be read from the namestring.
416
if (host != NIL || version != NIL) {
417                         useNamestring = false;
418                     } else if (Utilities.isPlatformWindows()) {
419                         if (version != NIL)
420                             useNamestring = false;
421                     }
422                 }
423             } else
424                 useNamestring = false;
425             if (useNamestring) {
426                 sb.append(quoteEscape(s));
427             } else {
428                 sb.append('(');
429                 if (host != NIL) {
430                     sb.append(":HOST ");
431                     sb.append(host.writeToString());
432                     sb.append(' ');
433                 }
434                 if (device != NIL) {
435                     sb.append(":DEVICE ");
436                     sb.append(device.writeToString());
437                     sb.append(' ');
438                 }
439                 if (directory != NIL) {
440                     sb.append(":DIRECTORY ");
441                     sb.append(directory.writeToString());
442                     sb.append(" ");
443                 }
444                 if (name != NIL) {
445                     sb.append(":NAME ");
446                     sb.append(name.writeToString());
447                     sb.append(' ');
448                 }
449                 if (type != NIL) {
450                     sb.append(":TYPE ");
451                     sb.append(type.writeToString());
452                     sb.append(' ');
453                 }
454                 if (version != NIL) {
455                     sb.append(":VERSION ");
456                     sb.append(version.writeToString());
457                     sb.append(' ');
458                 }
459                 if (sb.charAt(sb.length() - 1) == ' ')
460                     sb.setLength(sb.length() - 1);
461                 sb.append(')');
462             }
463             return sb.toString();
464         }
465         catch (ConditionThrowable t) {
466             return unreadableString("PATHNAME");
467         }
468     }
469
470     private static final String JavaDoc quoteEscape(String JavaDoc s) throws ConditionThrowable
471     {
472         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
473         sb.append('"');
474         final int limit = s.length();
475         for (int i = 0; i < limit; i++) {
476             char c = s.charAt(i);
477             if (c == '\"' || c == '\\')
478                 sb.append('\\');
479             sb.append(c);
480         }
481         sb.append('"');
482         return sb.toString();
483     }
484
485     public static Pathname parseNamestring(String JavaDoc namestring)
486         throws ConditionThrowable
487     {
488         return new Pathname(namestring);
489     }
490
491     public static Pathname coerceToPathname(LispObject arg)
492         throws ConditionThrowable
493     {
494         if (arg instanceof Pathname)
495             return (Pathname) arg;
496         if (arg instanceof AbstractString)
497             return new Pathname(arg.getStringValue());
498         if (arg instanceof FileStream)
499             return ((FileStream)arg).getPathname();
500         signal(new TypeError(arg.writeToString() +
501                              " cannot be converted to a pathname."));
502         // Not reached.
503
return null;
504     }
505
506     private static final void checkCaseArgument(LispObject arg)
507         throws ConditionThrowable
508     {
509         if (arg != Keyword.COMMON && arg != Keyword.LOCAL)
510             signal(new TypeError(arg, list3(Symbol.MEMBER, Keyword.COMMON,
511                                             Keyword.LOCAL)));
512     }
513
514     private static final Primitive2 _PATHNAME_HOST =
515         new Primitive2("%pathname-host", PACKAGE_SYS, false)
516     {
517         public LispObject execute(LispObject first, LispObject second)
518             throws ConditionThrowable
519         {
520             checkCaseArgument(second);
521             return coerceToPathname(first).host;
522         }
523     };
524
525     private static final Primitive2 _PATHNAME_DEVICE =
526         new Primitive2("%pathname-device", PACKAGE_SYS, false)
527     {
528         public LispObject execute(LispObject first, LispObject second)
529             throws ConditionThrowable
530         {
531             checkCaseArgument(second);
532             return coerceToPathname(first).device;
533         }
534     };
535
536     private static final Primitive2 _PATHNAME_DIRECTORY =
537         new Primitive2("%pathname-directory", PACKAGE_SYS, false)
538     {
539         public LispObject execute(LispObject first, LispObject second)
540             throws ConditionThrowable
541         {
542             checkCaseArgument(second);
543             return coerceToPathname(first).directory;
544         }
545     };
546
547     private static final Primitive2 _PATHNAME_NAME =
548         new Primitive2("%pathname-name", PACKAGE_SYS, false)
549     {
550         public LispObject execute(LispObject first, LispObject second)
551             throws ConditionThrowable
552         {
553             checkCaseArgument(second);
554             return coerceToPathname(first).name;
555         }
556     };
557
558     private static final Primitive2 _PATHNAME_TYPE =
559         new Primitive2("%pathname-type", PACKAGE_SYS, false)
560     {
561         public LispObject execute(LispObject first, LispObject second)
562             throws ConditionThrowable
563         {
564             checkCaseArgument(second);
565             return coerceToPathname(first).type;
566         }
567     };
568
569     private static final Primitive1 PATHNAME_VERSION =
570         new Primitive1("pathname-version", "pathname")
571     {
572         public LispObject execute(LispObject arg) throws ConditionThrowable
573         {
574             return coerceToPathname(arg).version;
575         }
576     };
577
578     // ### namestring
579
// namestring pathname => namestring
580
private static final Primitive1 NAMESTRING =
581         new Primitive1("namestring", "pathname")
582     {
583         public LispObject execute(LispObject arg) throws ConditionThrowable
584         {
585             Pathname pathname = coerceToPathname(arg);
586             String JavaDoc namestring = pathname.getNamestring();
587             if (namestring == null)
588                 signal(new SimpleError("Pathname has no namestring: " +
589                                        pathname.writeToString() + "."));
590             return new SimpleString(namestring);
591         }
592     };
593
594     // ### directory-namestring
595
// directory-namestring pathname => namestring
596
private static final Primitive1 DIRECTORY_NAMESTRING =
597         new Primitive1("directory-namestring", "pathname")
598     {
599         public LispObject execute(LispObject arg) throws ConditionThrowable
600         {
601             return new SimpleString(coerceToPathname(arg).getDirectoryNamestring());
602         }
603     };
604
605     // ### pathname
606
// pathname pathspec => pathname
607
private static final Primitive1 PATHNAME =
608         new Primitive1("pathname", "pathspec")
609     {
610         public LispObject execute(LispObject arg) throws ConditionThrowable
611         {
612             return coerceToPathname(arg);
613         }
614     };
615
616     // ### make-pathname
617
private static final Primitive MAKE_PATHNAME =
618         new Primitive("make-pathname",
619                       "&key host device directory name type version defaults case")
620     {
621         public LispObject execute(LispObject[] args)
622             throws ConditionThrowable
623         {
624             return _makePathname(args);
625         }
626     };
627
628     public static final Pathname makePathname(LispObject args)
629         throws ConditionThrowable
630     {
631         return _makePathname(args.copyToArray());
632     }
633
634     private static final Pathname _makePathname(LispObject[] args)
635         throws ConditionThrowable
636     {
637         if (args.length % 2 != 0)
638             signal(new ProgramError("Odd number of keyword arguments."));
639         Pathname p = new Pathname();
640         Pathname defaults = null;
641         boolean deviceSupplied = false;
642         boolean nameSupplied = false;
643         boolean typeSupplied = false;
644         for (int i = 0; i < args.length; i += 2) {
645             LispObject key = args[i];
646             LispObject value = args[i+1];
647             if (key == Keyword.HOST) {
648                 p.host = value;
649             } else if (key == Keyword.DEVICE) {
650                 p.device = value;
651                 deviceSupplied = true;
652             } else if (key == Keyword.DIRECTORY) {
653                 if (value instanceof AbstractString)
654                     p.directory = list2(Keyword.ABSOLUTE, value);
655                 else if (value == Keyword.WILD)
656                     p.directory = list2(Keyword.ABSOLUTE, Keyword.WILD);
657                 else
658                     p.directory = validateDirectory(value);
659             } else if (key == Keyword.NAME) {
660                 p.name = value;
661                 nameSupplied = true;
662             } else if (key == Keyword.TYPE) {
663                 p.type = value;
664                 typeSupplied = true;
665             } else if (key == Keyword.VERSION) {
666                 p.version = value;
667             } else if (key == Keyword.DEFAULTS) {
668                 defaults = coerceToPathname(value);
669             } else if (key == Keyword.CASE) {
670                 ; // Ignored.
671
}
672         }
673         if (defaults != null) {
674             // Ignore host.
675
p.directory = mergeDirectories(p.directory, defaults.directory);
676             if (!deviceSupplied)
677                 p.device = defaults.device;
678             if (!nameSupplied)
679                 p.name = defaults.name;
680             if (!typeSupplied)
681                 p.type = defaults.type;
682         }
683         return p;
684     }
685
686     private static final LispObject validateDirectory(LispObject obj)
687         throws ConditionThrowable
688     {
689         LispObject temp = obj;
690         while (temp != NIL) {
691             LispObject first = temp.car();
692             temp = temp.cdr();
693             if (first == Keyword.ABSOLUTE || first == Keyword.WILD_INFERIORS) {
694                 LispObject second = temp.car();
695                 if (second == Keyword.UP || second == Keyword.BACK) {
696                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
697                     sb.append(first.writeToString());
698                     sb.append(" may not be followed immediately by ");
699                     sb.append(second.writeToString());
700                     sb.append('.');
701                     return signal(new FileError(sb.toString()));
702                 }
703             }
704         }
705         return obj;
706     }
707
708     // ### pathnamep
709
private static final Primitive1 PATHNAMEP =
710         new Primitive1("pathnamep", "object")
711     {
712         public LispObject execute(LispObject arg) throws ConditionThrowable
713         {
714             return arg instanceof Pathname ? T : NIL;
715         }
716     };
717
718     // ### user-homedir-pathname
719
// user-homedir-pathname &optional host => pathname
720
private static final Primitive USER_HOMEDIR_PATHNAME =
721         new Primitive("user-homedir-pathname", "&optional host")
722     {
723         public LispObject execute(LispObject[] args) throws ConditionThrowable
724         {
725             switch (args.length) {
726                 case 0: {
727                     String JavaDoc s = System.getProperty("user.home");
728                     // For compatibility with SBCL and ACL (and maybe other
729
// Lisps), we want the namestring of a directory to end
730
// with a file separator character.
731
if (!s.endsWith(File.separator))
732                         s = s.concat(File.separator);
733                     return new Pathname(s);
734                 }
735                 case 1:
736                     return NIL;
737                 default:
738                     return signal(new WrongNumberOfArgumentsException(this));
739             }
740         }
741     };
742
743     // ### pathname-match-p pathname wildcard => generalized-boolean
744
private static final Primitive2 PATHNAME_MATCH_P =
745         new Primitive2("pathname-match-p", "pathname wildcard")
746     {
747         public LispObject execute(LispObject first, LispObject second)
748             throws ConditionThrowable
749         {
750             Pathname pathname = coerceToPathname(first);
751             Pathname wildcard = coerceToPathname(second);
752             return pathname.matches(wildcard) ? T : NIL;
753         }
754     };
755
756     // ### list-directory
757
private static final Primitive1 LIST_DIRECTORY =
758         new Primitive1("list-directory", PACKAGE_SYS, false)
759     {
760         public LispObject execute(LispObject arg) throws ConditionThrowable
761         {
762             Pathname pathname = Pathname.coerceToPathname(arg);
763             LispObject result = NIL;
764             String JavaDoc s = pathname.getNamestring();
765             if (s != null) {
766                 File JavaDoc f = new File JavaDoc(s);
767                 if (f.isDirectory()) {
768                     File JavaDoc[] files = f.listFiles();
769                     try {
770                         for (int i = files.length; i-- > 0;) {
771                             File JavaDoc file = files[i];
772                             Pathname p;
773                             if (file.isDirectory())
774                                 p = Utilities.getDirectoryPathname(file);
775                             else
776                                 p = new Pathname(file.getCanonicalPath());
777                             result = new Cons(p, result);
778                         }
779                     }
780                     catch (IOException JavaDoc e) {
781                         return signal(new FileError("Unable to list directory " +
782                                                     pathname.writeToString() + "."));
783                     }
784                 }
785             }
786             return result;
787         }
788     };
789
790     public boolean isWild() throws ConditionThrowable
791     {
792         if (host == Keyword.WILD || host == Keyword.WILD_INFERIORS)
793             return true;
794         if (device == Keyword.WILD || device == Keyword.WILD_INFERIORS)
795             return true;
796         if (directory instanceof Cons) {
797             if (memq(Keyword.WILD, directory))
798                 return true;
799             if (memq(Keyword.WILD_INFERIORS, directory))
800                 return true;
801         }
802         if (name == Keyword.WILD || name == Keyword.WILD_INFERIORS)
803             return true;
804         if (type == Keyword.WILD || type == Keyword.WILD_INFERIORS)
805             return true;
806         if (version == Keyword.WILD || version == Keyword.WILD_INFERIORS)
807             return true;
808         return false;
809     }
810
811     private static final Primitive2 _WILD_PATHNAME_P =
812         new Primitive2("%wild-pathname-p", PACKAGE_SYS, false)
813     {
814         public LispObject execute(LispObject first, LispObject second)
815             throws ConditionThrowable
816         {
817             Pathname pathname = Pathname.coerceToPathname(first);
818             if (second == NIL)
819                 return pathname.isWild() ? T : NIL;
820             if (second == Keyword.DIRECTORY) {
821                 if (pathname.directory instanceof Cons) {
822                     if (memq(Keyword.WILD, pathname.directory))
823                         return T;
824                     if (memq(Keyword.WILD_INFERIORS, pathname.directory))
825                         return T;
826                 }
827                 return NIL;
828             }
829             LispObject value;
830             if (second == Keyword.HOST)
831                 value = pathname.host;
832             else if (second == Keyword.DEVICE)
833                 value = pathname.device;
834             else if (second == Keyword.NAME)
835                 value = pathname.name;
836             else if (second == Keyword.TYPE)
837                 value = pathname.type;
838             else if (second == Keyword.VERSION)
839                 value = pathname.version;
840             else
841                 return signal(new ProgramError("Unrecognized keyword " +
842                                                second.writeToString() + "."));
843             if (value == Keyword.WILD || value == Keyword.WILD_INFERIORS)
844                 return T;
845             else
846                 return NIL;
847         }
848     };
849
850     private static final Primitive MERGE_PATHNAMES =
851         new Primitive("merge-pathnames",
852                       "pathname &optional default-pathname default-version")
853     {
854         public LispObject execute(LispObject arg) throws ConditionThrowable
855         {
856             Pathname pathname = coerceToPathname(arg);
857             Pathname defaultPathname =
858                 coerceToPathname(_DEFAULT_PATHNAME_DEFAULTS_.symbolValue());
859             LispObject defaultVersion = Keyword.NEWEST;
860             return mergePathnames(pathname, defaultPathname, defaultVersion);
861         }
862         public LispObject execute(LispObject first, LispObject second)
863             throws ConditionThrowable
864         {
865             Pathname pathname = coerceToPathname(first);
866             Pathname defaultPathname =
867                 coerceToPathname(second);
868             LispObject defaultVersion = Keyword.NEWEST;
869             return mergePathnames(pathname, defaultPathname, defaultVersion);
870         }
871         public LispObject execute(LispObject first, LispObject second,
872                                   LispObject third)
873             throws ConditionThrowable
874         {
875             Pathname pathname = coerceToPathname(first);
876             Pathname defaultPathname =
877                 coerceToPathname(second);
878             LispObject defaultVersion = third;
879             return mergePathnames(pathname, defaultPathname, defaultVersion);
880         }
881     };
882
883     public static final Pathname mergePathnames(Pathname pathname,
884                                                 Pathname defaultPathname,
885                                                 LispObject defaultVersion)
886         throws ConditionThrowable
887     {
888         if (pathname instanceof LogicalPathname)
889             signal(new LispError("Bad place for a logical pathname."));
890         Pathname p = new Pathname();
891         if (pathname.host != NIL)
892             p.host = pathname.host;
893         else
894             p.host = defaultPathname.host;
895         if (pathname.device != NIL)
896             p.device = pathname.device;
897         else
898             p.device = defaultPathname.device;
899         p.directory =
900             mergeDirectories(pathname.directory, defaultPathname.directory);
901         if (pathname.name != NIL)
902             p.name = pathname.name;
903         else
904             p.name = defaultPathname.name;
905         if (pathname.type != NIL)
906             p.type = pathname.type;
907         else
908             p.type = defaultPathname.type;
909         if (pathname.version != NIL)
910             p.version = pathname.version;
911         else if (pathname.name instanceof AbstractString)
912             p.version = defaultVersion;
913         else if (defaultPathname.version != NIL)
914             p.version = defaultPathname.version;
915         else
916             p.version = defaultVersion;
917         return p;
918     }
919
920     private static final LispObject mergeDirectories(LispObject dir,
921                                                      LispObject defaultDir)
922         throws ConditionThrowable
923     {
924         if (dir == NIL)
925             return defaultDir;
926         if (dir.car() == Keyword.RELATIVE && defaultDir != NIL) {
927             LispObject result = NIL;
928             while (defaultDir != NIL) {
929                 result = new Cons(defaultDir.car(), result);
930                 defaultDir = defaultDir.cdr();
931             }
932             dir = dir.cdr(); // Skip :RELATIVE.
933
while (dir != NIL) {
934                 result = new Cons(dir.car(), result);
935                 dir = dir.cdr();
936             }
937             LispObject[] array = result.copyToArray();
938             for (int i = 0; i < array.length - 1; i++) {
939                 if (array[i] == Keyword.BACK) {
940                     if (array[i+1] instanceof AbstractString || array[i+1] == Keyword.WILD) {
941                         array[i] = null;
942                         array[i+1] = null;
943                     }
944                 }
945             }
946             result = NIL;
947             for (int i = 0; i < array.length; i++) {
948                 if (array[i] != null)
949                     result = new Cons(array[i], result);
950             }
951             return result;
952         }
953         return dir;
954     }
955
956     public static final LispObject truename(LispObject arg,
957                                             boolean errorIfDoesNotExist)
958         throws ConditionThrowable
959     {
960         final Pathname pathname = Pathname.coerceToPathname(arg);
961         if (pathname.isWild())
962             signal(new FileError("Bad place for a wild pathname.", pathname));
963         Pathname defaultedPathname =
964             mergePathnames(pathname,
965                            Pathname.coerceToPathname(_DEFAULT_PATHNAME_DEFAULTS_.symbolValue()),
966                            NIL);
967         File JavaDoc file = Utilities.getFile(defaultedPathname);
968         if (file.isDirectory())
969             return Utilities.getDirectoryPathname(file);
970         if (file.exists()) {
971             try {
972                 return new Pathname(file.getCanonicalPath());
973             }
974             catch (IOException JavaDoc e) {
975                 return signal(new LispError(e.getMessage()));
976             }
977         }
978         if (errorIfDoesNotExist) {
979             StringBuffer JavaDoc sb = new StringBuffer JavaDoc("The file ");
980             sb.append(defaultedPathname.writeToString());
981             sb.append(" does not exist.");
982             return signal(new FileError(sb.toString(), defaultedPathname));
983         }
984         return NIL;
985     }
986
987     // ### mkdir
988
private static final Primitive1 MKDIR =
989         new Primitive1("mkdir", PACKAGE_SYS, false)
990     {
991         public LispObject execute(LispObject arg) throws ConditionThrowable
992         {
993             final Pathname pathname = Pathname.coerceToPathname(arg);
994             if (pathname.isWild())
995                 signal(new FileError("Bad place for a wild pathname.", pathname));
996             Pathname defaultedPathname =
997                 mergePathnames(pathname,
998                                Pathname.coerceToPathname(_DEFAULT_PATHNAME_DEFAULTS_.symbolValue()),
999                                NIL);
1000            File JavaDoc file = Utilities.getFile(defaultedPathname);
1001            return file.mkdir() ? T : NIL;
1002        }
1003    };
1004
1005    // ### rename-file filespec new-name => defaulted-new-name, old-truename, new-truename
1006
public static final Primitive2 RENAME_FILE =
1007        new Primitive2("rename-file", "filespec new-name")
1008    {
1009        public LispObject execute(LispObject first, LispObject second)
1010            throws ConditionThrowable
1011        {
1012            final Pathname filespec = (Pathname) truename(first, true);
1013            Pathname newName = coerceToPathname(second);
1014            if (newName.isWild())
1015                signal(new FileError("Bad place for a wild pathname."));
1016            newName = mergePathnames(newName, filespec, NIL);
1017            File JavaDoc source = new File JavaDoc(filespec.getNamestring());
1018            File JavaDoc destination = new File JavaDoc(newName.getNamestring());
1019            if (Utilities.isPlatformWindows()) {
1020                if (destination.isFile())
1021                    destination.delete();
1022            }
1023            if (!source.renameTo(destination))
1024                return signal(new FileError("Unable to rename " +
1025                                            filespec.writeToString() +
1026                                            " to " + newName.writeToString() +
1027                                            "."));
1028            LispThread.currentThread().setValues(newName, filespec,
1029                                                 truename(newName, true));
1030            return newName;
1031        }
1032    };
1033
1034    // ### file-namestring pathname => namestring
1035
private static final Primitive1 FILE_NAMESTRING =
1036        new Primitive1("file-namestring", "pathname")
1037    {
1038        public LispObject execute(LispObject arg) throws ConditionThrowable
1039        {
1040            Pathname p = coerceToPathname(arg);
1041            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1042            if (p.name instanceof AbstractString)
1043                sb.append(p.name.getStringValue());
1044            else if (p.name == Keyword.WILD)
1045                sb.append('*');
1046            else
1047                signal(new SimpleError("Pathname has no name component: " +
1048                                       p.writeToString() + "."));
1049            if (p.type instanceof AbstractString) {
1050                sb.append('.');
1051                sb.append(p.type.getStringValue());
1052            } else if (p.type == Keyword.WILD)
1053                sb.append(".*");
1054            return new SimpleString(sb);
1055        }
1056    };
1057
1058    // ### host-namestring pathname => namestring
1059
private static final Primitive1 HOST_NAMESTRING =
1060        new Primitive1("host-namestring", "pathname")
1061    {
1062        public LispObject execute(LispObject arg)
1063        {
1064            return NIL;
1065        }
1066    };
1067
1068    static {
1069        try {
1070            LispObject obj = _DEFAULT_PATHNAME_DEFAULTS_.getSymbolValue();
1071            _DEFAULT_PATHNAME_DEFAULTS_.setSymbolValue(coerceToPathname(obj));
1072        }
1073        catch (Throwable JavaDoc t) {
1074            Debug.trace(t);
1075        }
1076    }
1077}
1078
Popular Tags