diff -r 2b32fa78b41f -r e904785b7fdf nbproject/build-impl.xml --- a/nbproject/build-impl.xml Tue Sep 01 11:53:10 2009 +0200 +++ b/nbproject/build-impl.xml Wed Sep 02 11:41:09 2009 +0200 @@ -152,7 +152,7 @@ - + diff -r 2b32fa78b41f -r e904785b7fdf nbproject/genfiles.properties --- a/nbproject/genfiles.properties Tue Sep 01 11:53:10 2009 +0200 +++ b/nbproject/genfiles.properties Wed Sep 02 11:41:09 2009 +0200 @@ -4,8 +4,8 @@ # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=742204ce -nbproject/build-impl.xml.script.CRC32=b94c76f8 -nbproject/build-impl.xml.stylesheet.CRC32=e55b27f5 +nbproject/build-impl.xml.script.CRC32=b7bf05a5 +nbproject/build-impl.xml.stylesheet.CRC32=65b8de21 nbproject/profiler-build-impl.xml.data.CRC32=71623fcd nbproject/profiler-build-impl.xml.script.CRC32=abda56ed nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf diff -r 2b32fa78b41f -r e904785b7fdf nbproject/project.properties --- a/nbproject/project.properties Tue Sep 01 11:53:10 2009 +0200 +++ b/nbproject/project.properties Wed Sep 02 11:41:09 2009 +0200 @@ -17,7 +17,7 @@ dist.dir=dist dist.jar=${dist.dir}/abcl.jar dist.javadoc.dir=${dist.dir}/javadoc -excludes= +excludes=org/armedbear/lisp/scripting/**/* file.reference.abcl-src=src includes=org/armedbear/lisp/**/*.java,org/armedbear/lisp/**/*.lisp jar.compress=true diff -r 2b32fa78b41f -r e904785b7fdf src/org/armedbear/lisp/Lisp.java --- a/src/org/armedbear/lisp/Lisp.java Tue Sep 01 11:53:10 2009 +0200 +++ b/src/org/armedbear/lisp/Lisp.java Wed Sep 02 11:41:09 2009 +0200 @@ -39,6 +39,7 @@ import java.io.InputStream; import java.lang.reflect.Constructor; import java.math.BigInteger; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; import java.util.Hashtable; @@ -118,7 +119,7 @@ PACKAGE_LISP.usePackage(PACKAGE_CL); PACKAGE_LISP.usePackage(PACKAGE_EXT); PACKAGE_LISP.usePackage(PACKAGE_SYS); - PACKAGE_THREADS.usePackage(PACKAGE_CL); + PACKAGE_THREADS.usePackage(PACKAGE_CL); } catch (Throwable t) { @@ -330,7 +331,7 @@ int last = frames.length - 1; for (int i = 0; i<= last; i++) { if (frames[i].getClassName().startsWith("org.armedbear.lisp.Primitive")) - last = i; + last = i; } // Do not include the first three frames: // Thread.getStackTrace, LispThread.getJavaStackTrace, @@ -882,7 +883,7 @@ if (obj instanceof StackFrame) return (StackFrame) obj; return (StackFrame)// Not reached. - type_error(obj, Symbol.STACK_FRAME); + type_error(obj, Symbol.STACK_FRAME); } static @@ -1074,8 +1075,20 @@ } if (device instanceof Pathname) { - // We're loading a fasl from j.jar. + // Are we loading a fasl from j.jar? + // XXX this will collide with file names from other JAR files URL url = Lisp.class.getResource(namestring); + if (url == null) { + // Maybe device-->namestring references another JAR file? + String jarFile = ((Pathname)device).getNamestring(); + if (jarFile.startsWith("jar:file:")) { + try { + url = new URL(jarFile + "!/" + namestring); + } catch (MalformedURLException ex) { + Debug.trace(ex); + } + } + } if (url != null) { try @@ -1111,6 +1124,20 @@ LispObject obj = loadCompiledFunction(in, (int) size); return obj != null ? obj : NIL; } + else + { + // ASSERT type = "abcl" + entryName + = defaultPathname.name.getStringValue() + + "." + "abcl";//defaultPathname.type.getStringValue(); + byte in[] + = Utilities + .getZippedZipEntryAsByteArray(zipFile, + entryName, + namestring); + LispObject o = loadCompiledFunction(in); + return o != null ? o : NIL; + } } finally { diff -r 2b32fa78b41f -r e904785b7fdf src/org/armedbear/lisp/Load.java --- a/src/org/armedbear/lisp/Load.java Tue Sep 01 11:53:10 2009 +0200 +++ b/src/org/armedbear/lisp/Load.java Wed Sep 02 11:41:09 2009 +0200 @@ -33,6 +33,8 @@ package org.armedbear.lisp; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -43,6 +45,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; public final class Load extends Lisp { @@ -61,22 +64,22 @@ final String dir) { File file = new File(dir, filename); - if (!file.isFile()) { - String extension = getExtension(filename); - if (extension == null) { - // No extension specified. Try appending ".lisp" or ".abcl". - File lispFile = new File(dir, filename.concat(".lisp")); - File abclFile = new File(dir, filename.concat(".abcl")); - if (lispFile.isFile() && abclFile.isFile()) { - if (abclFile.lastModified() > lispFile.lastModified()) { - return abclFile; - } else { - return lispFile; - } - } else if (abclFile.isFile()) { - return abclFile; - } else if (lispFile.isFile()) { - return lispFile; + if (!file.isFile()) { + String extension = getExtension(filename); + if (extension == null) { + // No extension specified. Try appending ".lisp" or ".abcl". + File lispFile = new File(dir, filename.concat(".lisp")); + File abclFile = new File(dir, filename.concat(".abcl")); + if (lispFile.isFile() && abclFile.isFile()) { + if (abclFile.lastModified() > lispFile.lastModified()) { + return abclFile; + } else { + return lispFile; + } + } else if (abclFile.isFile()) { + return abclFile; + } else if (lispFile.isFile()) { + return lispFile; } } } else @@ -91,7 +94,7 @@ boolean print, boolean ifDoesNotExist) throws ConditionThrowable { - return load(pathname, filename, verbose, print, ifDoesNotExist, false); + return load(pathname, filename, verbose, print, ifDoesNotExist, false); } @@ -100,44 +103,110 @@ boolean verbose, boolean print, boolean ifDoesNotExist, - boolean returnLastResult) + boolean returnLastResult) throws ConditionThrowable { - String dir = null; + String dir = null; if (!Utilities.isFilenameAbsolute(filename)) { - dir = - coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS.symbolValue()).getNamestring(); + dir = coerceToPathname(Symbol.DEFAULT_PATHNAME_DEFAULTS + .symbolValue()).getNamestring(); } - File file = findLoadableFile(filename, dir); - if (file == null) { + String zipFileName = null; + String zipEntryName = null; + if (filename.startsWith("jar:file:")) { + String s = new String(filename); + s = s.substring(9); + int index = s.lastIndexOf('!'); + if (index >= 0) { + zipFileName = s.substring(0, index); + zipEntryName = s.substring(index + 1); + if (zipEntryName.length() > 0 && zipEntryName.charAt(0) == '/') + zipEntryName = zipEntryName.substring(1); + if (Utilities.isPlatformWindows) { + if (zipFileName.length() > 0 && zipFileName.charAt(0) == '/') + zipFileName = zipFileName.substring(1); + } + } + } + + + File file = findLoadableFile(filename, dir); + if (null == file && null == zipFileName) { if (ifDoesNotExist) - return error(new FileError("File not found: " + filename, - pathname)); + return error(new FileError("File not found: " + filename, pathname)); else return NIL; } - filename = file.getPath(); + if (checkZipFile(file)) { + // Either we are loading a packed FASL (i.e. ZIP with suffix ".abcl") + // Or we are loading from a JAR archive + if (".abcl".equals(getExtension(file.getPath()))) { + // So we adjust the value passed to + // loadFileFromStream() to get any further loading + // within this invocation of LOAD to work properly. + filename = file.getPath(); + } + zipFileName = file.getPath(); + zipEntryName = file.getName(); + } + + String truename = filename; ZipFile zipfile = null; - if (checkZipFile(file)) - { + + boolean packedFASL = false; + + InputStream in = null; + if (zipFileName != null) { try { - zipfile = ZipCache.getZip(file.getPath()); + zipfile = ZipCache.getZip(zipFileName); } catch (Throwable t) { - // Fall through. + return error (new FileError("Zip file not found: " + filename, pathname)); } - } - String truename = filename; - InputStream in = null; - if (zipfile != null) { - String name = file.getName(); - int index = name.lastIndexOf('.'); - Debug.assertTrue(index >= 0); - name = name.substring(0, index).concat("._"); - ZipEntry entry = zipfile.getEntry(name); - if (entry != null) { + ZipEntry entry = zipfile.getEntry(zipEntryName); + if (null == entry) { + // try appending "._" to base filename + int index = zipEntryName.lastIndexOf('.'); + if (-1 == index) index = zipEntryName.length(); + zipEntryName = zipEntryName.substring(0, index).concat("._"); + entry = zipfile.getEntry(zipEntryName); + } + if (null == entry) { + // try appending ".abcl" to base filename + int index = zipEntryName.lastIndexOf('.'); + if (index == -1) + index = zipEntryName.length(); + zipEntryName = zipEntryName.substring(0, index).concat(".abcl"); + entry = zipfile.getEntry(zipEntryName); + if (entry == null) { + return error(new LispError("Failed to find " + zipEntryName + " in " + + zipFileName + ".")); + } + packedFASL = true; + } + + if (null == entry) { + return error(new FileError("Can't read zip file entry " + + zipEntryName, pathname)); + } + if (".abcl".equals(getExtension(zipEntryName))) { + packedFASL = true; + } + if (packedFASL) { + // If we are loading a packed FASL from the JAR we + // have to decompress it first, and seek for the '._' + // init FASL. + int i = zipEntryName.lastIndexOf('.'); + String subZipEntryName = zipEntryName.substring(0, i).concat("._"); + in = Utilities.getZippedZipEntryAsInputStream(zipfile, + zipEntryName, + subZipEntryName); + + // XXX Help out the truename loading + // truename += ".abcl"; + } else { try { in = zipfile.getInputStream(entry); } @@ -162,9 +231,10 @@ } } try { - return loadFileFromStream(null, truename, - new Stream(in, Symbol.CHARACTER), - verbose, print, false, returnLastResult); + + return loadFileFromStream(null, truename, + new Stream(in, Symbol.CHARACTER), + verbose, print, false, returnLastResult); } catch (FaslVersionMismatch e) { FastStringBuffer sb = @@ -391,8 +461,8 @@ boolean verbose, boolean print, boolean auto) - throws ConditionThrowable { - return loadFileFromStream(pathname, truename, in, verbose, print, auto, false); + throws ConditionThrowable { + return loadFileFromStream(pathname, truename, in, verbose, print, auto, false); } private static final LispObject loadFileFromStream(LispObject pathname, @@ -401,7 +471,7 @@ boolean verbose, boolean print, boolean auto, - boolean returnLastResult) + boolean returnLastResult) throws ConditionThrowable { long start = System.currentTimeMillis(); @@ -466,8 +536,8 @@ private static final LispObject loadStream(Stream in, boolean print, LispThread thread) - throws ConditionThrowable { - return loadStream(in, print, thread, false); + throws ConditionThrowable { + return loadStream(in, print, thread, false); } private static final LispObject loadStream(Stream in, boolean print, @@ -482,7 +552,7 @@ thread.lastSpecialBinding = sourcePositionBinding; try { final Environment env = new Environment(); - LispObject result = NIL; + LispObject result = NIL; while (true) { sourcePositionBinding.value = Fixnum.getInstance(in.getOffset()); LispObject obj = in.read(false, EOF, false, thread); @@ -496,11 +566,11 @@ out._finishOutput(); } } - if(returnLastResult) { - return result; - } else { - return T; - } + if(returnLastResult) { + return result; + } else { + return T; + } } finally { thread.lastSpecialBinding = lastSpecialBinding; @@ -513,7 +583,7 @@ Stream in = (Stream) _LOAD_STREAM_.symbolValue(thread); final Environment env = new Environment(); final SpecialBinding lastSpecialBinding = thread.lastSpecialBinding; - LispObject result = NIL; + LispObject result = NIL; try { thread.bindSpecial(_FASL_ANONYMOUS_PACKAGE_, new Package()); while (true) { @@ -527,10 +597,10 @@ thread.lastSpecialBinding = lastSpecialBinding; } return result; - //There's no point in using here the returnLastResult flag like in - //loadStream(): this function is only called from init-fasl, which is - //only called from load, which already has its own policy for choosing - //whether to return T or the last value. + //There's no point in using here the returnLastResult flag like in + //loadStream(): this function is only called from init-fasl, which is + //only called from load, which already has its own policy for choosing + //whether to return T or the last value. } // Returns extension including leading '.' @@ -600,10 +670,10 @@ { @Override public LispObject execute(LispObject filespec, LispObject verbose, - LispObject print, LispObject ifDoesNotExist) - throws ConditionThrowable { - return load(filespec, verbose, print, ifDoesNotExist, NIL); - } + LispObject print, LispObject ifDoesNotExist) + throws ConditionThrowable { + return load(filespec, verbose, print, ifDoesNotExist, NIL); + } }; // ### %load-returning-last-result filespec verbose print if-does-not-exist => object @@ -613,49 +683,49 @@ { @Override public LispObject execute(LispObject filespec, LispObject verbose, - LispObject print, LispObject ifDoesNotExist) - throws ConditionThrowable { - return load(filespec, verbose, print, ifDoesNotExist, T); - } + LispObject print, LispObject ifDoesNotExist) + throws ConditionThrowable { + return load(filespec, verbose, print, ifDoesNotExist, T); + } }; private static final LispObject load(LispObject filespec, - LispObject verbose, - LispObject print, - LispObject ifDoesNotExist, - LispObject returnLastResult) - throws ConditionThrowable { - if (filespec instanceof Stream) { - if (((Stream)filespec).isOpen()) { - LispObject pathname; - if (filespec instanceof FileStream) - pathname = ((FileStream)filespec).getPathname(); - else - pathname = NIL; - String truename; - if (pathname instanceof Pathname) - truename = ((Pathname)pathname).getNamestring(); - else - truename = null; - return loadFileFromStream(pathname, - truename, - (Stream) filespec, - verbose != NIL, - print != NIL, - false, - returnLastResult != NIL); - } - // If stream is closed, fall through... - } - Pathname pathname = coerceToPathname(filespec); - if (pathname instanceof LogicalPathname) - pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); - return load(pathname, - pathname.getNamestring(), - verbose != NIL, - print != NIL, - ifDoesNotExist != NIL, - returnLastResult != NIL); + LispObject verbose, + LispObject print, + LispObject ifDoesNotExist, + LispObject returnLastResult) + throws ConditionThrowable { + if (filespec instanceof Stream) { + if (((Stream)filespec).isOpen()) { + LispObject pathname; + if (filespec instanceof FileStream) + pathname = ((FileStream)filespec).getPathname(); + else + pathname = NIL; + String truename; + if (pathname instanceof Pathname) + truename = ((Pathname)pathname).getNamestring(); + else + truename = null; + return loadFileFromStream(pathname, + truename, + (Stream) filespec, + verbose != NIL, + print != NIL, + false, + returnLastResult != NIL); + } + // If stream is closed, fall through... + } + Pathname pathname = coerceToPathname(filespec); + if (pathname instanceof LogicalPathname) + pathname = LogicalPathname.translateLogicalPathname((LogicalPathname)pathname); + return load(pathname, + pathname.getNamestring(), + verbose != NIL, + print != NIL, + ifDoesNotExist != NIL, + returnLastResult != NIL); } // ### load-system-file diff -r 2b32fa78b41f -r e904785b7fdf src/org/armedbear/lisp/Utilities.java --- a/src/org/armedbear/lisp/Utilities.java Tue Sep 01 11:53:10 2009 +0200 +++ b/src/org/armedbear/lisp/Utilities.java Wed Sep 02 11:41:09 2009 +0200 @@ -33,8 +33,14 @@ package org.armedbear.lisp; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; public final class Utilities extends Lisp { @@ -115,4 +121,60 @@ return null; } } + + public static byte[] getZippedZipEntryAsByteArray(ZipFile zipfile, + String entryName, + String subEntryName) + throws ConditionThrowable + { + ZipEntry entry = zipfile.getEntry(entryName); + + ZipInputStream stream = null; + try { + stream = new ZipInputStream(zipfile.getInputStream(entry)); + } + catch (IOException e) { + Lisp.error(new FileError("Failed to open '" + entryName + "' in zipfile '" + + zipfile + "': " + e.getMessage())); + } + // XXX Cache the zipEntries somehow + do { + try { + entry = stream.getNextEntry(); + } catch (IOException e){ + Lisp.error(new FileError("Failed to seek for '" + subEntryName + + "' in '" + + zipfile.getName() + ":" + entryName + ".:" + + e.getMessage())); + } + } while (!entry.getName().equals(subEntryName)); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int count; + byte buf[] = new byte[1024]; + try { + while ((count = stream.read(buf, 0, buf.length)) != -1) { + buffer.write(buf, 0, count); + } + } catch (java.io.IOException e) { + Lisp.error(new FileError("Failed to read compressed '" + + subEntryName + + "' in '" + + zipfile.getName() + ":" + entryName + ":" + + e.getMessage())); + } + return buffer.toByteArray(); + } + + public static InputStream getZippedZipEntryAsInputStream(ZipFile zipfile, + String entryName, + String subEntryName) + throws ConditionThrowable + { + return + new ByteArrayInputStream(Utilities + .getZippedZipEntryAsByteArray(zipfile, entryName, + subEntryName)); + } } + diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/bar.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lisp/abcl/bar.lisp Wed Sep 02 11:41:09 2009 +0200 @@ -0,0 +1,9 @@ +(defun bar () + (format t "Some BAR")) + +(defvar *bar* t) + +(defun baz () + (format t "Some BAZ")) + + diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/eek.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lisp/abcl/eek.lisp Wed Sep 02 11:41:09 2009 +0200 @@ -0,0 +1,2 @@ +(defun eek () + (format t "Another EEK.")) \ No newline at end of file diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/foo.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lisp/abcl/foo.lisp Wed Sep 02 11:41:09 2009 +0200 @@ -0,0 +1,15 @@ +#| + +Compile with + + (let ((sys::*compile-file-zip* t)) + (compile-file "foo.lisp" :output-file "foo.jar")) + +Load with + + (load "jar:file:foo.jar!/foo") + +|# + +(defun foo () + (format t "FOO here.")) diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/load.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lisp/abcl/load.lisp Wed Sep 02 11:41:09 2009 +0200 @@ -0,0 +1,60 @@ +(in-package #:abcl.test.lisp) + +#-:unix (error "Load test setup currently needs UNIX shell script support.") + +(defun load-init () + (let* ((*default-pathname-defaults* *this-directory*) + (asdf::*verbose-out* *standard-output*) + (package-command (format nil "sh ~A" (merge-pathnames "package-load.sh")))) + (compile-file "foo.lisp") + (compile-file "bar.lisp") + (compile-file "eek.lisp") + (asdf:run-shell-command package-command))) + +(load-init) + +(deftest load.1 + (let ((*default-pathname-defaults* *this-directory*)) + (load "foo")) + t) + +(deftest load.2 + (let ((*default-pathname-defaults* *this-directory*)) + (load "foo.lisp")) + t) + +(deftest load.3 + (let ((*default-pathname-defaults* *this-directory*)) + (load "foo.abcl")) + t) + +(deftest load.4 + (let ((*default-pathname-defaults* *this-directory*)) + (load "jar:file:baz.jar!/foo")) + t) + +(deftest load.6 + (let ((*default-pathname-defaults* *this-directory*)) + (load "jar:file:baz.jar!/bar")) + t) + +(deftest load.7 + (let ((*default-pathname-defaults* *this-directory*)) + (load "jar:file:baz.jar!/bar.abcl")) + t) + +(deftest load.8 + (let ((*default-pathname-defaults* *this-directory*)) + (load "jar:file:baz.jar!/eek")) + t) + +(deftest load.9 + (let ((*default-pathname-defaults* *this-directory*)) + (load "jar:file:baz.jar!/eek.lisp")) + t) + + + + + + diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/package-load.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lisp/abcl/package-load.sh Wed Sep 02 11:41:09 2009 +0200 @@ -0,0 +1,18 @@ +#!/bin/sh +srcdir=$PWD +tmpdir=/tmp/$$ + +mkdir $tmpdir + +cd $tmpdir + +unzip $srcdir/foo.abcl + +cp $srcdir/bar.abcl . + +cp $srcdir/eek.lisp . + +jar cfv $srcdir/baz.jar * + +rm -rf $tmpdir + diff -r 2b32fa78b41f -r e904785b7fdf test/lisp/abcl/package.lisp --- a/test/lisp/abcl/package.lisp Tue Sep 01 11:53:10 2009 +0200 +++ b/test/lisp/abcl/package.lisp Wed Sep 02 11:41:09 2009 +0200 @@ -1,5 +1,6 @@ (defpackage #:abcl.test.lisp (:use #:cl #:abcl-rt) + (:nicknames "ABCL-TEST") (:export #:run)) (in-package #:abcl.test.lisp)