5.10. Determining the Current Position Standard REXX does not have any seek call that returns the current position in a stream. Instead, it provides two calls that returns the amount of data remaining on a stream. These two built-in functions are LINES() and CHARS(). · The LINES() built-in function returns the number of complete lines left on the stream given as its first parameter. The term “complete lines” does not really matter much, since an implementation can assume the end-of-file to implicitly mean an end-of-line. · The CHARS() built-in function returns the number of character left in the stream given as its first parameter. This is one of the concepts where REXX I/O does not map very well to C I/O and vice versa. While REXX reports the amount of data from the current read position to the end of stream, C reports the amount of data from the start of the file to the current position. Further, the REXX method only works for input streams, while the C method works for both input and output files. On the other hand, C has no basic constructs for counting remaining or reposition at lines of a file. Example: Retrieving current position So, how does one find the current position in a file, when only allowed to do normal repositioning? The trick is to reposition twice, as shown in the code below. ftell: procedure parse arg filename now = chars(filename) call charin filename, 0, 1 total = chars(filename) call charin filename, 0, total-now return total-now Unfortunately, there are many potential problems with this code. First, it only works for input files, since there is no equivalent to CHARS() for output files. Second, if the file is empty, none of the repositioning work, since it is illegal to reposition at or after end-of-file for input files—-and the end-of-file is the first position of the file. Third, if the current read position of the file is at the end of file (e.g. all characters have been read) it will not work for similar reasons as for the second case. And fourth, it only works for persistent files, since transient files do not allow repositioning. Example: Improved ftell function An improved version of the code for the ftell routine (given above), which tries to handle these problems is: ftell: procedure parse arg filename signal on notready name not_persist now = chars(filename) signal on notready name is_empty call charin filename, 0, 1 total = chars() if now>0 then call charin filename, 0, total-now+1 else if total>0 then call charin filename, 1, total else nop /* empty file, should have raised NOTREADY */ return total-now+1 not_presist: say filename ‘is not persistent’; return 0 is_empty: say filename ‘is empty’; return 0 The same method can be used for line-oriented I/O too, in order to return the current line number of an input file. However, a potential problem in that case is that the routine leaves the stream repositioned at the start of the current line, even if it was initially positioned to the middle of a line. In addition, the line-oriented version of this ftell routine may prove to be fairly inefficient, since the interpreter may have to scan the whole file twice for end-of-line character sequences.