After completing this chapter, you will be able to:
Define Stacks and Queues
Manipulate the data stack
Create a buffer on the data stack
Drop a Buffer
Perform other related functions performed on Buffer
Describe Private stack
Explain application of stacks
REXX in TSO/E uses an expandable data structure called a data stack to store information. The data stack combines characteristics of a conventional stack and queue.
Stacks and queues are similar types of data structures used to temporarily hold data items until needed. When elements are needed, they are removed from the top of the data structure. The basic difference between a stack and a queue is how the elements are added. Elements are added to the top of a stack and to the bottom of a queue.
Let’s consider an example for a data stack:
Using a stack, the last element added to the stack (elem6) is the first removed. As the elements are placed on the top of a stack and removed from the top, the newest elements on a stack are the ones processed first. The technique is called LIFO (last in first out)
Let’s consider an example for a Queue:
Using a queue, the first element added to the queue (elem1) is the first removed. Because elements are placed on the bottom of a queue and removed from the top, the oldest elements on a queue are the ones processed first. The technique is called FIFO (first in first out).
The data stack that REXX uses combines the techniques used in adding elements to stacks and queues. Elements can be placed on the top or the bottom of a data stack. Removal of elements from the data stack, however, occurs from the top of the stack only.
There are several REXX instructions that manipulate the data stack. There are two instructions to add elements to the data stack and one to remove elements from the data stack.
Information can be stored on the data stack with two instructions, PUSH and QUEUE.
PUSH: This puts one item of data on the top of the data stack. There is virtually no limit to the length of the data item.
Elem1 = 'String 1 for the data stack' Elem2 = 'String 2 for the data stack' PUSH Elem1 PUSH Elem2 |
Some people find it less confusing when adding elements in a particular order to the data stack, to consistently use the same instruction, either PUSH or QUEUE, but not both
QUEUE: This puts one item of data on the bottom of the data stack. Again, there is virtually no limit to the length of the data item.
ElemB = 'String B for the data stack' QUEUE ElemA QUEUE ElemB |
After executing the earlier two instructions the stack will look like this,
As and when an element is retrieved from stack, it will be permanently removed from the stack. To retrieve information from the data stack, use the PULL and PARSE PULL instructions.
PULL and PARSE PULL - remove one element from the top of the data stack.
PULL stackitem command contains the value of Elem2 (in the variable stackitem) with the characters translated to uppercase.
For example, after execution of PULL command 'stackitem' will hold a value of 'STRING 1 FOR THE DATA STACK'.
PARSE PULL stackitem command contains the value of elem1 (in the variable stackitem) with the characters not translated to uppercase
For example, after execution of PARSE PULL command, 'stackitem' will hold a value of 'String 1 for the data stack'.
The QUEUED built-in function returns the total number of elements on a data stack. For example, to find out how many elements are on the data stack, QUEUED function can be used with no arguments.
SAY QUEUED() command will return the number of elements in a stack (displays a decimal number).
/* REXX */ PUSH 'A' PUSH 'E' PUSH 'I' PUSH 'O' PUSH 'U' number = queued () Do number PULL element SAY element END EXIT 0 |
When an exec calls a routine (subroutine or function) and both the exec and the routine use the data stack, the stack becomes a way to share information. However, execs and routines that do not purposely share information from the data stack, might unintentionally do so and end in error.
To help prevent this, TSO/E provides the MAKEBUF command that creates a buffer, which can be used for an extension to the stack, and the DROPBUF command that deletes the buffer and all elements within it.
Although the buffer does not prevent the PULL instruction from accessing elements placed on the stack before the buffer was created, it is a way for an exec to create a temporary extension to the stack. The buffer allows an exec to:
Use the QUEUE instruction to insert elements in FIFO order on a stack that already contains elements.
Have temporary storage that it can be deleted easily with the DROPBUF command.
Ensure that the elements placed in the stack buffer are accessible only to the current exec.
An exec can create multiple buffers before dropping them. Every time MAKEBUF creates a new buffer, the REXX special variable RC is set with the number of the buffer created. Thus if an exec issues three MAKEBUF commands, RC is set to 3 after the third MAKEBUF command.
Note:
To protect elements on the stack, an exec can create a new stack with the NEWSTACK command.
To create a buffer on the data stack before adding more elements to the stack, use the TSO/E REXX MAKEBUF command. All elements added to the data stack after the MAKEBUF commands are placed in the buffer.
Below the buffer, stack contains the elements placed before issuing the MAKEBUF command.
/* REXX */ PUSH 'a' PUSH 'b' 'MAKEBUF' PUSH 'c' EXIT 0 |
In the above example, Element 'a' and 'b' will be placed directly in the stack and 'c' will be placed in the buffer. Thus element 'c'' will be accessible only to the current exec where as 'a' & 'b' are universally accessible.
The buffer created by MAKEBUF does not prevent an exec from accessing elements below it. After an exec removes the elements added after the MAKEBUF command, it starts removing the elements which are added before the MAKEBUF command was issued.
When an exec has no more need for a buffer on the data stack, it can use the TSO/E REXX DROPBUF command to remove the buffer (and its contents). The DROPBUF command removes the most recently created buffer.
To drop a specific buffer on the data stack and all buffers created after it, issue the DROPBUF command with the number of the buffer. The first MAKEBUF creates buffer 1, the second creates buffer 2, and so on. For example, if an exec issued three MAKEBUF commands that created three buffers, when you issue DROPBUF 2, the second and third buffers and all elements within them are removed.
To remove all elements from the entire data stack including elements placed on the data stack before buffers were added, issue DROPBUF 0. DROPBUF 0 creates an empty data stack and should be used with caution.
Note:
Use DROPBUF 0 selectively, as it will result in an empty data stackTo find out how many buffers were created with the MAKEBUF command, use the TSO/E REXX QBUF command. QBUF returns the number of buffers created in a special variable RC.
QBUF returns the total number of buffers created, not just the ones created by a single exec. Thus if an exec issued two MAKEBUF commands and called a routine that issued two more, when the routine issues a QBUF command, RC returns the total number of buffers created, which is four.
To find out how many elements are in the most recently created buffer, use the TSO/E REXX QELEM command. QELEM returns in the REXX special variable RC, the number of elements in the most recently created buffer.
QELEM does not return the number of elements on a data stack which doesn‘t contain any buffers created by the MAKEBUF command. If QBUF returns 0, no matter how many elements are on the stack and subsequently QELEM also returns 0.
/* REXX */ PUSH a; PUSH b; 'MAKEBUF' PUSH c; PUSH d; 'QBUF' SAY RC 'QELEM' SAY RC EXIT 0 |
In the above example, QBUF returns a value of 1 and QELEM returns a value of 2.
Unlike normal stack, a private stack is accessible only to the current exec.
The TSO/E REXX NEWSTACK command creates a private data stack that is completely isolated from the original data stack. The elements on the original data stack cannot be accessed by an exec or the routines that it calls until a DELSTACK command is issued. Before DELSTACK is issued, PULL statement retrieves the date from the terminal when there are no more elements in the new data stack.
All elements added to the data stack after the NEWSTACK command, are placed in the new private data stack. The original stack contains the elements placed on the stack before the NEWSTACK command.
When an exec wants to delete the new stack and remove all elements placed on the new stack, it can issue the TSO/E REXX DELSTACK command. The DELSTACK command removes the most recently created data stack. If no stack was previously created with the NEWSTACK command, DELSTACK removes all the elements from the original stack.
To find out how many stacks exist, use the TSO/E REXX QSTACK command. QSTACK returns in the REXX special variable RC, the total number of stacks including the original data stack.
QSTACK returns the total number of stacks, not just the ones created for a single exec. Thus if an exec issued two NEWSTACK commands and called a routine that issued two more, when the routine issues a QSTACK command, RC returns the total number of stacks, which is five.
/* REXX */ ADDRESS MVS "NEWSTACK" PUSH 'a' PUSH 'b' PUSH 'c' PUSH 'd' number = queued() Do number PULL number Say number End ADDRESS MVS "QSTACK" SAY RC ADDRESS MVS "DELSATCK" EXIT 0 |
In the above example RC returns the value of 2 (If no other stacks are running in other EXECs)
The data stack has some unique characteristics, such as
It can contain a virtually unlimited number of data items of virtually unlimited size.
It can contain commands to be issued after the exec ends.
It can pass information between REXX execs and other types of programs in a TSO/E or non-TSO/E address space.
Because of the data stack‘s unique characteristics, the data stack can be used specifically to:
Store a large number of Data items for a single exec‘s use.
Pass a large number of arguments or an unknown number of arguments between a routine (subroutine or function) and the main exec.
Pass responses to an interactive command that can run after the exec ends.
Store data items from an input data set, which were read by the EXECIO command.
Share information between an exec and any program running in MVS.
Execute subcommands of a TSO/E command issued from a REXX exec.
Get five inputs (names) from the user in the order of getting their entrance tickets for the dance show and display the person‘s name (as per the order) coming out from that show?
/* REXX */ DROP INREC. DO I = 1 TO 5 SAY 'ENTER THE NAME OF THE PERSON 'I':' PULL NAME INREC.I = NAME END DO I = 1 TO 5 QUEUE INREC.I END Say 'Order of persons coming out from the show ' NUMBER = QUEUED() DO NUMBER PULL NUMBER SAY NUMBER END EXIT 0 |
QUEUE command: the first element added to the queue is the first removed. Because elements are placed on the bottom of a queue and removed from the top, the oldest elements on a queue are the ones processed first.
QUEUED () contains the number of elements in a stack
PULL command will retrieve the data from the stack
Display the element in the PULL by the Command 'SAY'
Proper comments must be used for better understanding
Indentation must be appropriate for better readability
Stack is a memory area used as a means of data transfer.
The scope of public stacks is global. It can be accessed by all the applications running at that time.
Stacks can hold seamless amount of data which enables transfer of huge amount of data across modules.
There are three types of stacks namely public stacks, stack buffers and private stacks.
Scope of stack buffers and Private stacks is local to the modules where they are created.
Any number of stack buffers and private stacks can be created.
Stack buffers will be created on top of the public stacks. Once all the elements from stack buffers are retrieved, public stacks will be accessed.
Private stacks will be created as a fresh stack. When the private stacks are active Public stacks can be accessed only when the private stack is deleted.
QUEUE A QUEUE B 'MAKEBUF' QUEUE C PULL item |
PUSH 'a' PUSH 'b' 'MAKEBUF' PUSH 'c' PUSH 'd' 'DROPBUF' PARSE PULL element |
QUEUE A QUEUE B QUEUE C 'QELEM' SAY RC |
What is returned to the function SAY QUEUED ()?
Name two instructions that can potentially clear all elements in a stack.
If you have any doubts or queries related to this chapter, get them clarified from our Mainframe experts on ibmmainframer Community!