<<< Back Home >>>

STACK$ 2R1D -- Storage, Table, & Queue Manager

Go to Table of Contents

1. Introduction & Packet Formats

1.1. Description

STACK$ is a reentrant MASM subroutine of about 750 words. Its purpose is to aid in managing a program's use of main storage by handling requests for buffers; maintaining any number of stacks and their associated pointers; and providing insertion, deletion, search, and retrieval functions for these items.

In this discussion, a "stack" is either a table (a limited number of consecutive entries within fixed storage boundaries) or a queue (any number of non-contiguous entries linked by forward and backward pointers).

Stacks may be of the FIFO (first-in/ first-out) or LIFO (last-in/ first-out) variety, and may have fixed- or variable-length entries.

Variable-length stack entries must always have their word count in a pre-designated portion of the first word. This first word is not included in the word count. If desired, other data may be kept in the unused portion of the word, as with SDF image control words.

Queue entries are always preceded by a pointer word containing the address of the next entry in the queue in H2 (0 for last entry) and that of the previous entry in H1 (0 for first entry). This word is not included in the word count and is fully maintained by STACK$. The user will always refer to a queue entry address by its first data word, not its pointer word; and STACK$ will do the same when returning an entry address to the user.

Registers used: X11, A0-A3, R1. Where indicated, certain functions will also require A4, A5, R2, and/or R3.

STACK$ uses the routines BFACQ$ and BFRLS$ to request and release storage, allowing for addresses up to 262K and making the entire STACK$ package about 950 words. Refer to BFACQ$ documentation for further details on these elements.

*Note* In order for STACK$ to use the BDI capability of BFACQ$ 2R1B and above, the user must make an initial (bdi,buffer) call to BFACQ$ himself using the main STACK$ control packet as the BFACQ$ packet. This is necessary to "condition" the buffer for the bdi. This is a dummy acquire that will not be used again, so it can be for just 1 word.

1.2. Packets

STACK$ requires at least one main control packet for the maintenance of flags, values, addresses, and information about individual stacks. If the user's program is banked, all addresses managed by STACK$ must be based before calling it.

In all packet illustrations below, names in parentheses are values to be maintained by STACK$ and must initially be 0. A name without parentheses is a value that must be supplied by the user. Cells with a 0 are either unused or used internally by STACK$ as temporary work space.

Unless otherwise specified, numeric items such as limits and lengths are bound only by the size of the cells containing them.

1.2.1. Main STACK$ Control Packet

The one control packet required by STACK$ is the main control packet. In the drawing below it is shown above the dotted line, and has the following format:

|-----------------------------------------------------| -1 | [optional T$CELL word] | |-----------------------------------------------------| 0 | (TS) | spbits | bfpmin | BFPLTH/A2MOD | |-----------------------------------------------------| Main 1 | 0 | BFSTRT | Control |-----------------------------------------------------| Packet .2.|.....MAXSID......|...0....|..........tctbad..........|......... 0 | (TS) | LIFO | qflag | length (fixed) | | | | |040(var)| schoff | wcstfr | Stack |-----------------------------------------------------| Control 1 | Limit | (count) | Packet |-----------------------------------------------------| 2 | (Lstent) | (fstent) | |-----------------------------------------------------| 3 | [Optional T$CELL word] | |-----------------------------------------------------| ... Etc.

The cells of the main control packet are as follows, with words 0-1 being a BFACQ$ packet:

0,,S1 - TS     - Test-and-set cell used by BFACQ$/BFRLS$. May be set to 040, making word negative, to indicate that test-and-set queuing is to be used for all packets, stacks, and tables controlled by this main control packet. When this is done, extra T$CELL words must be set up before the main control packet and trace table as shown; and as an extra word in any predefined stacks in the MAXSID area or elsewhere. Note, however, that in the case of the main control packet and trace table (if used), the original packet address is still used for referencing; i.e., the word after the T$CELL word.

If test-and-set queuing is used, the caller is responsible for doing any necessary ER TSQRG$ calls.

0,,S2 - Spbits - Special bits. Bit 0: Requests for buffers or entries are to be rounded up to one less than the next power of 2.

0,,S3 - Bfpmin - If non-zero, the minimum number of 64-word blocks to be held in reserve by BFACQ$. When storage becomes exhausted, BFACQ$ will do an MCORE$ to acquire enough words to satisfy the current request and have bfpmin*64 words remaining. When storage is freed, BFRLS$ will release storage via LCORE$ if it has more than bfpmin*64 words remaining.

