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.