A second limitation is that there is no pointer variable in FORTRAN 77, so there is no standard way to link one array to another. Of course an array index is often used in such cases. It is this principle that memory managers such as ZEBRA are based on. ZEBRA declares a single huge array, with a declaration similar to the following:-
A simplified scheme of the way ZEBRA works is shown below:-
The first step to improve readability it to follow a standard convention of most ZEBRA codes in the naming of links. All links should be of the form:-
Lbbbb, where bbbb is the bank nameSo, for bank MCVX, the link name would be LMCVX. If more than one MCVX link is required, further names are formed by adding a postfix e.g. an end vertex might be called LMCVXE or LMCVX_END.
The second step is to use the SNO convention for offsets, using parameters of the form:-
Kbbbb_fff, where fff is the offset nameFor example, KMCVX_PSX is the X position of the MCVX bank. A complete set of offset mnemonics for each bank can be found in the file:-
...snoman/n_nn/code/bank_bbbb.inc, e.g. bank_mcvx.incand is also shown in the corresponding Event Data Structure diagram. For example, see MCVX.
Using both these conventions, access to a bank data word now looks like this:-
"The PSX field of an MCVX is the dynamic store Q"
Warning: Unlike languages with true structures, there is nothing to prevent you from misforming either the link or the offset and consequently accessing the wrong word of the dynamic store. Reading from the wrong address can give unpredictable errors, and writing to it will damage the data structure. Using the offset parameters can eliminate one source of error, but you should take great care that your links are correct, particularly if you are generating memory requests. This is discussed further in Event Relocation and Local Links.
Warning:The ZEBRA documentation uses the numbering convention which is shifted up by one on the standard convention. So the user bits are 1 to 18 and the system bits are 19 to 32.
There are a number of points to notice about this diagram:-
Kbbbb_cccc, link from bbbb to ccccfor example:-
The value 0 is used to denote a null link.
There are 2 types of links:-
A bank can neither, either, or both, but if both, the structural links are always below the reference links. If a bank has NL links, of which NS are structural, then the layout is:-There are 2 sorts of structural links:-
A vertical structural link implies dependenceSo, in this case, the MCTK depends on its MCVX which is said to support it. If the MCVX is dropped then the MCTK it supports must also be dropped and ZEBRA does this automatically. In terms of the representation: if a vertex is dropped then the tracks that are produced by it must also be dropped.
To step down from a MCVX to its MCTK:-
Every bank has a HORIZONTAL link to the "Next" bank in the chainThis link is stored in LQ(L):-
A horizontal structural link implies independence; normally there is no significance to the order in which banks are placed in the chainIn our representation, every outgoing track depends on the vertex from which it comes, but each track is logically independent of all others. When ZEBRA drops a bank the user is offered a choice, to just drop the one bank or to follow the horizontal link and drop the rest of the linear chain.
Typical code to process all the tracks at a vertex looks like this:-
ZEBRA provides a number of utilities to process linear chains of banks. For example NZBANK counts the number of banks in a chain, given a link to the start of the chain. LFZFIND searches a chain for a bank having a specified value in a specified word. A summary of the most commonly used utilities can be found in ZEBRA Routines
Reference links imply no logical dependence; links may be made or broken at any time without changing the underlying data structure.A bank can have any number of reference links and can be pointed to by any number of reference links. The reference links need not even point to a bank's Status Word. It could, for example, point to a particular data word in the bank that has special significance for the bank holding the link. At the time of writing this guide, all of our reference links point to bank status words. Any departure from this practice will be clearly documented.
An example of a reference link is the link between an MCTK and the MCVX it ends on. The link offset for this is KMCTK_MCVX. The following code can be used to step from one vertex to the next, following its first outgoing track:-
Warning:Reference links to a bank may continue to point to it after it has been dropped.
When a bank is dropped, it is not immediately removed from the data structure but has a system status bit set to mark it as dead. As part of the dropping process, its only supporting structural link is either set to zero or bridged across to the next bank in the chain. However, trying to reset reference links to it is very time consuming; there may be any number and they may be located in any bank. This should not be a problem; the application code should know what reference links exist and should clear them when it drops the bank. In any case, if Garbage Collection takes place then all links have to be updated and any pointing into a dead bank will be set to zero.
If HBOOK is being used then ZEBRA is managing a third store defined by the /PAWC/ common block. However, beyond defining the size of this store, using the routine DEFINE_MEMORY_SIZE, no reference to this is store is made by SNOMAN.
Associated with each store is a STORE INDEX used to identify the store to ZEBRA. For the first store defined (the Q store), this index is zero, for all other stores the number is non-zero. For the CONS store the store index is MTSTOR, defined in mt.inc.
Divsions allow global operations on entire data structures. Consider, for example, the erasure of a data structure. This could be done, bank by bank, using MZDROP. But such an operation would be very time consuming. There is a much faster way of doing this using MZWIPE, which clears one of more divisions essentially by resetting the pointer to the first free word in the division. Traditionally, division 1 is used as a short term store and division 2 for more permanent data. So an analysis program could use division 1 to sequentially read in event data structures, wiping the division between events, and use division 2 to accumulate data derived from the events. SNOMAN uses division 1 of the Q store for event data structures and division 2 for Run Headers and other permanent data. Division 2 of the CONS store hold titles banks.
Each division is assigned a DIVISION INDEX, based on the store index as follows:-
division index = store index + division numberThe division index for the event data structure is IDIV_EVENT which is defined in z.inc. The titles banks division is MTDIV, which is defined in mt.inc.
In this way as much store a possible is recovered for new banks. If insufficient banks have been dropped, then even this procedure will eventually fail and ZEBRA will not be able to complete a memory request. In this case a STORE FULL trap is generated which results in control being transferred to the high level routine QNEXT (the routine that calls EVMAIN). This means that:-
MZLIFT never returns a failure due to lack of memory.This makes writing code that lifts banks easier as the store full condition, which could in principle happen at any time, does not have to be catered for. Instead all such errors are handled by the high level code which is the most appropriate place to deal with such problems. If it is required to write code that does not want to loose control because a store full has occurred, the routine MZNEED can be used. It returns the space that is currently available and this can be used to decide whether to call MZLIFT.
If you look in z.inc, you will see that an array of structural links and an array of reference links are declared:-
A potentially very serious bug can occur if a user takes a copy of a link into a local variable and continues to use it after event relocation may have taken place. Consider this apparently innocent, if rather odd piece, of code:-
Fortunately, avoiding the problem is not difficult so long as the following steps are carried out:-
A related problem can occur when passing bank data to subroutines and functions. Consider:-
A complete discussion of this subject is beyond the scope of this guide, only an outline will be given here. For more detail see MZFORM in the ZEBRA Reference Manual. To define a bank format the user has to pass a format string the MZFORM. The syntax of this string is given in the table below:-
Warning: Word counts give the number of 4 byte words notthe number of objects. This means that 24D means 24 words i.e. 12 double precision words.
The format string is passed to MZFORM which converts it into an I/O characteristic, which will eventually be stored in the bank. However, MZFORM stores this characteristic in a system table, and only returns a single word index to it. The user also passes the bank name to MZFORM e.g :-
bnkdef.inc
The next step is to call MZLIFT to create the bank and connect it into the data structure e.g.:-
It is possible to alter the size of an existing bank, either increasing or decreasing the number of links or data words, using MZPUSH. For example, to add 2 links and remove 3 data words from an MCVX bank:-
To wipe a complete divisions :-
Access Contents Description and Example Use +----------------------+ LQ(L-NL-NIO-1) | IOcb | NL+NIO+12 | I/O control/Offset to bank centre +----------------------| LQ(L-NL-NIO) | I/O opt. 1 | ... | ... | Extra I/O descriptor words (0 to 16) LQ(L-NL-1) | I/O opt. NIO | +----------------------+ LQ(L-NL) | Link NL | ... | ... | Reference links LQ(L-NS-1) | Link NS+1 | lmcvx_e = lq(lmctk1+KMCTK_MCVX) +----------------------+ LQ(L-NS) | Link NS | ... | ... | Structural (down) links LQ(L-1) | Link 1 | lmctk1 = lq(lmcvx+KMCVX_MCTK) +----------------------+ | | LQ(L)---------->| Next-link | Link to next bank in linear chain | | lmctk2 = lq(lmctk1) +----------------------+ | | LQ(L+1) | Up-link | Link to supporting bank | | lmcvx = lq(lmctk2+1) +----------------------+ | | LQ(L+2) | Origin-link | Address of supporting link | | lmctk1 = lq(lmctk2+2) +----------------------+ | | IQ(L-5) | IDN | Numeric bank identifier | | ibank_no = iq(lbank-5) +----------------------+ | | IQ(L-4) | IDH | Hollerith bank identifier (4 chars) | | print * , 'Bank name:' , chaint( iq(lbank4) ) +----------------------+ | | IQ(L-3) | NL | Total number of links | | num_links = iq(lbank-3) +----------------------+ | | IQ(L-2) | NS | Number of structural links | | num_str_links = iq(lbank-2) +----------------------+ | | IQ(L-1) | ND | Number of data words | | num_data = iq(lbank-1) +----------------------+ | | IQ(L)---------->| Status | Status bits: 0-17 user, 18-31 system | | if ( btest( iq(lmcvx) , KMCVX_SRC) ) ) then +----------------------+ IQ(L+1) | Data word 1 | ... | ... | Data words IQ(L+ND) | ... | energy = rq(lmctk+KMCTK_ENE) | Data word ND | id_part = iq(lmctk+KMCTK_IDP) +----------------------+Where:-
These routines perform service functions for linear structures. The parameter LLS is the address of the first bank of the linear structure.
+----------------------------+ | !LF = LZLAST(IXSTOR,!LLS) | +----------------------------+
searches the linear structure pointed to by LLS for its end. It returns in LF the address of the last bank in the structure. LF = 0 is returned if the structure is empty.
+----------------------------------+ | !LF = LZFIND(IXSTOR,!LLS,IT,JW) | +----------------------------------+
searches the linear structure pointed to by LLS for the first bank containing IT in word JW; it returns its address in LF. If none: LF=0.
+--------------------------------------+ | !LF = LZLONG(IXSTOR,!LLS,NW,ITV,JW) | +--------------------------------------+
has the same function as LZFIND, but ITV is a vector of NW words expected in words JW to JW+N-1 of the bank.
+----------------------------------------+ |!LF = LZBYT(IXSTOR,!LLS,IT,JBIT,NBITS) | +----------------------------------------+
has the same function as LZFIND, but it looks for a bank having IT in byte (JBIT,NBITS) of the status word.
+--------------------------------------+ |!LF = LZFVAL(IXSTOR,!LLS,VAL,TOL,JW) | +--------------------------------------+
has the same function as but it looks for a bank having in word JW a floating point number which is equal to VAL within the tolerance TOL.
+--------------------------+ | N = NZBANK(IXSTOR,!LLS) | +--------------------------+
counts the number of banks in the linear structure pointed to by LLS.
+--------------------------------+ | N = NZFIND(IXSTOR,!LLS,IT,JW) | +--------------------------------+
searches like LZFIND, but for all banks. It returns the number of such banks in N and stores the addresses of the first 100 such banks into IQUEST, starting at IQUEST(1).
+------------------------------------+ | N = NZLONG (IXSTOR,!LLS,NW,ITV,JW) | +------------------------------------+
searches like LZLONG, but for all banks. It returns the number of such banks in N and stores the addresses of the first 100 such banks into IQUEST, starting at IQUEST(1).
This routine will try to find the first bank of the linear structure of which the bank at LGO is a member. It does this by following the path indicated by the "origin" link of the bank at LGO, and using its "up" link.
+----------------------------+ | !LF = LZHEAD(IXSTOR,!LGO) | +----------------------------+
It returns the address of the first bank of the linear structure as the function value; or zero if there is trouble.
If the linear structure is not a top-level structure, ie. if the up-link LUP is non-zero, the path of origin-links should end in the link region of the bank at LUP, at a word whose off-set JBIAS can then be calculated. This is returned:
IQUEST(1) negative: = JBIAS
ie. LQ(LUP+JBIAS) contains the address of the first bank of the linear structure.
If LUP is zero, the origin-path should end at a word outside the bank space of the store IXSTOR, which word should contain the address of the first bank of the linear structure. In this case LZHEAD returns:
IQUEST(1) = 1: top-level structure IQUEST(2) = LS, relative adr of the supporting link-area link, ie. LQ(LS) contains LFIf LUP is zero, and if the origin-link in the last bank in the path is zero, this is a stand-alone structure, in which case LZHEAD returns:
IQUEST(1) = 2: stand-alone structure
If there is trouble, LZHEAD will return the function value zero, and set:
IQUEST(3) = 1 if LGO is zero 2 if LUP non-zero and the last origin-link points outside bank-space 3 if LUP non-zero and LQ(LUP+JBIAS) does not point to the last bank in the origin-path 4 if LUP zero, and LQ(LS) does not point to the last bank in the origin-path.
Unlike in HYDRA, and because of the reverse pointers, the operation of moving a bank by re-linking from one data-structure to another one is a non-trivial operation. The routine ZSHUNT is provided to execute such an operation.
ZSHUNT may be used to extract either a single bank (IFLAG=0) or a whole linear structure (IFLAG=1) from the old context, for insertion into the new context as described by the parameters LSUP and JB, which have the same significance as in MZLIFT.
+------------------------------------------+ |CALL ZSHUNT (IXSTOR,!LSH, !LSUP,JB,IFLAG) | +------------------------------------------+with
IXSTOR index of the store, zero for the primary store; IXDIV, the index of the division containing the bank to be shunted, may be given instead !LSH address of the bank or of the linear structure !LSUP if JB < 1: address of the new supporting bank if JB = 1: the new supporting link* JB if JB < 1: link bias in the new supporting bank if JB = 1: LSUP is the new supporting link, the origin-link in the bank at LSH will be made to point to it if JB = 2: detach without insertion IFLAG if IFLAG = 0: shunt the one single bank at LSH if IFLAG = 1: shunt the whole linear structure pointed to by LSH
If the bank or the structure to be re-linked is in fact inserted or added into an existing linear structure, both must be contained in the same division.
Examples:
Suppose we have the following data-structures to start with:
______ | | up | UA | <---.-------------.-------------. |______| | | | | | | | -3 | | | | | ______ ______ ______ | | | <-- | | <-- | | `----> | A1 | ---> | A2 | ---> | A3 | |______| |______| |______| and ______ | | up | UN | <---.-------------.-------------. |______| | | | | | | | -7 | | | | | ______ ______ ______ | | | <-- | | <-- | | `----> | N1 | ---> | N2 | ---> | N3 | |______| |______| |______| and ______ ______ ______ <--- | | <-- | | <-- | | LQMAIN ---> | X1 | ---> | X2 | ---> | X3 | |______| |______| |______|
Any bank may support further dependent partial data-structures, the corresponding structural down-links are not changed by ZSHUNT.
In what follows the notation Lxx is used to designate a link pointing to bank xx.
Examples:
CALL ZSHUNT (0,LA2,LUN,-7,0) gives: ______ | | | UA | <---.-------------. |______| | | | | | -3 | | | | ______ ______ | | | <-- | | `----> | A1 | ---> | A3 | |______| |______| and ______ | | | UN | <---.-------------.-------------.-------------. |______| | | | | | | | | | -7 | | | | | | ______ ______ ______ ______ | | | <-- | | <-- | | <-- | | `----> | A2 | ---> | N1 | ---> | N2 | ---> | N3 | |______| |______| |______| |______|
This moves a single bank (with is dependents, if any) out of a linear structure, and inserts it at the head of the linear structure supported by link -7 of the bank UN.
CALL ZSHUNT (0,LA2,LUN,-7,1) gives: ______ | | | UA | |______| | -3 | | ______ | | | `----> | A1 | |______| and ______ | | | UN | <--.-------------.-------------.------------------. |______| | | | | | | | | | -7 | | | | | | ______ ______ ______ ______ | | | <-- | | <-- | | <- ... - | | `----> | A2 | ---> | A3 | ---> | N1 | -- ... -> | N3 | |______| |______| |______| |______|
This is the same as example 1, except that the (partial) linear structure starting with bank A2 is re-linked.
CALL ZSHUNT (0,LA2,LN2,0,0) gives: ______ | | | UN | <---.-------------.-------------.-------------. |______| | | | | | | | | | -7 | | | | | | ______ ______ ______ ______ | | | <-- | | <-- | | <-- | | `----> | N1 | ---> | N2 | ---> | A2 | ---> | N3 | |______| |______| |______| |______|
This is again like example 1, but the bank is inserted inside the linear structure, rather than ahead of it.
CALL ZSHUNT (0,LA2,LQMAIN,1,0) gives: 0 0 0 0 ^ ^ ^ ^ | | | | ______ ______ ______ ______ <---- | | <-- | | <-- | | <-- | | LQMAIN -----> | A2 | ---> | X1 | ---> | X2 | ---> | X3 | |______| |______| |______| |______|
This relinks bank A2 to be the first in the top-level linear structure supported by LQMAIN.
L = LQMAIN CALL ZSHUNT (0,LA2,L,1,0)
has exactly the same effect as Example 4 above because, LQMAIN not being zero initially, the origin-link of the bank pointed to by L (and the up-link, but this is zero) is used for the connection.
CALL ZSHUNT (0,LA1,LHEAD,1,1) gives: ______ | | | UA | |______| | -3 | | ----> zero and 0 0 0 ^ ^ ^ | | | ______ ______ ______ <---- | | <-- | | <-- | | LHEAD -----> | A1 | ---> | A2 | ---> | A3 | |______| |______| |______|
supposing LHEAD=0 initially; this connects the linear structure to the (structural) link LHEAD, ie. the origin-link of the header bank A1 points back to the location of LHEAD.
CALL ZSHUNT (0,LA1,LDUMMY,2,1) gives: ______ | | | UA | |______| | -3 | | `----> zero and 0 0 0 ^ ^ ^ | | | ______ ______ ______ 0 <-- | | <-- | | <-- | | LA1 -----> | A1 | ---> | A2 | ---> | A3 | |______| |______| |______|
This detaches the linear structure from its old context without inserting it into a new one. This should only be temporary, one should insert the floating structure into a new context by a second call to ZSHUNT not too much later.
These routines perform service operations on linear structures. The parameter LLS is the address of the first bank of the linear structure.
+----------------------------+ |CALL ZTOPSY (IXSTOR,*!LLS*) | +----------------------------+
reverses the order of the banks in the linear structure, ie. the first bank becomes the last, and the last the first, for walking through the structure with L=LQ(L). Starting with Zebra version 3.67, LLS is updated to point to the first bank of the inverted structure on return.
+--------------------------+ |CALL ZPRESS (IXSTOR,!LLS) | +--------------------------+
removes by bridging dead banks still present in the linear structure pointed to by LLS.
Key-words may be either floating, integer or Hollerith. For Hollerith sorting a collating sequence inherent in the representation is used, thus the results will depend on the machine.
Sorting may be done either for a single key-word in every bank or for a key vector in every bank:
+--------------------------------+ |CALL ZSORT (IXSTOR,*!LLS*,JKEY) | +--------------------------------+
Sorts banks according to a single floating-point keyword
+----------------------------------+ | CALL ZSORTI (IXSTOR,*!LLS*,JKEY) | +----------------------------------+
Sorts banks according to a single integer keyword
+----------------------------------+ | CALL ZSORTH (IXSTOR,*!LLS*,JKEY) | +----------------------------------+
Sorts banks according to a single Hollerith keyword
+--------------------------------------+ |CALL ZSORV (IXSTOR,*!LLS*,JKEY,NKEYS) | +--------------------------------------+
Sorts banks according to a floating-point key vector
+----------------------------------------+ | CALL ZSORVI (IXSTOR,*!LLS*,JKEY,NKEYS) | +----------------------------------------+
Sorts banks according to an integer key vector
+----------------------------------------+ | CALL ZSORVH (IXSTOR,*!LLS*,JKEY,NKEYS) | +----------------------------------------+
Sorts banks according to a Hollerith key vector
with the parameters IXSTOR index of the store or of any division in this store, zero for the primary store; *!LLS* the address of the first bank of the linear structure, reset on return to point to the new first bank; JKEY in each bank at L, Q(L+JKEY) is the key word, or the first word of the key vector; NKEYS the number of words in the key vector.
The execution time taken by these routines is a function of the re-ordering which needs to be done. For perfect order the operation is a simple verification pass through the structure. The maximum time is taken if the banks are initially arranged with decreasing key words.
Sorting re-links the banks such that the key-words are in increasing order. If one needs them in decreasing order on may use CALL ZTOPSY (IXSTOR,LLS) which reverses the order of the banks in the linear structure pointed to be LLS.
We distinguish two kinds of link areas:
A permanent link area is initialized once at the steering level and stays alive for the whole program; it consists of just the vector of links.
A temporary link area is requested and de-activated by lower-level code any number of times. Each such area has two words pre-fixed to the link-vector for efficiency:
A link area must be in COMMON storage; if it is in local storage there is a danger that Fortran optimization causes a register to preserve the old value of a link across a relocation operation, for garbage collection, but also for simple updating with MZDROP, ZSHUNT, etc.
As for links in banks, a structural link may only contain zero or the valid address of a bank; it must never contain garbage.
To initialize a permanent link area, one calls once, and once only for this area:
+------------------------------------------------+ |CALL MZLINK (IXSTOR,chNAME,!LAREA,!LREF,!LREFL) | +------------------------------------------------+
with
IXSTOR index of the store into which the links will point, (IXDIV of any division in this store allowed) zero for the primary store chNAME name of the Fortran Common in which the link area resides, for printing purposes, 8 characters maximum !LAREA first word of the link area, being also the first link of this area !LREF first reference link, if any; last structural link, if no reference links !LREFL last reference link, if any, if none: give LAREA in this parameter positionMZLINK will clear the links to zero. Examples:
mixed link area: COMMON /LAMIX/ LS1,...,LSN, LR1,...,LRN CALL MZLINK (0,'/LAMIX/',LS1,LR1,LRN) structural link area: COMMON /LASTR/ LS1, ..., LSN CALL MZLINK (0,'/LASTR/',LS1,LSN,LS1) reference link area: COMMON /LAREF/ LR1, ..., LRN CALL MZLINK (0,'/LAREF/',LR1,LR1,LRN)
Note that in a permanent link area with exactly one link this link cannot be a reference link.
MZLINK prints at log level zero (or above) an initialization message on unit IQLOG.
To activate a temporary link area, one calls with:
+------------------------------------------------+ | CALL MZLINT (IXSTOR,chNAME,LAREA,!LREF,!LREFL) | +------------------------------------------------+
with
IXSTOR index of the store, as for MZLINK chNAME name of the link area, as for MZLINK LAREA first word of the link area, with: LAREA(1) the user flag word LAREA(2) system word LAREA(3) the first link of the area !LREF first reference link, if any, as for MZLINK !LREFL last reference link, if any, as for MZLINKMZLINT will clear the links to zero, set the flag-word LAREA(1) to be non-zero, and set the system-word LAREA(2) on first contact. To de-activate a temporary link-area the user sets LAREA(1)=0. From then on the links in this area are no longer relocated, and hence will be meaningless. To re-activate the area the user could set LAREA(1)=1, but he must then clear the contents of the links himself; it is safer to call MZLINT, which will do the necessary. Examples:
mixed link area: COMMON /LAMIX/ LAMIX(2), LS1,...,LSN, LR1,...,LRN CALL MZLINT (0,'/LAMIX/',LAMIX,LR1,LRN) structural link area: COMMON /LASTR/ LASTR(2), LS1, ..., LSN CALL MZLINT (0,'/LASTR/',LASTR,LSN,LASTR) reference link area: COMMON /LAREF/ LAREF(2), LR1, ..., LRN CALL MZLINT (0,'/LAREF/',LAREF,LR1,LRN)MZLINT prints a log message at level 1 for initialization and at level 2 for re-initialization.
+----------------------------------------------------------+ |CALL MZBOOK (IXDIV,!L*,!LSUP,JB, chID,NL,NS,ND,IOD,NZERO) | +----------------------------------------------------------+
or
+----------------------------------------------+ |CALL MZLIFT (IXDIV,!L*,!LSUP,JB, NAME, NZERO) | +----------------------------------------------+
with
IXDIV index of the division in which the bank is to be lifted = 0 use default in primary store [= IXSTOR use default in secondary store ] see below for details !L* returns the address of the bank created !LSUP if JB < 0: address of the supporting up bank if JB = 0: address of the supporting previous bank if JB = 1: supporting link* if JB = 2: LSUP not used JB if JB < 1: link bias in the supporting bank (must be a structural link) if JB = 1: create top-level bank if JB = 2: create stand-alone bank NAME specifies the properties of the bank: NAME(1) = ID: 4-character bank identifier, alphanumeric, MZBOOK: variable of type CHARACTER MZLIFT: Hollerith string of the form 4Hxxxx (2) = NL: total number of links, NL < 64k (3) = NS: number of structural links, NS <= NL (not counting the 3 links next, up, origin) (4) = ND: number of data words, ND < 1 Mwords (5) = IOD: I/O descriptor for the data words, which may be: - result from MZFORM, 1 word, I/O index - result from MZIOBK, 1 or more words, I/O characteristic - immediate, the whole bank is of the same type: IOD = 0 undefined, bank cannot be transported 1 32-bit unsigned integer 2 signed integer 3 floating 4 double-precision 5 Hollerith 7 self-descriptive - requests: IOD = 9 retrieve I/O characteristic by IDH, stored in the system by MZFORM 11 take the I/O characteristic from any bank in the target linear structure, if this is empty act as for 9
NZERO controls whether and how much of the data-part of the bank is preset to zero: N = -1: no presetting N = 0: the whole bank is cleared N > 0: the first N words are cleared The links of the bank are always cleared to zero.
In what follows we will need the parameter LNEXT, which is the address of the successor bank to the bank to be lifted; its address will be stored into link 0 of the new bank, ie. into its 'next' link. LNEXT is obtained as follows:
if JB < 1: LNEXT = LQ(LSUP+JB) JB = 1: LNEXT = LSUP JB = 2: LNEXT = 0
The division [ and the store ] into which the bank is to be lifted is selected by the parameter IXDIV. If a definite division is specified, this is used, but it must be compatible with LNEXT; a linear structure must be contained within one and the same division ! If 'default division' is specified, by giving zero [ or IXSTOR ] for IXDIV, the bank will be created in the division holding the logically nearest bank of the data structure into which the new bank will be inserted, in this order of priority:
The numeric bank identifier IDN serves to readily identify a particular bank within a linear structure for interactive work. Normally the Hollerith identifiers IDH in a linear structure are all identical; it is desirable that the IDN's are all different. In principle the user can set any positive integer into IQ(L-5) after the bank has been created, but MZLIFT/ MZBOOK will store a default value in this order of priority:
- if LNEXT is non-zero: use IDN+1 of the bank at LNEXT; - if JB = 0: use IDN+1 of the bank at LSUP; - if JB < 0: use the value IDN = -JB; - IDN = 1 will be set.
The bank being lifted is inserted into an existing data-structure according to LSUP under control of the parameter JB:
--- case 1: JB < 0 insert as dependent of the bank at LSUP ex.: CALL MZLIFT (0,L,LSUP,-4,NAME,0) _______ | | __| SUP | <-------------------------.------ ... | | | <---------. | link | |_______| | | JB= -4 | | | | | | | up | up | | ________ ________ | | | | | `---------------> | lift | ---> | NEXT | ---> ... |________| |________| SUP is the supporting bank whose address is LSUP lift is the new bank being lifted NEXT is the first bank of the linear structure in front of which the bank 'lift' is inserted, ie. the initial content of link JB in bank SUP was LNEXT = LQ(LSUP+JB). The up-link and the origin-link in the bank lifted are set as up-link <-- LSUP origin-link <-- LSUP+JB --- case 2: JB = 0 insert inside a linear structure ex.: CALL MZLIFT (0,L,LSUP,0,NAME,0) ______ | | __| UP | <------------------------------------------.---- ... | | | <------------. | | |______| | | | |<-------------. | | | | | | up | up | up | | ____ ________ ________ ________ | | | | | | | | | `---> | | -...-> | SUP | --> | lift | --> | NEXT | --> ... |____| |________| |________| |________| The up-link and the origin-link in the bank lifted are set as up-link <-- copy of the up-link in bank SUP origin-link <-- LSUP
SUP, lift, NEXT have the same significance as in case 1. UP is the bank pointed to by the up-link in bank SUP, which link might be zero. If bank NEXT does not exist, ie. if LNEXT = LQ(LSUP) is zero, the bank 'lift' is added at the end of the linear structure.
--- case 3: JB = +1 create new top-level bank ex.: CALL MZLIFT (0,L,LSUP,1,NAME,0) usually: zero <------------------. | | -------------->| | | up | up | ________ ________ | | | | result LSUP and L ----> | lift | ---> | NEXT | ---> ... |________| .--> |________| | input LSUP -----------------------^
For JB=+1 the origin-link and the up-link are taken from the bank NEXT pointed to by LSUP on input; the first time round, when NEXT does not exist, ie. when LSUP=0, the up-link is set to zero and the origin-link is made to point to the location containing LSUP.
The location pointed to by the origin-link is filled with the address of the bank created, unless the origin-link is zero.
--- case 4: JB = +2 no inserting at all ex.: CALL MZLIFT (0,L,0,2,NAME,0)
For JB=2 the bank is lifted without being linked into a structure; both the origin-link and the up-link in the bank are set to zero.
MZLIFT and MZBOOK print a monitor log message at level 2.
+--------------------------------------------+ | CALL MZPUSH (IXDIV,*!L*,INCNL,INCND,chOPT) | +--------------------------------------------+
with
IXDIV index of the division; zero [or IXSTOR] allowed, in which case MZPUSH will find the division *!L* address of the bank to be pushed, on return L contains the new address of the bank (cannot be a link in a bank !) INCNL number of additional links, zero for no change, negative for decrease. Additional links will be given type 'reference', unless the original bank has only structural links. INCND number of additional data words, zero for no change, negative for decrease. chOPT character string of options: default: any link may point to the bank at L, R but not into the abandoned bank region (in case of bank reduction) I isolated: only the inherent structural links point to this bank
For 'isolated' the user is sure that no link other than the supporting structural link, and the link passed in the parameter L, and the reverse links in the first level dependents, point to this bank.
The I/O descriptor of the old bank must also be valid for the new bank; if this would not be the case one should use MZREPL instead of MZPUSH.
New link words and new data words acquired by the bank are cleared to zero.
Except for special cases, increasing the size of a bank is an expensive operation, and should be avoided. The correct solutions to the problems of indefinite number of objects or of indefinite size are either the use of a linear structure or the lifting of a bank of maximum size, which is reduced to the final size once the contents are complete.
The increase of a bank is handled in general as follows: a new bank is lifted with the new dimensions, the contents of the original bank are copied over, and the old bank is marked as dropped. Any link pointing to the original bank must be re-routed to the replacement bank by MZPUSH. In full generality this can only be done by a relocation pass over all memory (ie. all link areas and all divisions pointing to the division in which the bank resides.)
The expensive part in this operation is the relocation pass, and this can be saved under special circumstances:
a) Increasing the data part of the last bank in a forward division, or the link part in a reverse division, can be done in situ without the lifting of a new bank. Hence any link pointing to the bank remains valid. (However note: this is not a good reason for creating an extra division, because the lifting of a maximum size bank is a better solution.)
b) If there are no links pointing to the bank (except the standard structural support links) there is no point to scan all links, because the relocation pass would have no effect. However, ZEBRA could not detect this situation without actually performing the relocation pass, but the user may know the situation a priori, in which case he can signal it to MZPUSH with the 'I' option.
Reducing the size of a bank is less onerous (if the 'R' option is given). The parameters of the original bank are adjusted to the new dimension in situ and the abandoned memory is marked as dead. Links which point into the abandoned region, if any, can only be reference links and must be reset to zero. To have links pointing into a bank, rather than to the status-word, is relatively rare. Again, the relocation pass can be saved, and for reducing a bank this is the normal situation, if the user knows the situation a priori and signals it to MZPUSH with the 'R' option (or 'I' which is stronger).
MZPUSH prints a monitor log message at level 2, but if the operation involves a relocation pass a log message will be given at level 1.
MZPUSH accumulates statistics of the number of times that an expensive operation was performed; this is printed by MZEND.
+--------------------------------+ |CALL MZDROP (IXSTOR, !L, chOPT) | +--------------------------------+
with
IXSTOR index of the store or of any division in this store, zero for the primary store !L the address of the bank or linear structure to be dropped chOPT character string of options: default: drop the bank at L only, ie. the 'next' link of this bank is not followed L drop the linear structure pointed to by L ie. the 'next' link of the bank at L is followed V drop only the partial data-structure dependent vertically downwards from the bank at L, but not the bank itself.MZDROP prints a monitor log message at level 2. The parameter L in the call to MZDROP is not as such changed on return, but if it is the structural link supporting the d/s it will in fact be up-dated for the removal of the first bank in this structure. Suppose this artifical sequence of operations (with LS=0 initially):
CALL MZLIFT (0,L,LS,1,...) create bank '3' CALL MZLIFT (0,L,LS,1,...) create bank '2' LS now points to bank 2 CALL MZLIFT (0,L,LS,1,...) create bank '1' LS now points to bank 1 CALL MZDROP (0,LS,'.') drop bank 1 LS now points again to bank 2 if however the dropping is done with CALL MZDROP (0,L,'.') drop bank 1 then LS will be made to point to bank 2, but L will continue to point to the (dead) bank 1.
Since the parameter L in the call to MZDROP is not changed, selective dropping of banks in a linear structure can be done with a loop like this:
L = start adr of the linear structure 12 IF (L.NE.0) THEN IF (bank not wanted) CALL MZDROP (0,L,'.') L = LQ(L) GO TO 12 ENDIF
+----------------------+ | CALL MZWIPE (IXWIPE) | +----------------------+
with the parameter IXWIPE indicating the divisions of a particular store to be wiped out. IXWIPE may be any of the three possible forms of a division index:
a) specific division index, as returned by MZDIV b) generic division index, [ IXSTOR + ] n, where n = 21: all user short range divisions 22: all user long range divisions 23: all package divisions c) compound division index, as created by MZIXCO, see there for details.
IXWIPE = 0 is taken to mean IXWIPE = 21, ie. all short range divisions in the primary store; similarily IXSTOR+21 can be used.
Wiping divisions resets the divisions to be empty, but without reducing the space reserved for them, followed by a relocation pass to reset to zero all links pointing into the wiped divisions. Included into this pass are the links of all link areas, of the working space and of all divisions which are declared to point to the divisions in question (all of this for one particular store only, of course).
If several divisions are to be wiped out, this must be done by one call to MZWIPE, and not by several calls in succession, to save the time of multiple relocation passes, each of which would take longer than the single pass.
Examples:
for the primary store one has:
1) Wipe the last 'event': CALL MZWIPE (0) 2) Wipe division 1: CALL MZWIPE (1) 3) Wipe all user's divisions: IX = MZIXCO (21,22,0,0) CALL MZWIPE (IX) 4) Wipe divisions IX1, IX2, IX3, IX4, and IX5: IX = MZIXCO (IX1,IX2,IX3,IX4) IX = MZIXCO (IX,IX5,0,0) CALL MZWIPE (IX)MZWIPE operates by calling MZGARB, which will print a monitor log message at level 2.
+----------------------------+ |CALL MZGARB (IXGARB,IXWIPE) | +----------------------------+
with
IXGARB index of the divisions where garbage is to be collected (none if =0) IXWIPE index of the divisions to be wiped out = 0: no divisions to be wiped
Both IXGARB or IXWIPE may be any of the three possible forms of a division index:
a) specific division index, as returned by MZDIV b) generic division index, [ IXSTOR + ] n, where n = 21: all user short range divisions 22: all user long range divisions 23: all package divisions c) compound division index, as created by MZIXCO, see there for details.MZGARB prints a monitor log message at level 2, but if the operation involves a garbage collection a message is given at level 1.
MZFORM may cause garbage collection.
The nature of the contents of any bank which is to be transported from one computer to another one has to be indicated to ZEBRA, such that it can do the necessary tranformations. In the simplest case that all the data words of a bank are of the same type, this is easily indicated in the parameters to MZLIFT or MZBOOK. For anything more complicated the user specifies the "format" of the bank by calling MZIOBK or MZFORM which encode the format into a variable number of words to be included into each bank in the system part as the "I/O characteristic".
Thus the content description is carried by each bank; this avoids complicated logistics of finding bank descriptors elsewhere than in the bank itself. Complex bank contents require a relatively large number of extra system words. This could represent a substantial overhead on memory or file space occupation, which the user can avoid in the design of his bank contents. Anyway, the number of these extra descriptor words is limited to 16, and any descriptor which would need more is refused. Thus ZEBRA will not handle any arbitrary bank contents via this basic procedure, but by using the concept of the "self-describing" sector (see below) the user can indeed store any kind of information mix, decided at execution time, into a bank and have it travel from one computer to another one.
The basic element for setting up an I/O characteristic is the sector, which is a number of words consecutive in the bank which are all of the same type. A sector is described in the format parameter to MZFORM et al. as a combination of its word-count "c" and its type "t" as "ct". For example, 24F is a sector of 24 single-precision floating-point numbers, 24D is a sector of 24 words holding 12 double-precision numbers, and 1I is a sector of one integer word.
The possible values for "t" are:
t = B bit string of 32 bits, right justified I integer F floating-point D double precision H 4-character Hollerith S self-describing sector (see below)
A ``static'' sector is a sector of a fixed number of words, such as the 24F of the example above.
An ``indefinite-length'' sector is a sector whose end is defined by the end of the bank. This is written as -t, for example -F signals that the rest of the bank is all floating-point words.
A ``dynamic'' sector is a sector which is preceded in the bank by a single positive integer word indicating the sector length; if this number is zero this means that the rest of the bank is currently unused. This is written as *t, for example *F indicates a dynamic sector of type floating.
Thus the word-count "c" in the sector specification is written as:
c = n numeric, n words: static length sector - all remaining words: indefinite length sector * dynamic length sector
A ``self-describing'' sector is a dynamic sector whose type is also encoded into the one word preceding the sector as
word 0 = 16*NW + IT with NW = length of the sector IT = numeric representation of the type = 1 B bit string 2 I integer 3 F floating 4 D double precision 5 H Hollerith 6 (reserve) 7 (special)
The form "nS" is meaningless; the form "*S" indicates one particular sector; the form "-S" is special in that it indicates that the rest of the bank is filled by self-describing sectors, as many as there may be. (Thus the forms, for example, '4I 5F / *S' and '4I 5F --S' are equivalent, but the second form is more economic; the user may give either, the internal result will be the second form.)
Looking now at the bank as a whole, we divide it into a "leading part" and a "trailing part", either of which may be empty.
The leading part consists of one region of maybe several sectors, occurring once at the beginning of the bank. This leading region may end with an indefinite-length sector, in which case the trailing part is empty.
The trailing part of the bank may be empty or it may consist of an indefinite number of regions which all have the same structure, such that the same format description is valid for all of them.
The symbol "/" marks the break between the leading region and the trailing regions in the format parameter to MZFORM et al.
Examples:
trailing part empty: '-F' the whole bank is floating '3I -F' the first 3 words are integer, the rest is F '*I -F' the first word n=IQ(L+1) is a positive integer, words 2 to n+1 are integers, the rest is F '3B *I -F' the first sector consists of 3 words bit-string, the second sector is dynamic of type integer, the rest of the bank is floating '3I *F' the first 3 words are integer, followed by a dynamic sector of type F, the rest (if any) of the bank is currently unused
both parts present '3B 7I / 2I 4F 16D' the leading region has 3 B and 7 I words, each trailing region consists of 2 integer words, followed by 4 F words, followed by 16 D words, ie. 8 double-precision numbers '4I / *H' the bank starts with 4 integer words, the rest is filled with dynamic Hollerith sectors '*I / 2I *F' the leading region is one dynamic I sector, each trailing region consists of 2 integers followed by a dynamic F sector (ie. 3 integers plus a number of floating words this number being indicated by the 3rd integer) leading part empty '/ *H' the bank is filled with dynamic Hollerith sectors '/ 4I 29F' 4 integers and 29 floating numbers alternate
It is in the interest of the user to design his bank contents such that the I/O characteristic is as simple as possible, because the number of system words in any bank increases with the complexity of the lay-out. "Simple" means: as few sectors to be described as possible.
For example: '2B 2I 2B 2I 2B 2I -F' is much less simple then '6B 6I -F'.
Moreover, if the integers described by this format are sure to be positive integers, then one can use the even simpler form '12B -F'.
In the following we give an exhaustive list of the most economic bank formats, those requiring zero or one extra system word in the banks.
These bank formats can be described by the 16 bits of the I/O control-byte alone:
(0) '-t' or '*t' 'ct -t' if c < 64 (c=* is represented as c=0, or 'ct *t' hence '*t -t' is a sub-case) (1) '*t *t -t' (2) '*t *t *t' (3) 'ct / *t' if c < 64 '/ ct *t' if c < 64 '/ ct' this is useful only if c=* else the form '-t' is used (4) '*t / *t *t' '*t *t / *t' (5) '/ *t *t *t'
These bank formats can be described by the 16 bits of the I/O control-byte plus the 32 bits of one extra I/O word:
(1) 'ct -t' 'ct ct -t' if c < 65536 'ct ct ct -t' if c < 1024 (2) 'ct *t' 'ct ct *t' if c < 65536 'ct ct ct *t' if c < 1024 (4) 'ct / ct' if c < 65536 'ct / ct ct' if c < 1024 'ct / ct ct ct' if c < 256 'ct ct / ct' if c < 1024 'ct ct / ct ct' if c < 256 (5) '/ ct ct' if c < 65536 '/ ct ct ct' if c < 1024 (remember: '/ ct ct ct ct' if c < 256 c=0 means c=*)
Three routines are provided to mediate between the user specifying the bank format in a readable form and the highly encoded I/O characteristic to be included into any bank at creation time.
analyses the format chFORM to convert and pack it into the output vector IOWDS. This is the basic routine, but it is usually called by the user only to specify formats of objects other than banks, like the user header vector for FZOUT.
To specify bank formats the following two routines serve more conveniently:
is provided for the context of MZLIFT; like MZIOCH it analyses the format chFORM, but it stores the result as part of the bank-description vector NAME for MZLIFT.
again analyses the format chFORM, but it does not return the result to the user. Instead, it remembers the I/O characteristic in a system data-structure, returning to the user only the index to the characteristic in the system. The user may then either pass this index to MZBOOK (or MZLIFT) at bank creation time, or alternatively he may request MZBOOK (or MZLIFT) to search the system data-structure for the I/O characteristic associated to the Hollerith identifier IDH of the bank to be created.
The first word of the I/O characteristic delivered by MZIOCH or MZIOBK has the following redundant format:
| 16 | 5 | 5 | 6 bits| |----------------------------------------------| | control-byte | NWXIO | NWXIO+1 | 1 | |----------------|---------|-----------|-------|
The I/O index delivered by MZFORM has the following format:
| 16 | 5 | 5 | 6 bits| |----------------------------------------------| | index | 0 | NWXIO+1 | 2 | |----------------|---------|-----------|-------|
where NWXIO is the number of extra I/O words, ie. the total length of the characteristic is NWXIO+1.
The format should be typed giving the "ct" for each sector, in the order in which they occur in the bank, as shown in the examples. Leading, interspersed, and trailing blanks (also comma or dot) for aeration are allowed and ignored.
Single-word sectors must be typed as '1t', 't' alone is illegal.
The c for double-precision sectors gives the number of words, thus 14D specifies 7 double-precision numbers; 7D is illegal.
+----------------------------------+ | CALL MZIOCH (IOWDS*,NWIO,chFORM) | +----------------------------------+
with
IOWDS* the I/O words to receive the result, a vector dimensioned to NWIO NWIO the maximum size of IOWDS, < 17 chFORM the format as a CHARACTER string
+--------------------------------+ |CALL MZIOBK (NAME*,NWMM,chFORM) | +--------------------------------+
with
NAME* the bank description vector for MZLIFT, the resulting characteristic will be stored into the I/O words starting at NAME(5), the IDH contained in NAME(1) will be used if diagnostics are necessary, a vector dimensioned to NWMM NWMM the maximum size of NAME, < 21 chFORM the format as a CHARACTER string
+----------------------------------+ | CAL MZFORM (chIDH,chFORM,IXIO*) | +----------------------------------+
with
chIDH the Hollerith IDH of the bank, type CHARACTER chFORM the format as a CHARACTER string IXIO* returns the index to the characteristic stored in a system data-structure, this can be passed to MZBOOK/MZLIFT, in which case it must not be modified
Examples:
DIMENSION IOHEAD(4), MMLIFT(8) CALL MZIOCH (IOHEAD,4, '8I -F') for an FZIN user header CALL MZIOBK (MMLIFT,8, '2I / 2I 8F') for MZLIFT CALL MZFORM ('RCBC', '2I/2I 8F'), IORCBC) for reference by index
People creating data outside Zebra, but destined to be read by FZ of Zebra, will have to know the representation of the I/O characteristic stored into any bank:
The physically first word of any bank contains:
right half: NOFF = NIO + NL + 12 (bits 1-16) where NIO: the number of extra I/O descriptor words for the bank NL: the number of links in the bank left half: the I/O control byte, which controls the (bits 17-32) interpretation of the I/O characteristic
In the simplest cases the I/O control byte alone specifies the nature of the data in the bank, without needing extra descriptor words (in which case NIO is zero). We give here the translation of some of these cases:
-B: 0001 *B: 0009 -I: 0002 *I: 000A -F: 0003 *F: 000B -D: 0004 *D: 000C -S: 0007
For example: suppose one were to prepare a bank with two links and 4000 data words which are all un-signed 32-bit integer (type B), a bank which is to travel in link-less mode such that all standard links are zero:
word 1 0001 000E -B | NOFF = 14 2 zero link 2 3 zero 1 4 zero link next 5 zero up 6 zero origin 7 IDN numeric ID 8 IDH Hollerith ID 9 2 number of links 10 1, say number of structural links 11 4000 number of data words 12 zero status word bits 19-22 give NIO, here zero 13 data word 1 ... 4012 data word 4000
Note that the status word contains NIO on bits 19--22 to allow Zebra to reach the start-of-bank.
It is impraticable to tabulate the translation of more complicated formats. There is a little program DIOCHAR to interactively take a format chFORM, translate it and display the result in hexadecimal. This is not yet properly installed on the CERN machines, but on the Apollo people at CERN can run it by giving the command /user/zoll/uty/diochar
The subroutine MZIOTC is provided to convert an encoded IO characteristic back into printable form. One may hand to this routine the address of a bank and receive its IO characteristic in a CHARACTER variable. Alternatively one may pass to it an integer array as delivered by MZIOCH for back-conversion to CHARACTER, for example the IO characteristic of a user-header vector read with FZIN.
+----------------------------------------+ |CALL MZIOTC (IXST, !L, NCHTR*, chIOTR*) | +----------------------------------------+
or
+----------------------------------------+ |CALL MZIOTC (IOWDS, 0, NCHTR*, chIOTR*) | +----------------------------------------+
with
IXST the index of the store holding the bank, or of any of its divisions !L the address of the bank IOWDS the integer array with the encoded characteristic (L must be zero in this case) NCHTR* number of useful characters stored into chIOTR = 0 if trouble chIOTR* the CHARACTER variable to receive the characteristic
The routine returns zero in NCHTR if L is non-zero and not a valid bank address, or if chIOTR is not long enough.
MZDROP
MZGARB - MZGAR1
MZLIFT - MZBOOK
MZLINK - MZLINT
MZRELB - MZRELL
+------------------------------+ | CALL MZDROP (IXSTOR,L,CHOPT) | +------------------------------+
case 1 : invalid input parameter L case 2 : LN = LQ(L) is invalidThe following numbers are given in /QUEST/
for cases 1 and 2 : IQUEST(11) = L for case 2 : IQUEST(12) = LNIn either case the parameters of the 'bank' pointed to by the invalid link L or LN are found in the post-mortem dump of /MZCN/.
+----------------------------+ |CALL MZGARB (IXGARB,IXWIPE) | +----------------------------+
case 1 : the store numbers of IXGARB and IXWIPE do not agreeThe following numbers are given in /QUEST/
for case 1 : IQUEST(11) = store number of IXGARB IQUEST(12) = store number of IXWIPE
+--------------+ | CALL MZGAR1 | +--------------+This is called from various parts of the system to force an automatic garbage collection for lack of space; NQRESV contains the amount of space available, a negative value indicates how much space has still to be found.
case 1 : not enough space can be found for a long range divisionThe following numbers are given in /QUEST/
for case 1 : IQUEST(11) = NQRESV, the amount of free space available, a negative number in this context IQUEST(12) = current store number IQUEST(13) = current division number (which may not be meaningful)
CALL ZTELL (99,1) not enough space for a short-range division IQUEST(11:13) as above
+--------------------------------------------+ |CALL MZLIFT (IXDIV,L*,LSUP,JB, NAME, NZERO) | +--------------------------------------------+
+--------------------------------------------------------+ | CALL MZBOOK (IXDIV,L*,LSUP,JB, IDH,NL,NS,ND,IOD,NZERO) | +--------------------------------------------------------+
case 1 : faulty NAME parameters case 2 : JB < 1 : LSUP does not point to a live bank JB = 1 : LSUP contains an invalid link case 3 : JB < 0 : the bank at LSUP has less than -JB structural links case 4 : LNEXT is invalid case 5 : I/O characteristic for IDH does not exist case 6 : I/O parameter NAME(5) = IOD(1) is invalid case 7 : trying to lift the bank into a wrong division, ie. the predecessor or the successor bank, address LSAME, is not in the division selected by IXDIV. case 8 : with JB=1 : trying to connect the new bank to the link at LQ(LP) in bank-spaceThe following numbers are given in /QUEST/
for all cases : IQUEST(11) = input value of LSUP (12) = JB (13) = IDH - NAME(1) (14) = NL - NAME(2) (15) = NS - NAME(3) (16) = ND - NAME(4) (17) = IOD - NAME(5) for case 4 : IQUEST(18) = LNEXT if JB < 1 : LNEXT=LQ(LSUP+JB) = 1 : LNEXT=LSUP for case 7 : IQUEST(18) = LSAME for case 8 : IQUEST(18) = LPThe parameters of the bank at LCHK are found in the post-mortem dump of /MZCN/, where LCHK is LSUP for cases 2 and 3; for case 4 LCHK is LNEXT.
+----------------------------------------------+ | CALL MZLINK (IXSTOR,CHNAME,LAREA,LREF,LREFL) | +----------------------------------------------+
+----------------------------------------------+ | CALL MZLINT (IXSTOR,CHNAME,LAREA,LREF,LREFL) | +----------------------------------------------+
case 1 : the parameters are inconsistent case 2 : the new link-area overlaps with the table of some store case 3 : the new link-area overlaps with some store case 4 : the new link-area overlaps with a previously defined link-area for some storeThe following numbers are given in /QUEST/
for cases 1 to 4 : IQUEST(11) = char 1:4 (12) = 5:8 of the printing name of the new link-area (13) = absolute adr of parameter LAREA (14) = absolute adr of parameter LREF (15) = absolute adr of parameter LREFL (16) = number of structural links derived (17) = total number of links derived for cases 2 to 4 : IQUEST(18) = serial number of the clashing store; = 0 for the primary store, = 1 for the first secondary store, etc. (19) = char 1:4 (20) = 5:8 of the printing name of the clashing store for case 4 : IQUEST(21) = char 1:4 (22) = 5:8 of the printing name of the clashing link-area (23) = absolute adr of the start of the clashing link-area (24) only for MZLINT : = initial content of LAREA(2)Case 4 will happen with MZLINT if the user over-writes the system word in LAREA(2), in which case the link-area will appear to clash with itself.
+----------------------------------------+ |CALL MZMARK (IXSTOR,L,CHOPT,NID,IDLIST) | +----------------------------------------+See MZFLAG
+-----------+ |CALL MZRELB| +-----------+ This is the relocator for links in banks.ZFATAL termination
case 1 : bank chaining clobbered case 2 : a structural link pointing into a dead area, and to be bridged, does not contain a valid bank address The following numbers are given in /QUEST/ the following numbers are given in /QUEST/ for case 1 : IQUEST(11) = LN, the start of the clobbered region for case 2 : IQUEST(11) = LS, the adr of the bank containing the invalid link IQUEST(12) = LW, the adr of the word containing the invalid link IQUEST(13) = the content of this link +-----------+ |CALL MZRELL| +-----------+ This is the relocator for links in Link Areas.ZFATAL termination
case 1 : a structural link pointing into a dead area, and to be bridged, does not contain a valid bank address The following numbers are given in /QUEST/ for case 1 : IQUEST(11) = absolute adr of the first word of the link area IQUEST(12) = relative position within the link area of the link to be bridged IQUEST(13) = the content of this link IQUEST(14) = char 1:4 (15) = 5:8 of the printing name of the link area
Go Back to the Snoman Companion Top Page