If bfpmin is 0, BFACQ$ will assume there is only a fixed amount of storage to work with, and will do no MCORE$'s or LCORE$'s.

0,,H2 - Bfplth - Length of main buffer pool; the number of words initially reserved to be managed by STACK$. The maximum bfplth is 131071. This cell is later used as work space by BFACQ$.

1,,H2 - BFSTRT - Initial address of storage pool to be managed by STACK$. BFSTRT must be at the high end of dbank if MCORE$ expansion is allowed.

2,,T1 - MAXSID - Maximum number of stack control packets that may follow the main control packet. There must be MAXSID*3 words reserved immediately following the main packet. The maximum MAXSID is 4095.

2,,H2 - Tctbad - If non-zero, the address of the trace table to be kept by STACK$ (see section on trace table).

1.2.2. Individual Stack Control Packet

The portion below the dotted line is an individual stack control packet. There may be up to MAXSID of these immediately following the main control packet; there may also be any number of isolated stack control packets elsewhere in storage, dynamically created by STACK$.

0,,S1 - TS     - Test-and-set cell for this individual stack. Not used if test-and-set queuing is being used.

0,,S2 - LIFO   - 0 if this stack is FIFO; 1 if it is LIFO.

0,,S3 - Qflag  - 0 if this stack is a table; 1 if it is a queue.

0,,XH2- length - (fixed-length stacks only) word length of each entry. Maximum = 131071.

For variable-length stacks, H2 of word 0 has the following format:

0,,S4 -        - 040. Causes length to test negative, indicating variable length.

0,,S5 - Schoff - Word offset for search functions -- up to 63.

0,,S6 - Wcstfr - The fraction of the first entry word in which the word count is stored. This is an assembler j-designator value, ranging from 0 thru 015. Remember that the mode-sensitive designators (T1-T3, Q1-Q4) will require that the program be in the correct mode (third- or quarter-word) when STACK$ is called.

The maximum entry lengths for the different word count fractions are: 63 for S1-S6; 511 for Q1-Q4; 2047 for T1-T3; and 131071 for H1, H2, and W. When wcstfr is W, a W will be used for storing; but H2 will be used for loading, adding, or subtracting.

1,,H1 - Limit  - For queues, the maximum number of entries. May be 0 if unlimited.
For tables: if fstent is supplied, limit is the highest address (upper bounds) of the table. If fstent is not supplied for the table, then limit denotes either the maximum number of entries (for fixed-length tables) or the total number of words in the table (for variable-length tables).

1,,H2 - Count  - The current number of entries in this stack.

2,,H1 - Lstent - Address of the last (most recent) entry in this stack. Must initially be 0 for queues.

2,,H2 - Fstent - Address of the first entry in this stack. Must initially be 0 for queues. For tables, may contain a preset address if the table area has already been reserved; the table will then be bounded by fstent and limit. If a table's fstent is initially 0, the table area will be allocated based on limit; limit will then be replaced by the table's upper bounds.

3     (T$CELL) - T$CELL word for this packet, if test-and-set queuing is being used. If S3 of this word is set to 1, this stack will be released with C$TSA rather than C$TS on a normal return, so that any activity which suspended itself with a C$TSQ on this cell will be reactivated.

1.2.3. Trace Table

By specifying an address for tctbad in the main control packet, the user can maintain a wrap-around trace table that will save significant values from each call to STACK$. The table consists of two control words followed by any number of 3-word entries, and is structured as follows:

|-----------------------------------------------------| -1 | [optional T$CELL word] | |-----------------------------------------------------| 0 | (TS) | 0 | 0 | (trclad) | control |-----------------------------------------------------| words 1 | (Trclim) | trclth | . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 | (User-data-addr) | (TRCX11) | |-----------------------------------------------------| entry 1 | (Stkpkt/SID) | (func) | |-----------------------------------------------------| 2 |(tcstat)| (TRCA2) | |-----------------------------------------------------| ... Etc.

Trace table control words:

0,,S1 - TS     - Test-and-set cell. Not used if S1 of control packet >= 040.

0,,H2 - Trclad - Last address used; address of most recent trace table entry.

