Using REXX Input/Output Commands

ID: Q99063


SUMMARY

This article lists the input/output capabilities of the REXX programming language and gives examples.


MORE INFORMATION

DISCLAIMER: This article is provided for users capable of developing programs with the information presented; it is not an extensive treatment of the language but rather a quick reference to aid someone in writing simple routines. Microsoft cannot support programming efforts beyond reproducing and submitting problems with the language implementation itself. If you need further assistance, consult REXX references such as "The REXX Language, A Practical Approach to Programming" by M. F. Cowlishaw, Prentice-Hall, Englewood Cliffs, 1985.

Examples are given at the bottom of the listing. Braces ({}) are used to indicate comments.

CHARIN(file|input_stream|kbd, start_read, number_to_read) { Returns number_to_read characters beginning with the file position specified by start_read (start_read cannot be specified for input_streams such as COM1). Specifying zero for number_to_read repositions the current "read point" to start_read. If the number of bytes requested is not available but may become available (that is, COMn) then CHARIN waits on them, otherwise a NOTREADY condition results. }

CHAROUT(output_stream|file|screen, data, start_write) { Writes characters to the specified destination. For files, if the 'data' is not specified then "write point" is moved to start_write. Normally the write point is at the end of the file so that data is always appended to the file by a CHAROUT. If neither 'data' or start_write are given then the file is closed). Processing stops until CHAROUT completes or an error condition is returned. }

CHARS(input_stream|file|kbd) { Returns the number of characters available to read. For STDIN it always returns 1 if data is present (zero otherwise). It always returns 1 for OS/2 devices. }

LINEIN(from_this_source, top_of_source?, number_of_lines) { returns either the line read or zero (from_this_source is opened automatically). If top_of_source is specified as 1 (the only valid value) then the current read point is reset to the first byte in the source. Number_of_lines is either zero (to reposition the read point) or 1. }

LINEOUT(to_this_target, this_data, top_of_target?) { returns the number of lines remaining to be written (usually an error) after this_data is written to to_this_target, if top_of_target? is set to 1 then the write position is set to the first byte of the target, if neither this_data or top_of_target is specified then to_this_target is closed. }

LINES(source) { returns 1 if there is more data available from source, zero otherwise. }

PULL var1 var2 ... var? { returns input into the variables specified. If more 'word' than variables are specified, the trailing words on a line are all placed in the last variable. The effect of PULL, either with or without variables specified, is to empty the input source. }

PUSH var1 var2 ... var? { places the contents of the variables into the input source. Each separate PUSH represents a line in the input source. Example: PUSH a b c creates one line in the input source containing the contents of a, b and c whereas PUSH a;PUSH b;PUSH c puts three lines in the input source, one with the contents of a, a second with the contents of b and a third with the contents of c. }

QUEUE var1 var2 .. . var? { places the variables at the end of the current queue. Each separate QUEUE puts a separate line in the input source. Using the above PUSH example, a 'QUEUE xyz' done after the 'PUSH c' would put xyz's contents in the input source as if a 'PUSH xyz' had been done before the 'PUSH a'. }

QUEUED() { returns the number of lines in the current REXX queue. }

SAY expression { is like the MS-DOS @echo command but evaluates an expression before displaying it on the screen. }

SOURCELINE(n) { returns the current program's line number 'n' or, if 'n' is not specified, the total number of program source lines. }

STREAM(I/O_stream, type_of_action, specific_command) { returns information of a (data) stream based on type_of_action which can be: 'C'ommand (requires a specific_command), 'D'escription (a superset of 'S'tate possibly returning additional information) and 'S'tate (which returns the current state such as ERROR, NOTREADY, READY, this is normally on an open file), specific_commands are: OPEN, CLOSE, SEEK offest, QUERY EXISTS, QUERY SIZE, QUERY DATETIME. The last three return a stream's path, size and date/time if the stream exists. }

Example (explanation follows):

(You are encouraged to extract the code below and run it. If you do, remember to include the beginning comment so that OS/2 recognizes it as a REXX file. In order to do so, you need to create two files: ORDERS and INSTOCK. Also make sure that you do not have a file named LABELS in the directory where you run the program. ORDERS has the following record layout with no carriage-return/line-feeds separating records:


temp_line = STREAM('instock','C','QUERY EXISTS')
IF temp_line = '' THEN
DO
    SAY Stock exhausted
    EXIT
END
temp_line = STREAM('orders','C','QUERY EXISTS')
IF temp_line = '' THEN
DO
    SAY No orders
    EXIT
END
temp_line = SOURCELINE(1)
PUSH "Labels produced by " temp_line
PULL temp_line
n = LINEOUT('labels',temp_line)
n = LINEOUT('labels','')
DO WHILE ((CHARS('instock') > 0) & (LINES('orders') > 0))
lname = CHARIN('orders',,8)
fname = CHARIN('orders',,5)
initial = CHARIN('orders',,1)
PUSH fname initial lname
cust_addr = CHARIN('orders',,10)
city_st_zip = CHARIN('orders',,16)
QUEUE cust_addr
QUEUE city_st_zip
part_desc = LINEIN('instock',,1)
PULL first_line
n = CHAROUT('labels',first_line)
n = LINEOUT('labels',part_desc)
DO WHILE queued() > 0
PULL temp_line
n = LINEOUT('labels', temp_line)
END
END 
The first twelve lines use the STREAM command to test for the existence of the files being used and display error messages using the SAY command if they are not found. Temp_line is used as a working storage string.

Line 13 through 17 use the SOURCELINE command to get the first line of this program's source. Whatever you place there will be written as the first line of the LABELS file. The PUSH effectively combines the result of SOURCELINE with an explanatory prefix which is PULLed back into temp_line and then written to LABELS with the LINEOUT command. PUSH and PULL use a built-in REXX internal queue as temporary storage. Each PUSH creates a carriage-return/line-delimited line in the queue and each PULL removes a line.

Line 18 uses both the CHARS and LINES commands to cause the loop to end when the end of either ORDERS or INSTOCK is encountered.

Lines 19-21 read three variables using CHARIN since ORDERS is not a line-delimited file. The PUSH in line 22 rearranges these three variables for output.

The variables read in lines 23 and 24 are QUEUEd in lines 25 and 26 in order to put the address and city/state/zip after the name in the REXX internal queue. This allows the full address to be put out in the order desired by simply PULLing off of the top of the internal queue.

LINEIN is used in line 27 because INSTOCK is a line-delimited file. PULL is then used in line 28 to get the name which is output using CHAROUT in line 29. CHAROUT is used because it does not add a carriage-return/line- feed and this is desired in order to put the INSTOCK description next to the name in the LABELS file. This is followed by the LINEOUT in line 30 to complete the line.

In line 31 the QUEUED command is used to test for remaining data in the queue and write it out to LABELS.

Additional query words: 2.10 2.1 .10a 2.1a 2.20 2.2

Keywords :
Version :
Platform :
Issue type :


Last Reviewed: November 9, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.