Copyright (c) 2012-2016 Hyperion Entertainment and contributors.

AmigaOS Manual: ARexx Input and Output

From AmigaOS Documentation Wiki
Jump to: navigation, search

ARexx's input and output model consists of three parts: character input streams, character output streams, and an external data stack. The input and output streams can be manipulated character-by-character or line-by-line, while the data stack can be accessed only by line operations.

The External Data Stack

The external data stack is ARexx's queue service. An ARexx program can store character strings (lines) to the stack and pull strings out of the stack. The external data stack is connected to the command line interface which is the standard input/output stream. The external data stack provides an alternative way for inter-process-communication, since a parent program can pull lines from the stack which where pushed there by a child program and a child program can pull lines from the stack which were pushed there by a parent program.

There are two instructions for adding lines of text to the external data stack. PUSH will add one line at the top of the stack while QUEUE will add the line at the bottom of the stack. Despite of the stack's connection to the standard input/output stream, lines stored in the external data stack will not be visible to the user until an ARexx script exits. Only after then the whole content of the stack will be emptied to the standard output stream.

PULL instruction is used for reading and removing the top-most line from the external data stack. If the stack is empty, PULL will read a line from the standard input stream, i.e. from the console window.

Program 17. ReadLine.rexx

/* 
** Read a line from the console window. 
*/
SAY 'Type anything and press enter.'
 
/* 
** PULL will read a line from the standard input since
** the external data stack is empty.                   
*/
PULL line
SAY 'You typed:' line

The external data stack can operate as a stack or a queue, depending on which instruction has been used for filling the stack: PUSH or QUEUE.

When a PUSH instruction is used for adding a line to the stack, the line will be added at the top of the stack. Together with a PULL instruction this forms a stack data structure where last inserted line is pulled out first – last-in-first-out (LIFO).

Program 18. Stack.rexx

/* 
** Stack example 
*/
/* Put 3 lines to the stack */
PUSH 'Item 1'
PUSH 'Item 2'
PUSH 'Item 3'
 
/* Pop 3 lines from the stack */
PARSE PULL first
PARSE PULL second
PARSE PULL third
 
SAY '1st' first
SAY '2nd' second
SAY '3rd' third

If a QUEUE instruction is used for adding a line to the stack, the line will be added at the bottom of the stack. Together with a PULL instruction this forms a queue data structure where the first inserted line is pulled out first – first-in-first-out (FIFO).

Program 19. Queue.rexx

/* 
** Queue example 
*/
/* Put 3 lines to the stack */
QUEUE 'Item 1'
QUEUE 'Item 2'
QUEUE 'Item 3'
 
/* Pop 3 lines from the stack */
PARSE PULL first
PARSE PULL second
PARSE PULL third
 
SAY '1st' first
SAY '2nd' second
SAY '3rd' third

If the number of stacked items is unknown, you can use LINES function to find out how many lines there currently are in the stack. The program below demonstrates how to empty the stack by utilising the LINES function.

Program 20. EmptyStack.rexx

/*
** Empty the external data stack
*/
/* Add 4 lines to the external stack */
QUEUE 'Tinker, Tailor,'
QUEUE 'Soldier, Sailor,'
QUEUE 'Rich Man, Poor Man,'
QUEUE 'Beggar Man, Thief.'
 
/* Pull all lines from the stack */
DO LINES( STDIN )
    PARSE PULL line
    SAY line
END

Examples

An example of inter-process-communication through the external data stack.

Program 21. Parent.rexx

/* 
** This program adds data to the external stack, then
** executes the child program 'Child.rexx', which reads the data
** from the stack, and finally reads child's reply from the stack.
*/
/* Add two lines to the stack */
SAY 'Parent: sending data to child...'
QUEUE 'Item 1'
QUEUE 'Item 2'
 
/* Execute child */
ADDRESS command 'RX Child.rexx'
 
/* Get child's reply */
PARSE PULL message
SAY 'Parent: Got the following reply:' message

Program 22. Child.rexx

/* 
** Child program
*/
 
/* Get data */
PARSE PULL first
PARSE PULL second
SAY 'Child: Received the following data:'
SAY '     ' first
SAY '     ' second
 
/* Reply through the external stack */
PUSH 'Thanks!'

The Character Input and Output Streams

The character input and output streams are used for reading and writing to files. The following functions are available for the streams:

CLOSE Close an input/output stream.
EOF Check if the read/write position of the stream is at the end of the stream.
OPEN Open an input/output stream.
READCH Reads specified number of characters from a previously opened input stream at the current stream position.
READLN Reads a line from a previously opened input stream at the current stream position.
SEEK Moves the stream's read/write position.
WRITECH Writes a string to a previously opened output stream at the current stream position.
WRITELN Writes a line to a previously opened output stream at the current stream position.

The general procedure of writing to a file is as follows:

  1. Open an output stream using OPEN function.
  2. Write to the stream using WRITECH or WRITELN function.
  3. Close the stream using CLOSE function.

Example 23. CreateFile.rexx

/* Create a file */
file = 'RAM:myfile.txt'
 
/* Open a file for writing */
IF ~OPEN( 'MYFILE', file, 'W' ) THEN DO
    SAY 'Failed to create file "' || file || '".'
    EXIT 10
END
 
/* Write to the file */
CALL WRITELN( 'MYFILE', 'It goes in the morning on four feet,' )
CALL WRITELN( 'MYFILE', 'at lunch-time on two,' )
CALL WRITELN( 'MYFILE', 'in the evening on three.' )
CALL WRITELN( 'MYFILE', '' )
CALL WRITELN( 'MYFILE', 'What is it?' )
 
/* Close the file */
CALL CLOSE( 'MYFILE' )

The general procedure of reading from a file is as follows:

  1. Open an input stream using OPEN function.
  2. Read characters or lines from the stream using READCH or READLN function.
  3. Close the stream using CLOSE function.

Example 24. ReadFile.rexx

/* Read a file */
file = 'RAM:myfile.txt'
 
/* Open a file for reading */
IF ~OPEN( 'MYFILE', file, 'R' ) THEN DO
    SAY 'Failed to open file "' || file || '".'
    EXIT 10
END
 
/* Read the whole file content or maximum of 65535 characters */
content = READCH( 'MYFILE', 65535 )
 
/* Close the file */
CALL CLOSE( 'MYFILE' )
 
/* Print file content */
SAY content

The character input and output stream functions can also be used for reading and writing to the standard input and output stream – to the console window. ARexx opens and closes the input and output streams to the standard input and output automatically and provides a common logical name for accessing the standard input/output stream: STDIN.

Reading and writing to the console window is simpler than reading and writing to a file because you do not have to open and close the stream – ARexx will do that for you. To read a line from the console window you just call the READLN function with the logical name of STDIN:

line = READLN( STDIN )

Writing to the console window is equally easy:

CALL WRITELN( STDIN, 'Hello world!' )

The advantage of using the input/output functions over SAY and PULL instructions is that you can read and write restricted number of characters to the console instead of lines.

Example 25. ReadCharacters.rexx

/* Read 3 characters from the standard input */
characters = READCH( STDIN, 3 )
SAY characters
 
/* Any extra characters are stored in the     */
/* external data stack and can be pulled out. */
PARSE PULL extraChars
SAY extraChars

The following program shows how to print text without changing a line.

Example 26. WriteCharacters.rexx

/* Print prompt using WRITECH */
CALL WRITECH( STDIN, "Hi! I'm Amiza. What is your problem? " )
 
PARSE PULL line
SAY 'I see.'