1,,H1 - Trclim - Highest address+1 in trace table; used as limits test to determine when to wrap around.

1,,H2 - Trclth - Length of the trace table entry area -- should be a multiple of 3. There must be trclth words reserved immediately following the control words.

Trace table entry:

0,,H1 - User-data-addr - Original A0 increment. Address to or from which data was transferred by STACK$.

0,,H2 - TRCX11 - X11 modifier. User's return address.

1,,H1 - Stkpkt/SID - Original A1 increment, containing either a stack packet address or a stack id.

1,,H2 - Func   - Original A1 modifier. The STACK$ function bits for this call.

2,,S1 - tcstat - If kept, the STACK$ completion status.

2     - TRCA2  - Original A2 contents (variable).

2. Calling STACK$

2.1. Masm Call

The call to STACK$ can be as simple as:

        LA,U      A1,FUNCTION-BITS
        LMJ       X11,STACK$

Or as complex as:

        LA        A1,(STKPKT | SID,FUNCTION-BITS)
        LA        A4,(SCHWD1) | (LIFO*/6+QFLAG,LENGTH)
        LA        A5,(SCHWD2) | (LIMIT,FSTENT)
        LR        R2,(SCHMSK1)
        LR        R3,(SCHMSK2)
        LMJ       X11,STACK$
                [ (Search no-find return) ]

(Bars denote a choice among mutually exclusive items.)

The complexity of the call depends entirely on the functions being performed, which are specified by the function-bits parameter in the lower half of A1. These function bits are the heart of STACK$; and as they are discussed in the next section, the meanings of the other possible parameters will be brought out.

The parameter in the lower half of A0 is the address of the main control packet, which is the only other required parameter.

2.2. The STACK$ Function Bits

The settings of bits 0 thru 15 of A1 determine STACK$'s course of action each time it is called. The interrelationship of these bits may be complicated to follow, but a procedure that generates calls to STACK$ will be introduced later to alleviate this.

The STACK$ function bits, then, are defined as follows, with each one having a three-letter mnemonic associated with it for easier reference and procedure calls:

Bit  0 - ('WRT') - Read/write bit. If 0, denotes a "read" function; if 1, a "write" function.

During most calls to STACK$, the address of a certain entry of a particular stack will be determined, based on other function bits (sequence number, search, etc.). Which stack to use is determined by the parameter in the upper half of A1: either a stack control packet address (stkpkt), or a stack id (see 'SID' bit).

For a read function, if a user data address is supplied in the upper half of A0 (data-addr), the entry will be transferred from the stack to that address.

For a write function, space will be acquired for a new entry (if a queue), and, if data-addr is coded, the entry will be transferred from the user's address to the new stack entry area. Pointers and counters in the stack's control packet, as well as in preceding and following queue entries, will be updated to indicate that the new entry follows the one found at the beginning of the function. (If there were no entries in the stack to start with, the new entry will be written as the first.) If a new table entry is inserted between other entries, all higher entries will be shifted down.

If no data address is supplied for a write function on a variable-length stack, the request will be ignored, since STACK$ must obtain the entry's word count from the first word of the entry.

There are two ways to force the allocation of a new variable length entry without the transfer of data: 1) If the entry length is 511 or less, load the length as the "data address." 2) For any entry length, store the length negative in any storage word, in the appropriate fraction; then load the address of that word as the data address. The negative length will be a signal not to transfer any data. This second method requires that the word count fraction be H1, H2, W (the whole word), or T1-T3 (in third-word mode). In both cases, STACK$ will allocate the entry and store the entry length into the appropriate part of the first word.

Bit  1 - ('INB') - 'insert before' bit. If set during a write function, will adjust pointers (or shift entries, for a table), to cause the new entry to precede, rather than follow, the one found at the beginning of the function.

If set during a read function for a variable-length stack, will have the special effect of transferring the entry to the user's data address (if any) starting with the second word (i.e., minus the word count word).

Bit  2 - ('DRW') - Delete/rewrite bit. If set during a read function, will delete (pop) the entry from the stack after transferring it, if called for, to the user's address. Pointers and counters will be updated, or tables shifted, where required.

For a write function, this bit denotes that an existing entry is to be overwritten. If the stack is variable-length, the word count of the existing entry will first be stored into the designated portion of the new entry's first word to ensure the same number of words is transferred.

