When a procedure is a data target, it is signalled that it has been closed by one final callback with a possibly empty string containing any final buffered data, and the boolean false. GS 8.51 does not seem to do this unless the buffer is nonempty at time of closefile: AFPL Ghostscript 8.51 (2005-04-18) Copyright (C) 2005 artofcode LLC, Benicia, CA. All rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for details. GS>{ =only == ( ) } /NullEncode filter dup (Hi) writestring closefile true() true(H) false(i) % good, but: GS>{ =only == ( ) } /NullEncode filter dup (Hi) writestring GS<1>dup flushfile closefile true() true(H) true(i) GS> % whoa, where's the close? and even: GS>{ =only == ( ) } /NullEncode filter closefile GS> % whoa, where's the close? By contrast: PostScript(r) Version 3010.108 (c) Copyright 1984-1999 Adobe Systems Incorporated. Typefaces (c) Copyright 1981 Linotype-Hell AG and/or its subsidiaries. All Rights Reserved. PS>{ =print == ( ) } /NullEncode filter dup (Hi) writestring dup flushfile true() true(H) true(i) PS>closefile false() % good, gets closed PS>{ =print == ( ) } /NullEncode filter closefile false() % good, gets closed Not sure when this changed; my code that relies on procedure data targets worked in GS 7.07, but 8.51 is definitely broken. The bug means a data target procedure that needs to take special action on close fails badly.
Weird: in CVS diffs for zfproc.c, I don't see anything between 7.07 and 8.51 that looks like it could account for this - but I definitely never saw the problem before upgrading, and now it's entirely repeatable.
Performing regression test (on Genoa test suite) with the patch: *************** *** 279,285 **** stream_proc_state *const ss = (stream_proc_state *) st; uint rcount = pr->limit - pr->ptr; ! if (rcount > 0) { uint wcount = r_size(&ss->data) - ss->index; uint count = min(rcount, wcount); --- 279,286 ---- stream_proc_state *const ss = (stream_proc_state *) st; uint rcount = pr->limit - pr->ptr; ! /* if 'last' return CALLC even when rcount == 0. ss->eof terminates */ ! if (rcount > 0 || (last && !ss->eof)) { uint wcount = r_size(&ss->data) - ss->index; uint count = min(rcount, wcount); ----------------------------------------------------------------------------- This definitely results in the 'false' call, producing: true() true(H) true(i) false() and *should* be OK for other proc_write usage. As the PLRM states, Encode filters are fairly rare, and procedure targets are a subset of those. I will examine the Genoa tests to see which, if any, of them tests this case. If no problems, I will commit.
Patch committed. Testing showed no problems.