On 3/24/10 7:08 PM, Faré wrote:
[…]
Can ASDF1 do this loading from jar files? I certainly didn't remove
anything from it. If you have a local patch to ASDF1 to do it, I'll be
please to include it in either ASDF2 or a contrib to it.
Yes, ABCL ADSF1 can load from jar files and no, nothing has been removed
from ASDF2 as it's more of a case of what has been added, namely that it
now OPENs the .asd file instead of LOADing it, and ASDF-BINARY-LOCATIONS
are baked-in.
That a Pathname for jar locations in ABCL are not currently capable of
being OPENed turns out to be easily implemented (see attached patch).
That a jar Pathname is not a writable location turns out to cause
problems for the binary locations part of ASDF2. It was sufficient to
[patch the behavior][1] of ASDF1 to have OPERATION-DONE-P return T if
all the members of the output files of COMPILE-OP on a CL-SOURCE-FILE
were determined to be within a jar. But this turns out only to have
worked with ABCL because there was a bug in how *LOAD-TRUENAME* was
computed in loading from a jar Pathname that I would like to fix going
forward (it's fixed in the patch).
[1]:
http://trac.common-lisp.net/armedbear/browser/trunk/abcl/src/org/armedbear/lisp/asdf-abcl.lisp
It would be perhaps cleaner to have the binary locations machinery of
ASDF2 react to not being able to write to the Pathname derived from the
location of the ".asd" file in an extensible manner. This might be
useful for users of Lisps other than ABCL who don't have permission to
write to the system ASDF location for instance. My current problem is
that the :BEFORE for PERFORM specialized on COMPILE-OP SOURCE-FILE
contains an ENSURE-DIRECTORIES-EXIST which by default is derived from
the ".asd" Pathname. Is there a way to per-system customization of the
output location?
Thinking quickly for an ASDF2 algorithm:
1. Is the directory containing the ".asd" writable? If so, continue
normally.
2. Otherwise, can we establish an alternative location to write the
output of COMPILE-OP as configured by the user? If so, continue normally.
3. Otherwise, skip the COMPILE-OP of this system. For LOAD-OP, search
for FASLs by some user-extensible mechanism, falling back to looking in
the same directory as the ".lisp" files. If no FASLs can be found, load
the source files.
If there are any regressions from ASDF1 to ASDF2, I want them fixed.
Otherwise, there shouldn't be a problem upgrading ABCL from ASDF1 to
ASDF2.
No regressions have been noted; I will report them if found. As it
stands, I can't upgrade ABCL to ASDF2 without breaking the existing
functionality of loading ADSF definitions from jars. The responsibility
for fixing this situation certainly lies with ABCL's extension of
Pathnames to cover jar files, which we are working to bring in line with
new features offered by ASDF2.
--
"A screaming comes across the sky. It has happened before, but there
is nothing to compare to it now."
diff -r a9813719dfba src/org/armedbear/lisp/BuiltInClass.java
--- a/src/org/armedbear/lisp/BuiltInClass.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/BuiltInClass.java Thu Mar 25 06:20:00 2010 +0100
@@ -181,6 +181,9 @@
public static final LispClass FILE_STREAM =
addClass(Symbol.FILE_STREAM,
new StructureClass(Symbol.FILE_STREAM, list(SYSTEM_STREAM)));
+ public static final LispClass JAR_STREAM =
+ addClass(Symbol.JAR_STREAM,
+ new StructureClass(Symbol.JAR_STREAM, list(SYSTEM_STREAM)));
public static final LispClass CONCATENATED_STREAM =
addClass(Symbol.CONCATENATED_STREAM,
new StructureClass(Symbol.CONCATENATED_STREAM,
list(SYSTEM_STREAM)));
@@ -233,6 +236,8 @@
FIXNUM.setCPL(FIXNUM, INTEGER, RATIONAL, REAL, NUMBER, CLASS_T);
FILE_STREAM.setCPL(FILE_STREAM, SYSTEM_STREAM, STREAM,
STRUCTURE_OBJECT, CLASS_T);
+ JAR_STREAM.setCPL(JAR_STREAM, SYSTEM_STREAM, STREAM,
+ STRUCTURE_OBJECT, CLASS_T);
FLOAT.setDirectSuperclass(REAL);
FLOAT.setCPL(FLOAT, REAL, NUMBER, CLASS_T);
FUNCTION.setDirectSuperclass(CLASS_T);
diff -r a9813719dfba src/org/armedbear/lisp/FileStream.java
--- a/src/org/armedbear/lisp/FileStream.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/FileStream.java Thu Mar 25 06:20:00 2010 +0100
@@ -286,11 +286,6 @@
else {
return type_error(first, Symbol.PATHNAME);
}
- if (pathname.isJar()) {
- error(new FileError("Direct stream input/output on entries in
JAR files no currently supported.",
- pathname));
- }
-
final LispObject namestring = checkString(second);
LispObject elementType = third;
LispObject direction = fourth;
@@ -300,16 +295,30 @@
if (direction != Keyword.INPUT && direction != Keyword.OUTPUT &&
direction != Keyword.IO)
error(new LispError("Direction must be :INPUT, :OUTPUT, or
:IO."));
- try {
- return new FileStream(pathname, namestring.getStringValue(),
- elementType, direction, ifExists,
- externalFormat);
- }
- catch (FileNotFoundException e) {
- return NIL;
- }
- catch (IOException e) {
- return error(new StreamError(null, e));
+
+ if (pathname.isJar()) {
+ if (direction != Keyword.INPUT) {
+ error(new FileError("Only direction :INPUT is supported
for jar files.", pathname));
+ }
+ try {
+ return new JarStream(pathname, namestring.getStringValue(),
+ elementType, direction, ifExists,
+ externalFormat);
+ } catch (IOException e) {
+ return error(new StreamError(null, e));
+ }
+ } else {
+ try {
+ return new FileStream(pathname,
namestring.getStringValue(),
+ elementType, direction, ifExists,
+ externalFormat);
+ }
+ catch (FileNotFoundException e) {
+ return NIL;
+ }
+ catch (IOException e) {
+ return error(new StreamError(null, e));
+ }
}
}
};
diff -r a9813719dfba src/org/armedbear/lisp/JarStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/armedbear/lisp/JarStream.java Thu Mar 25 06:20:00 2010 +0100
@@ -0,0 +1,150 @@
+/*
+ * JarStream.java
+ *
+ * Copyright (C) 2010 Mark Evenson
+ * $Id: FileStream.java 12422 2010-02-06 10:52:32Z mevenson $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under
+ * terms of your choice, provided that you also meet, for each linked
+ * independent module, the terms and conditions of the license of that
+ * module. An independent module is a module which is not derived from
+ * or based on this library. If you modify this library, you may extend
+ * this exception to your version of the library, but you are not
+ * obligated to do so. If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
+
+package org.armedbear.lisp;
+
+import static org.armedbear.lisp.Lisp.*;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+
+/**
+ * Stream interface for an entry in a jar pathname.
+ *
+ * This only supports reading from the stream.
+ */
+public final class JarStream extends Stream
+{
+ private final Pathname pathname;
+ private final InputStream input;
+ private final Reader reader;
+ private final int bytesPerUnit;
+
+ public JarStream(Pathname pathname, String namestring,
+ LispObject elementType, LispObject direction,
+ LispObject ifExists, LispObject format)
+ throws IOException
+ {
+ super(Symbol.JAR_STREAM);
+ Debug.assertTrue(direction == Keyword.INPUT);
+ Debug.assertTrue(pathname.name != NIL);
+ isInputStream = true;
+
+ super.setExternalFormat(format);
+
+ this.pathname = pathname;
+ this.elementType = elementType;
+
+ this.input = pathname.getInputStream();
+ if (elementType == Symbol.CHARACTER || elementType ==
Symbol.BASE_CHAR) {
+ isCharacterStream = true;
+ bytesPerUnit = 1;
+ InputStreamReader isr = new InputStreamReader(input);
+ this.reader = (Reader) new BufferedReader(isr);
+ initAsCharacterInputStream(this.reader);
+ } else {
+ isBinaryStream = true;
+ int width = Fixnum.getValue(elementType.cadr());
+ bytesPerUnit = width / 8;
+ this.reader = null;
+ initAsBinaryInputStream(this.input);
+ }
+ }
+
+ @Override
+ public LispObject typeOf()
+ {
+ return Symbol.JAR_STREAM;
+ }
+
+ @Override
+ public LispObject classOf()
+ {
+ return BuiltInClass.JAR_STREAM;
+ }
+
+ @Override
+ public LispObject typep(LispObject typeSpecifier)
+ {
+ if (typeSpecifier == Symbol.JAR_STREAM)
+ return T;
+ if (typeSpecifier == BuiltInClass.JAR_STREAM)
+ return T;
+ return super.typep(typeSpecifier);
+ }
+
+ @Override
+ public void setExternalFormat(LispObject format) {
+ super.setExternalFormat(format);
+ }
+
+ public Pathname getPathname()
+ {
+ return pathname;
+ }
+
+ @Override
+ public void _close()
+ {
+ try {
+ if (input != null) {
+ input.close();
+ }
+ if (reader != null) {
+ reader.close();
+ }
+ setOpen(false);
+ }
+ catch (IOException e) {
+ error(new StreamError(this, e));
+ }
+ }
+
+ @Override
+ public String writeToString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(Symbol.JAR_STREAM.writeToString());
+ String namestring = pathname.getNamestring();
+ if (namestring != null) {
+ sb.append(" ");
+ sb.append(namestring);
+ }
+ return unreadableString(sb.toString());
+ }
+}
diff -r a9813719dfba src/org/armedbear/lisp/Load.java
--- a/src/org/armedbear/lisp/Load.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/Load.java Thu Mar 25 06:20:00 2010 +0100
@@ -462,17 +462,24 @@
String type = truePathname.type.getStringValue();
if (type.equals(COMPILE_FILE_TYPE)
|| type.equals(COMPILE_FILE_INIT_FASL_TYPE.toString())) {
- thread.bindSpecial(Symbol.LOAD_TRUENAME_FASL,
truePathname);
+ Pathname truenameFasl = new Pathname(truePathname);
+ thread.bindSpecial(Symbol.LOAD_TRUENAME_FASL,
truenameFasl);
}
if (truePathname.type.getStringValue()
.equals(COMPILE_FILE_INIT_FASL_TYPE.getStringValue())
&& truePathname.isJar()) {
if (truePathname.device.cdr() != NIL ) {
- // set truename to the enclosing JAR
+ // We set *LOAD-TRUENAME* to the argument that
+ // a user would pass to LOAD.
+ Pathname enclosingJar =
(Pathname)truePathname.device.cdr().car();
+ truePathname.device = new
Cons(truePathname.device.car(), NIL);
truePathname.host = NIL;
- truePathname.directory = NIL;
- truePathname.name = NIL;
- truePathname.type = NIL;
+ truePathname.directory = enclosingJar.directory;
+ if
(truePathname.directory.car().equals(Keyword.RELATIVE)) {
+ truePathname.directory.setCar(Keyword.ABSOLUTE);
+ }
+ truePathname.name = enclosingJar.name;
+ truePathname.type = enclosingJar.type;
truePathname.invalidateNamestring();
} else {
// XXX There is something fishy in the asymmetry
diff -r a9813719dfba src/org/armedbear/lisp/Pathname.java
--- a/src/org/armedbear/lisp/Pathname.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/Pathname.java Thu Mar 25 06:20:00 2010 +0100
@@ -643,6 +643,7 @@
p.directory = directory;
p.name = name;
p.type = type;
+ p.invalidateNamestring();
String path = p.getNamestring();
StringBuilder result = new StringBuilder();
if (Utilities.isPlatformWindows) {
diff -r a9813719dfba src/org/armedbear/lisp/Symbol.java
--- a/src/org/armedbear/lisp/Symbol.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/Symbol.java Thu Mar 25 06:20:00 2010 +0100
@@ -2999,6 +2999,9 @@
PACKAGE_SYS.addExternalSymbol("SET-CHAR");
public static final Symbol SET_SCHAR =
PACKAGE_SYS.addExternalSymbol("SET-SCHAR");
+ public static final Symbol JAR_STREAM =
+ PACKAGE_SYS.addExternalSymbol("JAR-STREAM");
+
// Internal symbols in SYSTEM package.
public static final Symbol BACKQUOTE_MACRO =
diff -r a9813719dfba src/org/armedbear/lisp/ZipCache.java
--- a/src/org/armedbear/lisp/ZipCache.java Tue Mar 23 13:59:08 2010 +0100
+++ b/src/org/armedbear/lisp/ZipCache.java Thu Mar 25 06:20:00 2010 +0100
@@ -111,11 +111,13 @@
try {
return new ZipFile(f);
} catch (ZipException e) {
- Debug.trace(e); // XXX
- return null;
+ error(new FileError("Failed to construct ZipFile"
+ + " because " + e,
+ Pathname.makePathname(f)));
} catch (IOException e) {
- Debug.trace(e); // XXX
- return null;
+ error(new FileError("Failed to contruct ZipFile"
+ + " because " + e,
+ Pathname.makePathname(f)));
}
} else {
Entry e = fetchURL(url, false);
@@ -185,11 +187,13 @@
try {
entry.file = new ZipFile(f);
} catch (ZipException e) {
- Debug.trace(e); // XXX
- return null;
+ error(new FileError("Failed to get cached ZipFile"
+ + " because " + e,
+ Pathname.makePathname(f)));
} catch (IOException e) {
- Debug.trace(e); // XXX
- return null;
+ error(new FileError("Failed to get cached ZipFile"
+ + " because " + e,
+ Pathname.makePathname(f)));
}
} else {
entry = fetchURL(url, true);
@@ -205,29 +209,31 @@
try {
jarURL = new URL("jar:" + url + "!/");
} catch (MalformedURLException e) {
- Debug.trace(e);
- Debug.assertTrue(false); // XXX
+ error(new LispError("Failed to form a jar: URL from "
+ + "'" + url + "'"
+ + " because " + e));
}
- URLConnection connection;
+ URLConnection connection = null;
try {
connection = jarURL.openConnection();
- } catch (IOException ex) {
- Debug.trace("Failed to open "
- + "'" + jarURL + "'");
- return null;
+ } catch (IOException e) {
+ error(new LispError("Failed to open "
+ + "'" + jarURL + "'"
+ + " with exception "
+ + e));
}
if (!(connection instanceof JarURLConnection)) {
- // XXX
- Debug.trace("Could not get a URLConnection from " + jarURL);
- return null;
+ error(new LispError("Could not get a URLConnection from "
+ + "'" + jarURL + "'"));
}
JarURLConnection jarURLConnection = (JarURLConnection) connection;
jarURLConnection.setUseCaches(cached);
try {
result.file = jarURLConnection.getJarFile();
} catch (IOException e) {
- Debug.trace(e);
- Debug.assertTrue(false); // XXX
+ error(new LispError("Failed to fetch URL "
+ + "'" + jarURLConnection + "'"
+ + " because " + e));
}
result.lastModified = jarURLConnection.getLastModified();
return result;
_______________________________________________
asdf-devel mailing list
asdf-devel@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/asdf-devel