Bit  3 - ('MSK') - Search mask bit. Indicates that a mask is being used on a search function (see 'SCH' bit).

Bit  4 - ('2WD') - Two-word search bit. Indicates that a search function is being performed on two consecutive entry words rather than one (see 'SCH' bit).

Bit  5 - ('SCH') - Search function bit. Starting with the entry determined at the beginning of the function, consecutive entries will be searched until the first word of the entry is equal to the contents of register A4 (SCHWD1). If no find is made, or if there are no entries in the stack, the search no-find return will be taken. Whenever the 'SCH' bit is set, there must be an additional return word between the error and normal returns.

If the '2WD' bit is set, the second word of the entry must also match the contents of A5 (SCHWD2).

If the 'MSK' bit is set, the first entry word and A4 will each be 'ANDed' with the contents of R2 (SCHMSK1) before being compared. A4 will be destroyed. If the '2WD' bit is also set, the second entry word and A5 will each be 'ANDed' with the contents of R3 (SCHMSK2) before being compared. A5 will be destroyed. R2 and R3 will not be changed.

If the stack is variable-length, the search offset in the stack's control packet will be added to each entry's starting address to derive the correct word(s) to compare with A4(A5). (With an offset of 0, the word count word would always be the first word searched.)

When a search function is performed, the upper half of A2 must contain a search count (schcnt). Usually this will be 0 or 1, meaning return after the first search find is made. If greater than 1, say n, this denotes a multiple search count, meaning find the nth entry that matches. If fewer than n entries match, the no-find return will be taken.

If the search count is negative, the search will go in reverse through the stack entries. Furthermore, if neither an entry address nor sequence number was supplied, the search will begin at the last entry. Bear in mind, however, that if the stack is LIFO, it already has an implied reverse built in: a positive search count would start from the last entry, and a negative one from the first.

If the search results in a find, any other operation requested by function bits will then be performed normally: the entry found by the search may be read, written, or deleted; or a new entry may be inserted before or after it.

Bit  6 - ('SQN') - Sequence number bit. Indicates that the user is specifying an entry sequence number in the lower half of A2, to be used in determining the desired starting entry. A search, if requested, would start from this entry. Sequence numbers start at 1.

If the sequence number is negative, the count will start from the last entry and go in reverse. If the stack is LIFO, it will be complemented: LIFO and FIFO stack entries are inserted in the same order, but read in opposing order.

If the sequence number is 0 or the 'SQN' bit is not set, and a specific entry address is not supplied, then -1 will be assumed for a FIFO write, or a 'SCH' with a negative count; 1 will be assumed for all other cases.

Bit  7 - ('ENT') - Entry address bit. The user is supplying the starting entry address desired (entadr) in the lower half of A2, rather than a sequence number. This eliminates the need for STACK$ to search through the stack for the proper entry. The caller is responsible for passing the correct address of an entry belonging to the stack being acted upon.

A special case exists when the 'ENT', 'SQN', and 'SCH' bits are all set: using the entry address supplied in the lower half of A2, and a relative sequence number n in the upper half of A2 (relsqn), STACK$ will find the nth entry after (n>0) or before (n<0) the given entry. If there are fewer than n entries left to search from the starting entry, the no-find return will be taken. LIFO complementing applies.

Bit  8 - ('SID') - Stack id bit. The user is supplying a stack id in the upper half of A1, rather than the address of a stack control packet. The stack packet, therefore, must be in the area reserved immediately after the main control packet (see MAXSID parameter). Its address is 3*SID+3 plus the address of the main packet (4*SID+3 if TS queuing used). The valid range of a SID is 0 thru MAXSID-1.

If the SID is negative and the dynamic bit is set, a new stack control packet may be created in the MAXSID area, provided there is an empty slot.

The advantage of SIDS and the MAXSID area is that any number of stack control packets may be predefined and ready for use at execution time.

Bit  9 - ('ACQ') - Acquire/release bit. Interfaces with BFACQ$ & BFRLS$ through STACK$. (Although the user could call these routines directly, this interface may be desirable because it will be logged in the trace table, if one is being kept.)

If the 'WRT' bit is set, the user is requesting a buffer whose length is in the lower half of A2 (buflth). Its address will be returned in the lower half of A3.

If the 'WRT' bit is not set, the user is releasing a buffer -- previously acquired via the 'ACQ' bit -- whose address (rlsadr) is in the lower half of A2.

