>Well, it depends on which Rexx you are using. In CMS Rexx (i.e. no
>standard Rexx I/O) you would be doing something like:
>
> DO FOREVER
> 'EXECIO 1 DISKR ...'
> IF (rc <> 0) THEN LEAVE
> PARSE PULL xxx
> ...
But if you have this (on CMS or TSO), it's even better to do
'EXECIO * DISKR' filename '(FINIS)'
do queued()
parse pull line
call do_something_with_this_line line
end
or
'EXECIO * DISKR' filename '(FINIS STEM FOO.)'
do i = 1 to foo.0
call do_something_with_this_line foo.i
end
Then you're not limited to blindly groping through the file
sequentially. You can treat the entire contents of the file
as an in-memory array and do Neat Things with it. Of course,
your system has to have the megabytes...
--
Steve Bacher (Batchman) Draper Laboratory
Internet: s...@draper.com Cambridge, MA, USA
'PIPE < DISK FILE A | STEM FOO.'
but as long as you've got PIPE you can possibly do all your manipulation
of the file with PIPE filters, instead of with considerably slower Rexx
variables. You might even be able to use PIPE filters to avoid any need
to read the whole file into storage. But that is the topic of another
newsgroup.
I precisely did NOT recommend reading the whole thing into storage in
either the stack or an array, because it artificially limits the size of
a file you can process, and it is wasteful of a resource that is
constrained on many systems - memory. Why cause all that paging and such
unless you have a good reason to? (But as I said, If you have a good
reason, do it with PIPE.)
Roger Deschner, University of Illinois at Chicago U52...@UICVM.UIC.EDU
/**/ CALL TIME('R')
do 10; 'execio * diskr all notebook a0 (stem JUNK.'; end
say time('e')
do 10; 'pipe < all notebook a0 | stem junk.' ; end
Say time('e')
EXECIO appeared to be a lot faster whether it ran first or second. Comments?
Dave Gomberg, role model for those who don't ask much in their fantasy lives.
GOMBERG@UCSFVM Internet node UCSFVM.UCSF.EDU fax-> (415)731-7797
>As a separate matter, in another thread on some other day it might
>be interesting to discuss the merits of worrying so much about
>portability.
The simple answer is that "There is no portable way" means "I can't tell you
the answer because I don't know what system you are on (and even if I did I
might not know how it deals with this issue)".
Clearly, portability is difficult if not impossible for any program
which issues host commands. However, it does no harm to try and make a
program as portable as possible, for instance by using standard stream
I/O instead of system-dependent things like eof(). Some people obviously
thought portability was important enough to set up the ANSI committee to
design a "standard" REXX.
Having said that, using features which are specific to ANSI or to language
level 4.00 does not ensure portability because there are a number of older
interpreters which do not support these features.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
>There is no portable way to detect the end-of-file condition on interpreters
>below language level [4.00]
and
>The simple answer is that "There is no portable way" means "I can't tell you
>the answer because I don't know what system you are on (and even if I did I
>might not know how it deals with this issue)".
Portability is one thing, but I think we really have a severe problem with
a language that forces you to resort to the hugely forbidden technique of
using a SIGNAL as a GOTO in order to deal with the universally present
situation of End Of File.
Come now. Even Common Lisp, that amalgam of dialects overly concerned
with portability of programming language concepts to the point where
(gc) and (exit) were omitted from the language definition because there
were no portable ways to define garbage collection and exiting a program,
found room to include an EOF flag on the READ function.
Do you really believe that a language touted as making life easy for
the user should require said user to code SIGNAL ON NOTREADY (what in blazes
does "end of file" have to do with "not ready"? Does that mean that if
I wait long enough, another record will magically appear?) and do a
state-losing jump into space in order to deal with this?
Why sink to, nay below, the level of TSO CLIST?
- seb
I guess this is MVS-FLAME (tm). Of course, Steve misses the point that a
transient file may not have any more records now, but may have more records
later. Coming from an environment that had trouble with the ELSE keyword, he
deserves our sympathy, not our derision. Let us hope the REXXLIST rises above
this kind of oral diarrhea (tm). Dave
>I guess this is MVS-FLAME (tm). Of course, Steve misses the point that a
>transient file may not have any more records now, but may have more records
>later. Coming from an environment that had trouble with the ELSE keyword, he
>deserves our sympathy, not our derision.
Last time I checked, Unix had EOF too. C has feof()...
- seb
Who said that? Firstly, I supplied two alternatives, which means you aren't
forced to do any one thing. Secondly, "signal on notready" is not exactly
"the hugely forbidden technique of using a SIGNAL as a GOTO" because it
really is being used as an exception handler; the main drawback is that
it causes state loss (how much state loss is another matter. TRL seems
to imply that only state within the current function is lost; Uni-REXX
and Regina agree. My opinion, and REXX/imc's behaviour, is that state
within the function containing the "signal on" instruction should be lost.
However, there may be some implementations where state within the current
program is lost).
>Come now. Even Common Lisp [...]
>found room to include an EOF flag on the READ function.
How does this work exactly (I'm not a Lisp programmer, probably never
will be)? Is it different from testing stream(file)\="READY"?
Now, if you are using REXX/imc then you can use the option "SETRC" which
causes "parse pull" and "linein" to set the variable RC to indicate success
or failure (and 99 equals EOF). This is really a compatibility mode
(provided because earlier versions of REXX/imc, not having the NOTREADY
condition or the stream() function, used RC in this manner), but one could
still use it if it is thought necessary.
> (what in blazes
>does "end of file" have to do with "not ready"? Does that mean that if
>I wait long enough, another record will magically appear?)
In my opinion, yes this is possible. Particularly if the input is a
terminal. The unix command "tail -f"[*] is an example of a utility
which uses a similar magical feature. REXX/imc could be used to implement
"tail -f", if so desired.
The ANSI committee has different ideas. It says that if lines() should
ever return zero, then all further inputs must fail. However, I suppose a
conforming implementation could behave like "tail -f" as long as lines()
were implemented as:
lines: return 1
[*]The command "tail -f file" prints out the last portion of the file but
does not stop when the last line of the file has been printed. Instead
it enters an infinite loop, sleeping for a second and then attempting to
read further records from the file. This command may be used to monitor
the growth of a file that is being written by some other process.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
>>>Do you really believe that a language touted as making life easy for
>>>the user should require said user to code SIGNAL ON NOTREADY (what in blazes
>>>does "end of file" have to do with "not ready"? Does that mean that if
>>>I wait long enough, another record will magically appear?)
>Last time I checked, Unix had EOF too. C has feof()...
Unless I missed it being mentioned already, I want to point out that
REXX indeed has the equivalent of EOF() since version 3.50. CHARS(name)
returns 0 if there are no more characters remaining in the input stream
name (which may be a file), and LINES(name) returns 0 if there are no
more complete lines remaining in it.
Unfortunately, a version 3.50 (or better) implementation of REXX may be
still in the future of VM/CMS or MVS though. Maybe this is what makes
Steve angry, and I could understand that very well.
Horst
- - - - - - - - - - - - - - - - - - - - - - -
Horst Kiehl - Internet h.p....@kfa-juelich.de
Does that mean that the REXX programmer has to test the value of CHARS()
or LINES() on every read? On some OS's this could mean checking the
remaining size of a file (number-of-lines-or-chars) times. I leave it
up to others to compute the O(n) value of that algorithm.
>Unfortunately, a version 3.50 (or better) implementation of REXX may be
>still in the future of VM/CMS or MVS though. Maybe this is what makes
>Steve angry, and I could understand that very well.
I don't think so, since mainframe REXX doesn't even have LINExx and
CHARxx functions. However, EXECIO, which it does have, supports
end of file detection via the * (read the whole file) function and
also by return codes when reading at end of file. So it is the
non-MVS implementations, not the MVS ones...
- seb
>How does this work exactly (I'm not a Lisp programmer, probably never
>will be)? Is it different from testing stream(file)\="READY"?
The following is from "Common Lisp: The Language, Second Edition",
by Guy L. Steele, Jr.- aka "The Bible".
(c) copyright 1990 by Digital Equipment Corp.
--- beginning of excerpts ---
read &optional input-stream eof-error-p eof-value recursive-p [Function]
read reads in the printed representation of a Lisp object from input-stream,
builds a corresponding Lisp object, and returns the object.
...
Section 22.2.1. Input from Character Streams.
Many character input functions take optional arguments called input-stream,
eof-error-p, and eof-value. ...
The eof-error-p argument controls what happens if input is from a file (or
any other input source that has a definite end) and the end of the file is
reached. If eof-error-p is true (the default), an error will be signaled at
end of file. If it is false, then no error is signaled, and instead the
function returns eof-value.
X3J13 voted in January 1989 (7) to clarify that an eof-value
argument may be any Lisp datum whatsoever.
Functions such as read that read the representation of an object rather than
a single character will always signal an error, regardless of eof-error-p, if
the file ends in the middle of an object representation. ... Similarly, the
function read-line will successfully read the last line of a file even if that
line is terminated by end-of-file rather than the newline character. ...
--- end of excerpts ---
- seb
Yes, indeed. Heck, though nobody is queued up, the door is still
open and more people could indeed walk through (even if hours
later).
>The ANSI committee has different ideas. It says that if lines() should
>ever return zero, then all further inputs must fail.
I can understand this if one doesn't want to chance going into a
wait-forever loop. (Like, I hate waiting a minute or so when after
10 seconds I know it's not worth waiting for the telnet connection
to be made and I can't do a Ctrl-Z to stop the task...).
But having the OPTION to be able to "leave the door open even if the
queue seems empty" would be very nice, and may even be *necessary*
in multitasking environments? Like when merging outputs of pipes?
(Or am I spouting nonsense? :-) )
Regards.
$$/ (Yes Steve, "EOF or BUST!" :-) )
> Unless I missed it being mentioned already, I want to point out that
> REXX indeed has the equivalent of EOF() since version 3.50. CHARS(name)
> returns 0 if there are no more characters remaining in the input stream
> name (which may be a file), and LINES(name) returns 0 if there are no
> more complete lines remaining in it.
I had a REXX program that used LINES() to discover end-of-file. I ran
it on OS/2, and it was impossibly slow. I think it was reading the
whole file to count the lines, and the file was a few meg, and it was
located on an NFS volume...
I changed it to the following, and it was a lot faster:
call on notready name seteof
eof = 0
do forever
i = linein()
if eof then leave
whatever...
end
return
seteof: procedure expose (eof)
eof = 1
return
I think this much work to detect EOF is silly...
--
Richard Krehbiel ri...@kastle.com or ri...@netcom.com
Nothing witty comes to mind...
: Does that mean that the REXX programmer has to test the value of CHARS()
: or LINES() on every read? On some OS's this could mean checking the
: remaining size of a file (number-of-lines-or-chars) times. I leave it
: up to others to compute the O(n) value of that algorithm.
Only if the programmer doesn't make some reasonable simplifying
assumptions.
uni-REXX LINES(...) reads the file all the way through the first time itis
is called, but from that point on (as long as the file size does not
change) it simply remembers how many lines it has gone past and does
some simple math to return the current value of LINES.
-Ed
--
========================================================================
========= The morning will bring joy, for every girl and boy. ========
Ed Spire e...@wrkgrp.com (on uunet)
Me, too. How about:
DO FOREVER; i=LINEIN(Ifn); IF LENGTH(i)=0 THEN LEAVE; whatever...; END
At least if you use a null line to signal eof or don't have null lines in
your file. Dave
Edward T Spire <e...@wrkgrp.com> writes:
>Only if the programmer doesn't make some reasonable simplifying
>assumptions.
You are talking about the REXX implementer, not the REXX programmer,
as I gather from what follows.
REXX programmers have little knowledge of, or control over, the abilities
or forethought of the implementer, in the general case.
>uni-REXX LINES(...) reads the file all the way through the first time itis
>is called, but from that point on (as long as the file size does not
>change) it simply remembers how many lines it has gone past and does
>some simple math to return the current value of LINES.
I'm glad to hear that, but if I hadn't read this message I would not
consider using such a technique, especially after Rick K's experience.
- seb
> DO FOREVER; i=LINEIN(Ifn); IF LENGTH(i)=0 THEN LEAVE; whatever...; END
>
>At least if you use a null line to signal eof or don't have null lines in
>your file. Dave
How about
DO FOREVER; i=LINEIN(Ifn); IF i='999999' THEN LEAVE; whatever...; END
Just as valid, IMHO.
Never make assumptions about the content of an input file.
- seb
Seb, your choice would be just as good in an implementation that set i
to all nines after end-of-file. Sadly, or I guess I should say happily,
I don't know of any like that. But if you find one, your code should
work great. Till then, use mine.
What if you're reading from a terminal? Then you can never be sure
the last record is really the last, because more records may come along.
To be brief:
I know that.
I'm talking about the "obvious" case where one is reading from a file.
When one reads from a file, one expects to reach the end. 99.9% of all
small programs expect to reach the end of their input file.
Why can't a user-friendly language do the obvious>
I hope this is the end of this particular thread. Many ideas have been
brought out, and many views of the problem have been elucidated. It is
now up to the implementators to debate the issue. Thank you all for
your responses.
- seb
Quite possibly it was. Did you try changing it to chars()? It doesn't
need to read the whole file for that, and it should be the case that
(chars()=0) == (lines()=0)
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
>>How does this work exactly (I'm not a Lisp programmer, probably never
>>will be)? Is it different from testing stream(file)\="READY"?
>The following is from "Common Lisp: The Language, Second Edition",
That did not answer my question. It told me that you can set the function
to treat eof as an error. But what happens on error? Does it call some
function, or just set a flag that you can check later?
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
>I can understand this if one doesn't want to chance going into a
>wait-forever loop.
>But having the OPTION to be able to "leave the door open even if the
>queue seems empty" would be very nice, and may even be *necessary*
As far as I am aware, the following is currently true: if the input is a
terminal, then the implementation is encouraged to return lines()=1 until
a real EOF is discovered (but whatever it does, it has to obey the above
rule). That is, lines() could equal 1 even when no input is present.
This is to allow programmers to write a loop which does not stop until
the input has certainly finished.
The following will be true eventually: lines() will have an extra option
(something like 'W' for 'waiting'), which allows the implementation to
return the actual number of lines waiting to be read - or at any rate, an
indication of whether lines are waiting. However, it will still be true
that once you have called lines() without this option and obtained a zero
result, all further inputs must fail.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
imc>How does this work exactly (I'm not a Lisp programmer, probably never
imc>will be)? Is it different from testing stream(file)\="READY"?
seb>The following is from "Common Lisp: The Language, Second Edition",
imc>That did not answer my question. It told me that you can set the function
imc>to treat eof as an error. But what happens on error? Does it call some
imc>function, or just set a flag that you can check later?
Error handling was not defined in Common Lisp I. Subsequently a sophisticated
condition handling system was defined in CL II. Without going into too much
detail, you can define an error handler to get control when certain types of
events occur, including signalled Lisp errors. Since this all happens within
carefully defined scopes (as with all Lisp constructs), the behavior is
well defined and no loss of state need be feared.
Setting the EOF parameter on READ is better, though. The typical way one
does this in Lisp is to set it to an object that cannot possibly be equal
(or EQ, to use the precise Lisp function) to any other object. The best
way to construct such an object in Lisp is to use the expression
(cons nil nil).
Using NIL as an EOF marker may be OK for some situations, but in general
is ill-advised, as it is likely that a NIL will be read from the input
stream. Same for very-weird-symbol or "imPoSsIble_stRing". You never
know what will crop up.
- seb
Sounds good 'nuf to me. :-)
Regards.
$$/
>In article <RICH.93N...@friend.kastle.com>, ri...@kastle.com (Richard L. it should be the case that
>
>(chars()=0) == (lines()=0)
Not on all systems. Under DOS or OS/2, a line end can consist of the two
characters carriage return, CR, and line feed, LF. When the last two
characters of a file are CR LF, and the read postition is on the last
one, LF, CHARS() returns 1 but LINES() already returns 0.
(I've just tested this on my OS/2 2.1 system with the built-in REXX
interpreter; it's version string is "REXXSAA 5.00 08 Jul 1992".)
Thus, you can't say the above, but you can say the following:
(chars() == 0) /* implies */ (lines() == 0)
I want to say more about the result of LINES() but I'll better open
another thread for that.
You started this by flippantly asking "What has "NOTREADY" got to do with
EOF? Does that mean that some time later another record will magically
appear?" However, that is beside the point...
>When one reads from a file, one expects to reach the end. 99.9% of all
>small programs expect to reach the end of their input file.
>Why can't a user-friendly language do the obvious>
Steve, would you like to tell me what "the obvious" is?
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
Remarkably, it appeared in a completely unrelated posting...
do until eof(file)
x = linein(file)
end
or something like that...
- seb
>do until eof(file)
> x = linein(file)
>end
eof: return stream(arg(1))\="READY" /* is that not good enough for you? */
Unless, of course, you want eof() to return 1 when the end of the file has
been reached but before it has been discovered. In that case, it would
have to be implemented by the interpreter attempting to read a character
from the file without you having asked for one, and I'm not terribly happy
about that. For one thing, you don't want to start reading ahead when the
input is a terminal because that could pause the program unexpectedly.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
} In article <931112212...@support4.draper.com>, "Stephen E. Bacher" <s...@DRAPER.COM> wrote:
} >>Steve, would you like to tell me what "the obvious" is?
}
} >do until eof(file)
} > x = linein(file)
} >end
}
} eof: return stream(arg(1))\="READY" /* is that not good enough for you? */
Dunno if it is good enough or not, since I'm not sure what it does. ARexx
doesn't have a 'stream()'. [It does, however, have eof()].
Another footnote on the end-of-file discussion is that *in*ARexx*, there
is _no_ "chars()" call and the lines() call works _only_ for queued
interactive input, *NOT* for general file input.
As far as I can tell, in ARexx eof(handle) is the *only* way to detect
end of file.
/Bernie\
--
Bernie Cosell cos...@world.std.com
Fantasy Farm Fibers, Pearisburg, VA (703) 921-2358
>Not on all systems. Under DOS or OS/2, a line end can consist of the two
>characters carriage return, CR, and line feed, LF. When the last two
>characters of a file are CR LF, and the read postition is on the last
>one, LF, CHARS() returns 1 but LINES() already returns 0.
I could understand it being the other way around, but that OS/2 behaviour
seems to be "wrong" to me. If the last line of your file is blank then does
linein() signal a "notready" when it reaches that line or does it happily
return the empty string? If the latter then lines() should surely return 1
immediately before the linein() is called. If the former then something is
wrong with a system which ignores a blank last line.
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk
I don't understand your point; perhaps you misunderstood me.
The particular instance of behaviour of the OS/2 REXX interpreter I
described seems correct to me. CR and LF together mark the end of a
line. When the read position is on the LF then there's no complete line
left, and LINES() returns 0, but there's still one character, and
CHARS() returns 1.
*But*, as I described in an article with an own subject (crossposted
to both comp.lang.rexx and comp.os.os2.programmer.misc), I found out
that the beaviour of the OS/2 REXX interpreter for LINES() near the end
of a file seems bogus. Even if the last line of a file isn't terminated
by a CR LF sequence (but the last "regular" character of the last line
is the last character in the file), LINES() returns 1 if the read
position is on the second-to-last character, but it returns 0 if the
read position is on the last character. (CHARS() is correct though.) IE
the result of LINES() near the end of a file seems to depend only on the
distance from the end of the file. :-(
I haven't tested what happens if the end of the file consists of
CR CR LF (for example) or if only LF marks the end of a line in a file,
or the results of LINEIN() or the signalling of NOTREADY. Currently I'm
not very eager to do this - someone else perhaps? (Remember, I'm writing
about the built-in REXX interpreter of OS/2 -
"REXXSAA 4.00 08 Jul 1992".)
I don't believe 'execio' closes the file after reading it so you're not
incurring that overhead (and also not re-opening it on subsequent passes).
Try adding 'finis' to the options and see if the execution times are closer.
Tony Damon
ard...@pacbell.com
>Dunno if it is good enough or not, since I'm not sure what it does. ARexx
>doesn't have a 'stream()'. [It does, however, have eof()].
Stream() is a TRL2 function. When called with one parameter it returns a
word indicating the status of the stream. If the status is anything other
than "READY", then it means that some error has occurred (except when the
status is "UNKNOWN", which usually means that you have never used that
stream before). On an Unix implementation, doing an I/O operation on a
file which resulted in EOF will cause stream() to return "NOTREADY" on
that file.
>Another footnote on the end-of-file discussion is that *in*ARexx*, there
>is _no_ "chars()" call and the lines() call works _only_ for queued
>interactive input, *NOT* for general file input.
ARexx is obviously rather out of date...
Ian Collier
Ian.C...@prg.ox.ac.uk | i...@ecs.ox.ac.uk