1 21 22 package org.armedbear.lisp; 23 24 import java.io.File ; 25 import java.io.IOException ; 26 import java.net.URL ; 27 import java.util.StringTokenizer ; 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 protected LispObject type = NIL; 38 39 protected LispObject version = NIL; 41 42 private String namestring; 43 44 protected Pathname() 45 { 46 } 47 48 public Pathname(String s) throws ConditionThrowable 49 { 50 init(s); 51 } 52 53 public Pathname(URL url) throws ConditionThrowable 54 { 55 String protocol = url.getProtocol(); 56 if ("jar".equals(protocol)) { 57 String s = url.getPath(); 58 if (s.startsWith("file:")) { 59 int index = s.indexOf("!/"); 60 String 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 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 s) throws ConditionThrowable 84 { 85 if (s == null) 86 return; 87 if (Utilities.isPlatformWindows()) 88 s = s.replace('/', '\\'); 89 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 d = null; 128 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 n = null; 160 String 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 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 st = new StringTokenizer (d, "/\\"); 191 while (st.hasMoreTokens()) { 192 String 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 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 sb = new StringBuffer (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 getDirectoryNamestring() throws ConditionThrowable 263 { 264 StringBuffer sb = new StringBuffer (); 265 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 = '/'; 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 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 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 writeToString() throws ConditionThrowable 405 { 406 try { 407 StringBuffer sb = new StringBuffer ("#P"); 408 boolean printReadably = (_PRINT_READABLY_.symbolValue() != NIL); 409 boolean useNamestring; 410 String s = getNamestring(); 411 if (s != null) { 412 useNamestring = true; 413 if (printReadably) { 414 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 quoteEscape(String s) throws ConditionThrowable 471 { 472 StringBuffer sb = new StringBuffer (); 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 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 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 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 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 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 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 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 ; } 672 } 673 if (defaults != null) { 674 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 sb = new StringBuffer (); 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 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 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 s = System.getProperty("user.home"); 728 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 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 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 s = pathname.getNamestring(); 765 if (s != null) { 766 File f = new File (s); 767 if (f.isDirectory()) { 768 File [] files = f.listFiles(); 769 try { 770 for (int i = files.length; i-- > 0;) { 771 File 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 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(); 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 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 e) { 975 return signal(new LispError(e.getMessage())); 976 } 977 } 978 if (errorIfDoesNotExist) { 979 StringBuffer sb = new StringBuffer ("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 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 file = Utilities.getFile(defaultedPathname); 1001 return file.mkdir() ? T : NIL; 1002 } 1003 }; 1004 1005 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 source = new File (filespec.getNamestring()); 1018 File destination = new File (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 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 sb = new StringBuffer (); 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 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 t) { 1074 Debug.trace(t); 1075 } 1076 } 1077} 1078 | Popular Tags |