Bit 10 - ('DYN') - Dynamic stack creation/deletion bit.

If set during a write call and the upper half of A1 contains either a 0 stack control packet address or a negative SID, STACK$ will dynamically create a new stack control packet: either in the MAXSID area if the 'SID' bit is set, or anywhere in the buffer pool, by acquiring a three word buffer. STACK$ expects registers A4 and A5 to be loaded with the stack packet parameters as shown in the ASM call illustration and in the stack control packet diagram.

If set during a read function and the last remaining stack entry is read, and the 'DRW' bit is set to delete that entry -- or if the stack's entry count was zero to begin with -- the stack control packet will be released. Any further reference to that stack will not be valid; and if the packet was in the MAXSID area, that slot will become available for creating other stack packets. Note that when the 'DYN' bit is used this way, the stack packet must either have been previously acquired by STACK$ or be in the MAXSID area.

Bit 11 -         - Presently undefined. Reserved for future use.

Bit 12 - ('PTC') - Partial trace bit. Will release trace table early, before doing a search or sequence number find. Errors occurring after this point will not be recorded in the trace table, since the return status will not be stored; but the trace table will be freed up sooner to avoid excessive TS lockout time.

Bit 13 - ('NTC') - No-trace bit. This call to STACK$ is not to be logged in the trace table at all.

Bit 14 - ('NCL') - No-clear bit. See next bit for explanation.

Bit 15 - ('NTS') - No-test-and-set bit.

Each time STACK$ is called in reference to a particular stack, that stack's control packet is locked out via TS for the duration of the call, and released prior to returning. (All STACK$ error returns release the packet as well.) To retain control of the stack after returning from STACK$, set the 'NCL' bit, so that the packet's TS cell will not be cleared. To retain control during subsequent calls, set both the 'NTS' and 'NCL' bits, so STACK$ will not try to perform a TS on the locked packet. On the final call, after which the stack will be released, set only the 'NTS' bit, thus allowing STACK$ to clear the TS cell.

The 'PTC', 'NTC', 'NCL', and 'NTS' bits are intended mainly for multiple activities calling STACK$.

Bits 16 and 17 are used internally by STACK$ and must always be 0.

2.3. Return From STACK$

2.3.1. Normal Return

After a normal return from STACK$, registers are loaded as follows:

A0 - 0.

A2 - The current entry count of the stack.

A3M (lower half) - The address of the stack entry that was acted upon (whether read, written, searched, etc.). If the entry was deleted, however, this value will be zero.

A3I (upper half) - Stack control packet address (also present after a search no-find return). If the stack was dynamically deleted, however, A3 will be all zeros.

2.3.2. Error Return & Error Codes

After an abnormal return, A0 contains one of the following octal status codes:

1 - Storage overflow [BFACQ$]

2 - Zero length requested [BFACQ$]

3 - Corrupted link encountered (address in upper half of A1. Tentative user buffer address in lower half.) [BFACQ$]

4 - Release address out of bounds [BFRLS$]

5 - Corrupted link encountered (same as BFACQ$ error 3) [BFRLS$]

6 - Bad SID (out of range, or negative without dynamic bit)

7 - MAXSID overflow -- no more room for stack packets in the MAXSID area

010 - Nonexistent stack (not initialized [length=0] or stack packet address 0 but dynamic bit not set)

011 - Nonexistent entry or sequence number out of range

012 - No-find on a search function. The search no-find return will be taken.

013 - Entry overflow -- new entry would have exceeded limits specified in stack control packet.

014 - Zero main control packet address

061 - TCS error releasing control packet

062 - TCS error releasing trace table

063 - TCS error releasing individual stack control packet

07X - TCS error from BFACQ$/BFRLS$ (actual status would have been x)

2.4. Proc Calls

2.4.1. S$TACK: Generate Call To STACK$

The MASM procedure S$TACK can facilitate generating calls to STACK$. The format of the call is:

S$TACK[,n] 'KEYWD1'[,param] 'KEYWD2'[,param] ...

The optional n may be 0 or 1. A 1 will set the 'WRT' bit. N may be negative to set the 'INB' bit for either a read (-0) or a write (-1). N may also be preceded by an asterisk to set the 'DRW' bit (*0, *-0, *1, *-1).

