I've spent the past few days porting my Mandelbrot Explorer to run on xpost.
And I've run into a bizarre snag. Here's a typescript that illustrates
the problem. [I've inserted '[^D]' to indicate where I hit ctrl-D.]
515(1)10:56 PM:ps 0> cat
interact.ps
{
{ (%lineedit) (r) file }
stopped { clear exit } if
dup bytesavailable
string readline pop
print (\n) print
} loop
516(1)10:59 PM:ps 0> gsnd
interact.ps
GPL Ghostscript 8.62 (2008-02-29)
Copyright (C) 2008 Artifex Software, Inc. All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
a
b
c
[^D]a
b
c
GS>[^D]517(1)11:00 PM:ps 0> xpost -nd
interact.ps
197 opcodes
227 definitions in systemdict
mcp
interact.ps
a
%%[ Error: rangecheck; OffendingCommand: readline ]%%
Stack:
-filestream-
(a)
Exec Stack:
--quit--
{ { handleerror } --if----quit--}
false
-filestream-
--loop--
--cvx--
[ { (%lineedit)(r)file } stopped { clear exit } if dup bytesavailable
string readline pop print (
)print ]
{ pop print (
)print }
stop
mcp launching executive
Xpost Version x2vG
PS<FS>[^D]518(1)11:00 PM:ps 0>
But here's the description from the PLRM 1ed.
readline
reads a line of characters (terminated by newline character) from file
and stores them into successive elements of string. readline then
returns the substring of string that was actually filled and a boolean
indicating the outcome (true normally, false if end-of-file was encoun-
tered before a newline character was read).
The terminating newline character is not stored into string or included
at the end of the returned substring. If readline completely fills string
before encountering a newline character, it executes the error
rangecheck.
So I've implemented this in xpost with the following C function.
OPFN_ void FSreadline(state *st, object f, object s) {
if (!f_status(st, f)) error(st,ioerror);
int n, c = 0;
if (!f.flags.read) error(st,invalidaccess);
for (n = 0; n < s.u.c.n; n++) {
c = getc( *(FILE **)VM(f.u.c.a));
if (c == EOF || c == '\n') break;
STR(s)[n] = c;
}
//if (c != EOF)
if (n == s.u.c.n && c != '\n') error(st,rangecheck);
s.u.c.n = n;
push(s);
push(consbool(c != EOF));
}
So it seems I'm doing *what it says*. But I much prefer
ghostscript's behavior of not signaling this error here.
I toyed with adding the 'if (c != EOF)' part to suppress
the error, but I'm not sure I'm following the standard
by doing that.
Any thoughts?