5.13.10 Main Differences from Standard REXX Now, as the functionality has been explained, let me point out the main conceptual differences from standard REXX; they are: [Current position.] ARexx does not differ between a current read and write position, but uses a common current position for both reading and writing. Further, this current position (which it is called in this documentation) can be set to any byte within the file, and to the end-of-file position. Note that the current position is zero-based. [Indirect naming.] The stream I/O operations in ARexx do not get a parameter which is the name of the file. Instead, ARexx uses an indirect naming scheme. The OPEN() built-in function binds a REXX stream name for a file to a named file in the AmigaDOS operating system; and later, only the REXX stream name is used in other stream I/O functions operating on that file. [Special stream names.] There are two special file names in ARexx: STDOUT and STDIN, which refer to the standard input file and standard output file. With respect to the indirect naming scheme, these are not file names, but names for open streams; i.e. they can be used in stream I/O operations other than OPEN(). For some reason, is it possible to close STDIN but not STDOUT. [NOTREADY not supported.] ARexx has no NOTREADY condition. Instead, you must detect errors by calling EOF() and checking the return codes from each I/O operations. [Other things missing.] In ARexx, all files must be explicitly opened. There is no way to reposition line-wise, except for reading lines and keeping a count yourself. Of course, ARexx also has a lot of functionality which is not part of standard REXX, like relative repositioning, explicit opening, an end-of-file indicator, etc. But this functionality is descriptive above in the descriptions of extended built-in functions, and it is of less interest here. When an ARexx script has opened a file in Write mode, other ARexx scripts are not allowed to access that file. However, if the file is opened in Read or Append mode, then other ARexx scripts can open the file too, and the same state of the contents of the file is seen by all scripts. Note that it is difficult to translate between using standard REXX stream I/O and ARexx stream I/O. In particular, the main problem (other than missing functionality in one of the systems) is the processing of end-of-lines. In standard REXX, the end-of-file is detected by checking whether there is more data left, while in ARexx one checks whether the end-of-file has been read. The following is a common standard REXX idiom: while lines(‘file’)>0 /* for each line available */ say linein(‘file’) /* process it */ end In ARexx this becomes: tmp = readln(‘file’) /* attempt to read first line */ do until eof(‘file’) /* if EOF was not seen */ say tmp /* process line */ tmp = readln(‘file’) /* attempt to read next line */ end It is hard to mechanically translate between them, because of the lack of an EOF() built-in function in standard REXX, and the lack of a LINES() built-in function in ARexx. Note that in the ARexx example, an improperly terminated last line is not read as an independent line, since READLN() searches for an end-of-line character sequence. Thus, in the last invocation tmp is set to the last unterminated line, but EOF() returns true too. To make this different, make the UNTIL subterm of the DO loop check for the expression EOF(‘file’) && TMP<>“. The limit of 1000 characters for READLN() means that a generic line reading routine in ARexx must be similar to this: readline: procedure parse arg filename line = ‘’ do until length(tmpline)<1000 tmpline = readln(filename) line = line || tmpline end return line This routine calls READLN() until it returns a line that is shorter than 1000 characters. Note that end-of-file checking is ignored, since READLN() returns an empty string a the end-of- stream.