The fields in the proc call are designed not only to supply STACK$ parameters, but also, wherever possible, to set the function bits implied by their presence. In this way, the user should rarely have to code specific function bits other than the 'n' parameter after the proc name or the four special-purpose bits ('PTC', 'NTC', 'NCL', 'NTS').

Each field begins with a keyword in quotes and is optionally followed by a parameter. Below is a list of the possible keywords, the items they represent, and the function bits they set, if any. If a keyword is not followed by a parameter, a load of that parameter will not be generated, but any function bits governed by the keyword will still be set.

Unless otherwise noted, the parameter following each keyword is an operand field in the standard *u,*x,j format, where j is assumed to be 017 if not coded. Some parameters cause additional action if their keywords are flagged with an asterisk (*'KEYWD'); others are accompanied by additional information where needed.

'CTLPKT' - Main control packet address. This parameter can be omitted if the tag 'STACK$PACKET' is attached to the user's packet, either as a label or thru an EQU directive.

'DATA'   - User data address (including a length under 01000 octal, as described earlier under the 'WRT' bit).

'STKPKT' - Stack control packet address. If less than 0200, denotes a control register containing the stack packet address in its upper half, as might have been returned in A3 and saved from a previous call. The register used must not be any of those used by STACK$ (X11, A0-A3[-A5], R1[-R3]). If flagged, will set 'DYN' bit.

'SID'    - Stack id. Sets 'SID' bit. If flagged, will load operand negative.

'SQN'    - Sequence number. Sets 'SQN' bit. If flagged, will load operand negative.

'ENTADR' - Stack entry address. Sets 'ENT' bit.

'RELSQN' - Relative sequence number. Sets 'SQN', 'SCH', & 'ENT' bits. If flagged, will load operand negative.

'BUFLTH' - Requested buffer length to be loaded into the lower half of A2. Sets 'ACQ' & 'WRT' bits. If flagged, will load negative so buffer will be zeroed by BFACQ$.

'RLSADR' - Buffer release address to load into A2. Sets 'ACQ' bit.

'SCHWD'  - Address of single-word search item. Sets 'SCH' bit. If flagged, will set 'MSK' bit. Will generate load of A4 with the operand. The j-field is assumed to be 0 if not coded.

'SCHWDS' - Address of double-word search items. Sets 'SCH' and '2WD' bits. If flagged, will set 'MSK' bit. Will generate a double load of A4 with the operand.

'SCHMSK' - Address of search mask word(s). Sets 'SCH' & 'MSK' bits. If flagged, or if the 'SCHWDS' keyword is used, will set '2WD' bit and generate a load of R3 with the operand address+1 in addition to the load of R2. The j-field is assumed to be 0 if not coded.

'SCHCNT' - Multiple search count. Sets 'SCH' bit. If flagged, will load the operand negative.

'STKINF' - Address of two-word stack information packet as described under the 'DYN' bit, which this keyword sets. Generates a double load of A4 with the operand.

'FBITS' or 'FBIT' - Additional function bits. Instead of an operand, the user may list any additional functions bits desired for this call after the keyword. Example: 'FBITS','DYN','NTC',...

'FUNC'   - Function-bits parameter. The user may supply the entire lower half of A1 here, and it will replace any function bits that might have been generated by other parameters.

'ERR'    - Error return. If coded with a parameter, will generate a jump to that address on an error return. If coded without a parameter, will generate a normal return. If not coded, will generate 'ER ERR$'. If flagged, will generate 'J STACK$ERROR', assuming the user has attached that tag to the desired error return address. If a parameter is included, the j-field is assumed to be 0 if not coded.

'SCHNOF' - Search no-find return. Same as 'ERR', except if flagged, will generate 'J STACK$SCHNOF'. Sets 'SCH' bit.

'STRA3'  - Address for storing A3 following a normal return. This field is provided for the convenience of the user. If coded, will generate a store of A3 into the operand, thus saving the stack packet and stack entry addresses returned by STACK$. The j-field is assumed to be 0 if not coded.

'STRA2'  - Same as 'STRA3' for A2. If flagged, will generate a double store, saving both A2 and A3.

2.4.2. STACK$FCONST: Setting Constant Function Bits

The user may wish to have certain function bits always set on all calls to STACK$ or on a certain group of calls. This can be accomplished with the procedure STACK$FCONST:


