7.2.4 The zeroth buffer
Normally, data pushed on the stack is added to the top of the
stack.  When a stack contains only one buffer, the strings in that
buffer are the strings stored above that buffer-mark. The strings
below it are not part of the first buffer; instead, they are said
to belong to the zeroth buffer.

Thus, all strings from the bottom of the stack, up till the first
buffer mark (or the top of the stack if no buffers exist) is said
to be the strings in the zeroth buffer. However, note that the
zeroth buffer is only defined implicitly. Thus, it can not really
be removed by calling DROP; only the strings in the zeroth buffer
are removed. Afterwards, the zeroth buffer will still contain all
strings at the bottom of the stack, up till the first buffer mark
(if existing).

Example: Process all strings in the stack

This is a common REXX idiom, where a loop iterates over all the
strings currently in the stack, but otherwise leave the stack
untouched. Supposing the routine PROCESS() exists, and do to
processing with its parameter and return the processed string:

     do i=1 to 5                /* just to fill the stack      */
          push ‘line #’ i
     end
     
     do queued()                /* foreach line in the stack   */
          parse pull line         /* fetch the line
     */
          queue process(line)     /* put back the processed line
     */
     end

Here, it is important to use QUEUE to put the strings back into
the stack, not PUSH, else the loop will iterate the correct number
of times, but only operate on the same data string. It is also
important that the stack does not contain any buffers. Since QUEUE
will insert into the bottom of the topmost buffer, the loop would
iterate the correct number of times, but only on a part of the
stack. Thus, the topmost part of the strings in the stack would be
processed multiple times.

Example: How to empty the stack

The following short example shows how you can most easily empty
the stack:

     do i=1 to 5               /* Just to fill the stack */
          push ‘line #’ i
     end
     
     do queued()               /* For each line in the stack */
          pull                   /* Remove the line from the stack
     */
     end

This is trivially simple, but there are several interesting and
subtle notes to make about this example. First, if the number of
strings in the stack is likely to change, due to some external
process, then the DO clause should perhaps better be written as:

     do i=1 to 5               /* Just to file the stack */
          push ‘line #’ i
     end
     
     do while queued()>0       /* While the stack is not empty */
          pull                   /* Remove a line from the stack
     */
     end

This will in general mean more work for the interpreter, as it is
now required to check the number of strings in the stack for each
iteration, while for the previous code fragment, the number of
strings is only checked once. Another point is that this might not
remove all buffers from the stack. Suppose the zeroth buffer is
empty, i.e. there exists an buffer which was put on the stack when
the stack was empty.  This buffer is removed in any of the
following situations: calling DESBUF, calling DROPBUF (sometimes),
or reading a string below the buffer mark. Since there are no
strings below the buffer mark, pulling a string from the stack
would make the interpreter read from the keyboard, and hang the
interpreter.

Thus, the only “safe” way to remove the string and buffers from
the stack, without side effects, is to call DESBUF or DROPBUF.  On
the other hand, if you only want to make sure that there are no
strings in the buffer, the method described here is more suitable,
since it is far more compatible (although possibly not so
efficient).  But anyway, buffers are not a compatible construct,
so it does not matter so much.



PREV NEXT