5.13.3 LINES() and CHARS() are Inaccurate
Because of the large differences between various operating
systems, REXX allows some fuzz in the implementation of the
LINES() and CHARS() built-in functions.  Sometimes, it is
difficult to calculate the number of lines or characters in a
stream; generally because the storage format of the file often
requires a linear search through the whole stream to determine
that number. Thus, REXX allows an implementation to return the
value 1 for any situation where the real number is difficult or
impossible to determine. Effectively, an implementation can
restrict the domain of return values for these two functions only
1 and 0 from these two functions.

Many operating systems store lines using a special end-of-line
character sequence. For these systems, it is very time-consuming
to count the number of lines in a file, as the file must be
scanned for such character sequences. Thus, it is very tempting
for an implementor to return the value 1 for any situation where
there are more than zero lines left.

A similar situation arises for the number of characters left,
although it is more common to know this number, thus it is
generally a better chance of CHARS() returning the true number of
characters left than LINES() returning the true number of lines
left.

However, you can be fairly sure that if an implementation returns
a number greater than 1, then that number is the real number of
lines (or characters) left in the stream. And simultaneously, if
the number returned is 0, then there is no lines (or characters)
left to be read in the stream. But if the number is 1, then you
will never know until you have tried.

Example: File reading idiom

This example shows a common idiom for reading all contents of a
file into REXX variables using the LINES() and LINEIN() built-in
functions.

     i = 1
     signal on notready
     lleft = lines(file)
     do while lleft>0
          do i=i to i+lleft
               line.i = linein(file)
          end
          lleft = lines(file)
     end
     notready:
     lines.0 = i-1

Here, the two nested loops iterates over all the data to be read.
The innermost loop reads all data currently available, while the
outermost loop checks for more available data. Implementations
having a LINES() that return only 0 and 1 will generally iterate
the outermost loop many times; while implementations that returns
the “true” number from LINES() generally only iterates the
outermost loop once.

There is only one place in this code that LINEIN() is called.  The
I variable is incremented at only one place, and the variable
LINES.0 is set in one clause, too. Some redundancy can be removed
by setting the WHILE expression to:

     do while word(value(‘lleft’,lines(file)) lleft,2)>0

The two assignments to the LLEFT variable must be removed.  This
may look more complicated, but it decreases the number of clauses
having a call to LINES() from two till one. However, it is less
certain that this second solution is more efficient, since using
VALUE() built-in function can be inefficient over “normal”
variable references.



PREV NEXT