From: Adam W. <li...@co...> - 2005-05-13 00:54:49
|
Hi Peter, Thanks for fixing the location of temporary class files so the code I posted a couple of days ago will load. In other Common Lisp implementations upon Unix I'm able to open an octet stream to /dev/stdout: (open "/dev/stdout" :direction :output #-clisp :if-exists #-clisp :overwrite :element-type '(unsigned-byte 8))) This approach doesn't work in ABCL because the code in FileStream.java always tries to either {set the seek position of the file, or set its length}: raf = new RandomAccessFile(file, mode); // ifExists is ignored unless we have an output stream. if (isOutputStream) { if (ifExists == Keyword.OVERWRITE) raf.seek(0); else if (ifExists == Keyword.APPEND) raf.seek(raf.length()); else raf.setLength(0); } It looks like raf.setLength(0) should only execute when ifExists == Keyword.SUPERSEDE. With this change I can now open an octet stream to /dev/stdout: $ diff -u ~/Lisp/J/j/src/org/armedbear/lisp/FileStream.java FileStream.java --- /home/adam/Lisp/J/j/src/org/armedbear/lisp/FileStream.java 2005-04-18 14:49:10.000000000 +1200 +++ FileStream.java 2005-05-13 12:31:15.433915360 +1200 @@ -67,7 +67,7 @@ raf.seek(0); else if (ifExists == Keyword.APPEND) raf.seek(raf.length()); - else + else if (ifExists == Keyword.SUPERSEDE) raf.setLength(0); } this.pathname = pathname; CL-USER(15): (defparameter *stdout* (open "/dev/stdout" :direction :output #-(or abcl clisp) :if-exists #-(or abcl clisp) :overwrite :element-type '(unsigned-byte 8))) *STDOUT* CL-USER(16): (write-sequence #(65 66 67 10) *stdout*) #(65 66 67 10) CL-USER(17): (force-output *stdout*) ABC NIL Note that as with CLISP I have to avoid supplying :if-exists :overwrite as otherwise an illegal seek will still occur (whereas it is necessary to supply the keywords in some other implementations). Both variations appear to be conforming. Regards, Adam |
From: Peter G. <pe...@ar...> - 2005-05-17 16:36:27
|
On Fri, 13 May 2005 at 12:54:06 +1200, Adam Warner wrote: > In other Common Lisp implementations upon Unix I'm able to open an > octet stream to /dev/stdout: > > (open "/dev/stdout" :direction :output > #-clisp :if-exists #-clisp :overwrite :element-type '(unsigned-byte 8))) > > This approach doesn't work in ABCL because the code in FileStream.java > always tries to either {set the seek position of the file, or set its > length}: > > raf = new RandomAccessFile(file, mode); > // ifExists is ignored unless we have an output stream. > if (isOutputStream) { > if (ifExists == Keyword.OVERWRITE) > raf.seek(0); > else if (ifExists == Keyword.APPEND) > raf.seek(raf.length()); > else > raf.setLength(0); > } > > It looks like raf.setLength(0) should only execute when ifExists == > Keyword.SUPERSEDE. With this change I can now open an octet stream to > /dev/stdout: > > > $ diff -u ~/Lisp/J/j/src/org/armedbear/lisp/FileStream.java FileStream.java > --- /home/adam/Lisp/J/j/src/org/armedbear/lisp/FileStream.java > 2005-04-18 14:49:10.000000000 +1200 +++ FileStream.java > 2005-05-13 12:31:15.433915360 +1200 @@ -67,7 +67,7 @@ > raf.seek(0); > else if (ifExists == Keyword.APPEND) > raf.seek(raf.length()); > - else > + else if (ifExists == Keyword.SUPERSEDE) > raf.setLength(0); > } > this.pathname = pathname; > > > CL-USER(15): (defparameter *stdout* (open "/dev/stdout" :direction :output > #-(or abcl clisp) :if-exists #-(or abcl clisp) :overwrite > :element-type '(unsigned-byte 8))) > *STDOUT* > CL-USER(16): (write-sequence #(65 66 67 10) *stdout*) > #(65 66 67 10) > CL-USER(17): (force-output *stdout*) > ABC > NIL Good work tracking this down! I've fixed this in CVS, but with a slightly different fix. If you call raf.setLength(0) only when ifExists == Keyword.SUPERSEDE, you end up breaking cases where IF-EXISTS is :NEW-VERSION and you're dealing with an existing real file (as opposed to /dev/stdout). In that situation, you'll end up correctly writing the new stuff at the beginning of the file, but if the file was longer to begin with than the length of the new stuff that was written, the old stuff that comes later will be left in the file. There are a couple of ansi-tests that test this situation, and they fail with your suggested fix. What you really want to do is only call setLength(0) when the file exists and is not of length 0 to begin with: if (isOutputStream) { final long length = file.isFile() ? file.length() : 0; if (length > 0) { if (ifExists == Keyword.OVERWRITE) raf.seek(0); else if (ifExists == Keyword.APPEND) raf.seek(raf.length()); else raf.setLength(0); } } > Note that as with CLISP I have to avoid supplying :if-exists > :overwrite as otherwise an illegal seek will still occur (whereas it > is necessary to supply the keywords in some other implementations). > Both variations appear to be conforming. I don't think :IF-EXISTS :OVERWRITE should cause any breakage in this situation, and with the new fix it doesn't: CL-USER(1): (defparameter *stdout* (open "/dev/stdout" :direction :output :if-exists :overwrite :element-type '(unsigned-byte 8))) *STDOUT* CL-USER(2): (write-sequence #(65 66 67 10) *stdout*) #(65 66 67 10) CL-USER(3): (force-output *stdout*) ABC NIL Thanks for your work on this issue! -Peter |