If n is not coded, the tag STACK$FCONST(1) will be equated to a constant with all the function bits listed in the call set to 1. The procedure S$TACK will then 'or' its own function word with this value each time it is called until the tag is cleared or redefined.

If n = 1, the function bits listed in the keyin will be added to those already set; if n = -1, the bits listed will be cleared.

2.4.3. STACK$SIDSET: Defining & Optionally Listing SIDS

If several stack packets are being defined in the MAXSID area following the main stack control packet, the procedure STACK$SIDSET provides a way of defining the SID values associated with each packet. These values may also be listed to aid in interpreting trace table data.

The procedure requires that each packet have the same label attached to it, with different subscripts. The subscripts may be names describing the purpose of each packet, but they must be no longer than 12 characters, be the same length, and occur in alphabetical order. Example:

STACK$PACKET     +     8,512
                 +     0,buffer
                 +     3*/6,0
STK('FILES')     +     1,5
                 +     0,0
                 +     0,0
STK('NAME')      +     1,8
                 +   100,0
                 +     0,0
STK('TABLE')     +     1,20
                 +     0,0
                 +     0,0

Proc call: STACK$SIDSET[,1] ['LABEL']

The above proc call will result in the definition of SID('FILES') as 0, SID('NAME') as 1, and SID('TABLE') as 2. The optional 1 following the proc call will cause these SID values to be listed in octal. The label name in the operand field is needed only if the common subscripted label for the MAXSID stack packets is other than 'STK'.

3. Examples Of STACK$ Calls
   S$TACK,1  'SID',3  'DATA',newcrd

Insert the data at NEWCRD as the the next entry in the stack with id 3.

   S$TACK,*0  'CTLPKT',stkctl  'STKPKT',0,X5  'SQN',-3

Delete the third last entry in the stack whose control packet address is in X5 (no user address, so no data transfer).

DWF       FORM  18,18,18,18
   S$TACK,1  *'SID'  'STKINF',(DWF  1,5,2000,0)  'DATA',INIT

Dynamically create a new stack packet in the MAXSID area. The stack will be a queue with a maximum of 2000 5-word records. After the stack is created, its first entry will be transferred from INIT.

             'SCHWDS',('NEWRECORDXXX') 'SCHMSK',(-0777777D) ;
              'DATA',TSTBUF  'SCHCNT',4   'SCHNOF',TRYAGAIN .

1. Include the partial trace bit in all future calls.

2. Beginning with an entry address saved from a previous call to STACK$, find the 4th entry having the word 'NEWRECORD' as its first 9 characters. If it is found, transfer it to TSTBUF (apparently a variable length entry, since the word count word is being excluded). If it is not found, jump to the label TRYAGAIN.

   S$TACK,0  'STKINF',params  'SCHNOF' .

Create an empty stack packet in storage for later use. The 'SCHNOF' keyword is used both to set the 'SCH' bit and to avoid erroring when the no-find return is taken.

4. Changes Since Earlier Levels

4.1. Changes in STACK$ 2R1D (since 2R1C)

Enhancement and corrections to creating variable length stack entries without the transfer of data (see 'WRT' bit). When a variable length packet has a word count fraction of W (whole word), the W will be used when storing, but only H2 will be used when loading, adding, or subtracting. Corrections to S$TACK proc when generating error and search no-find returns.

Fixed bug so that a negative search count would always start at sequence number -1 if no entry address or sequence number supplied. This is what was always intended, and the documentation on the 'SCH' and 'SQN' bits has been revised to clarify that.

Table of Contents

(Go to Top)

1. Introduction & Packet Formats
1.1. Description
1.2. Packets
1.2.1. Main STACK$ Control Packet
1.2.2. Individual Stack Control Packet
1.2.3. Trace Table
2. Calling STACK$
2.1. Masm Call
2.2. The STACK$ Function Bits
2.3. Return From STACK$
2.3.1. Normal Return
2.3.2. Error Return & Error Codes
2.4. Proc Calls
2.4.1. S$TACK: Generate Call To STACK$
2.4.2. STACK$FCONST: Setting Constant Function Bits
2.4.3. STACK$SIDSET: Defining & Optionally Listing SIDS
3. Examples Of STACK$ Calls
4. Changes Since Earlier Levels
4.1. Changes in STACK$ 2R1D (since 2R1C)