ASMB,L,C,R
      HED DBMST IMAGE/1000 UTILITY SUBROUTINE 
      NAM DBMST,7 92069-16155 REV.1912 790130 
* 
* 
******************************************************************* 
* (C) COPYRIGHT HEWLETT-PACKARD COMPANY 1979. ALL RIGHTS RESERVED.
* NO PART OF THIS PROGRAM MAY BE PHOTOCOPIED, REPRODUCED, OR
* TRANSLATED TO ANOTHER PROGRAM LANGUAGE WITHOUT THE PRIOR WRITTEN
* CONSENT OF HEWLETT-PACKARD COMPANY. 
******************************************************************* 
* 
* 
*     SOURCE:    92069-18155
*     RELOC:     92069-16155
* 
*     PRGMR:     CEJ
* 
* 
******************************************************************* 
* 
* 
* 
*  MaSTer put is a utility subroutine used by DBPUT to determine the
*  proper record number for a new master data set entry and to build the
*  media record in the record buffer for that entry 
* 
*  The calling sequence for DBMST is: 
* 
*         JSB DBMST 
*          DEF *+5
*          DEF BASE        data base # from ibase parameter 
*          DEF MSNUM       master data set's #
*          DEF READ        the READ flag from DBHRD 
*          DEF RECRD       the record # from DBHRD
* 
* 
*  DBMST returns a condition code in the A register, zero if successful.
* 
*  DBMST must be called immediately after DBHRD or before any of the
*  values passed back by DBHRD have been altered.  It uses the READ flag
*  and RECRD number returned by DBHRD to determine the new master record
*  number and to build the new entry's media record.  When we enter the 
*  routine we assume that the READ flag is not zero since this would
*  mean that a master entry already exists with the new entry's key item
*  value and the new entry could not be added.  If the READ flag is > 0,
*  the new record should go into the record whose number was passed by
*  DBHRD in RECRD, however, that record contains a synonym for another
*  chain.  Therefore, we must move it.  If the READ flag is < 0, we have
*  to check the record in the record buffer itself to decide what to do.
*  If the record is empty, we've hit the simplest case.  The new record 
*  is put into the record whose number was passed to us with no synonyms. 
*  If the record is non-empty, it contains the current synonym chain foot 
*  for the new record's synonym chain.  We need to find the next free re- 
*  cord in the master (searching serially from the record number: RECRD)
*  and make the new record the end of the synonym chain.
* 
*  Our first action is to resolve the parameter and return point addresses. 
* 
      ENT DBMST 
      EXT .DIS,.DCO,.ENTR,AIRUN,DBFCB,DBFDS,DBFWZ,DBRBL 
      EXT DBRBP,DBRED,DBWRT,EREAD 
A     EQU 0 
B     EQU 1 
* 
BASE  NOP 
MSNUM NOP 
READ  NOP 
RECRD NOP 
* 
DBMST NOP 
      JSB .ENTR 
       DEF BASE 
* 
      CLA           Set the primary FLAG
      STA FLAG        to true.
* 
*  We will deal with a synonym belonging to a different chain than the
*  new record first.  This means, move the synonym to the next (serially) 
*  free record in the master.  Then, put the new record in the synonym's
*  old record as a primary with "no" synonyms.
* 
      LDA READ,I
      SSA           Is READ flag > 0? 
      JMP MST3        No - we deal with that later. 
* 
      DLD RECRD,I     Yes - save this record #
      DST SAVE1 
* 
      JSB DBFFR     Ask DBFFR to give us the next 
*                                     free record in the data set.
* 
      LDA RECRD,I   Did DBFFR succeed?
      SSA             (i.e. record # non-negative?) 
      JMP MSTE        No - inform caller. 
* 
      JSB DBWRT       Yes - write the synonym to
       DEF *+4          the new record. 
       DEF BASE,I   DBWRT needs: data base #
       DEF MSNUM,I               data set # 
       DEF RECRD,I               record number
* 
      SZA           Did DBWRT encounter an error? 
      JMP MSTR        Yes - pass it to the user.
* 
      LDA DBRBP       No - save off synonym's forward 
      ADA D3            and backward synonym
      DLD A,I           chain pointers. 
      DST FRWRD 
      LDA DBRBP 
      INA 
      DLD A,I 
      DST BKWRD 
* 
*  Update any synonyms which point to the record we just moved. 
* 
      SZB,RSS       Was it's backward pointer = 0?
      SZA 
      RSS 
      JMP E154        Yes - we've got a corrupt chain.
* 
      JSB DBRED       No - read the backward pointer
       DEF *+4
       DEF BASE,I 
       DEF MSNUM,I
       DEF BKWRD
* 
      SZA           Did DBRED encounter an error? 
      JMP MSTR        Yes - pass it to user.
* 
      LDA DBRBP       No - make its forward pointer 
      ADA D3            the synonym's new record #
      STA TEMP
      DLD RECRD,I 
      DST TEMP,I
* 
      JSB DBWRT         and write it back to disc.
       DEF *+4
       DEF BASE,I 
       DEF MSNUM,I
       DEF BKWRD
* 
      SZA           Any error?
      JMP MSTR        Yes - pass it to the user.
* 
      CPA FRWRD+1     No - was synonym's forward pointer = 0? 
      RSS 
      JMP MST1
      CPA FRWRD 
      JMP MST2          Yes - we are through w/synonym. 
* 
MST1  JSB DBRED         No - read the forward pointer.
       DEF *+4
       DEF BASE,I 
       DEF MSNUM,I
       DEF FRWRD
* 
      SZA           Any error?
      JMP MSTR        Yes - pass it to user.
* 
      LDA DBRBP       No - make it's backward pointer 
      INA               the synonym's new record #. 
      STA TEMP
      DLD RECRD,I 
      DST TEMP,I
* 
      JSB DBWRT     Then, write it back out to disc.
       DEF *+4
       DEF BASE,I 
       DEF MSNUM,I
       DEF FRWRD
* 
      SZA           Any error?
      JMP MSTR        Yes - pass it to user.
* 
MST2  DLD SAVE1     Done with synonym move. 
      DST RECRD,I   Put new entry's record #
      JMP MST4        back into RECRD for joint processing. 
      SKP 
* 
*  Now, we'll deal with the case of the new record belonging to an al-
*  ready existant synonym chain.  (Remember that this case is signified 
*  by the READ flag < 0 and the entry in the record buffer being non- 
*  empty.)  This case is handled by finding the next free record in the 
*  data set from the current record number.  The new record is flagged
*  as a synonym by setting the primary FLAG to FALSE (-1) and storing the 
*  current record number (the old end of synonym chain) in the SYNYM
*  storage area.
* 
*  The READ flag is already known to be less than zero, so we start by
*  checking the entry type.  The type flag is the first word of the media 
*  record of the entry.  It is non-zero if the entry is empty.
* 
MST3  LDA DBRBP,I   Is the current entry empty? 
      SZA,RSS 
      JMP MST4        Yes - simple case.
* 
      DLD RECRD,I     No - save the record as the old 
      DST SYNYM         synonym chain foot. 
      CCA             Set the primary flag to FALSE.
      STA FLAG
* 
      JSB DBFFR     Get the next free record
*                                     in the master set.
* 
      LDA RECRD,I   Did we get it?
      SSA             Yes - continue to joint processing. 
      JMP MSTE        No - let the caller know. 
      SKP 
* 
*  There is no special processing for the simple case of DBHRD not find-
*  ing a synonym for the new record's key value and not finding a synonym 
*  in its proper primary location.  So we just join all cases here. 
* 
*  We have the new record's proper record number in RECRD.  If it is a
*  synonym (primary FLAG = FALSE) we have the old synonym chain foot's
*  record number in SYNYM.  Now all we have to do is build the new record 
*  in the record buffer by setting its proper entry type in the first 
*  word of the media record to: 
*     1 - if a primary entry (FLAG = TRUE)
*    -1 - if a synonym entry (FLAG = FALSE) 
*  and if a synonym, setting the backward synonym pointer (2nd & 3rd words
*  of media record) to SYNYM.  The remainder of the media record is all 
*  zeroes.
* 
MST4  JSB DBFWZ     Fill the record buffer with zeroes. 
       DEF *+3
       DEF DBRBL    DBFWZ needs: length of area to zero 
       DEF DBRBP                 address of area to zero
* 
      CLB,INB       If a primary entry, set 
      LDA FLAG        entry type to 1 
      SSA             else set entry typ
      CMB,INB         to -1.
      STB DBRBP,I 
* 
      SSA,RSS       If a synonym, put SYNYM 
      JMP MSTE        in new record's backward
      LDB DBRBP       synonym chain pointer.
      INB 
      STB TEMP
      DLD SYNYM 
      DST TEMP,I
* 
*  Return to caller.
* 
MSTE  CLA 
MSTR  JMP DBMST,I 
* 
*  Error return point.
* 
E154  LDA D154      Corrupt chain pointers. 
      JMP MSTR
* 
*  Constants and variables. 
* 
D3    DEC 3 
D154  DEC 154 
SYNYM BSS 2 
FRWRD BSS 2 
BKWRD BSS 2 
SAVE1 BSS 2 
TEMP  NOP 
FLAG  NOP 
      SKP 
* 
*  Find Free Record is a utility subroutine for DBMST.  It performs the 
*  service of finding the next free record in a master data set (MSNUM) 
*  by searching serially through the data set from the current record 
*  number (in RECRD) until a free record is found or a complete wrap around 
*  on the set has been performed.  If it finds a free record, it returns
*  the number of that record in RECRD.  If it does not find a free record,
*  it sets RECRD to -1. 
* 
DBFFR NOP 
* 
*  Save current record number in RECRD as starting point. 
* 
      DLD RECRD,I 
      DST START 
* 
*  Ask DBFCB to give us the data set's DCB. 
* 
      JSB DBFCB 
       DEF *+4
       DEF BASE,I   DBFCB needs: data base number 
       DEF MSNUM,I               data set number
       DEF MSDCB        returns: DCB address
* 
      SZA           Did DBFCB encounter an error? 
      JMP MSTR        Yes - return in to user.
* 
*  Ask DBFDS to get MSNUM'S DSCB pointer for us.
* 
      JSB DBFDS 
       DEF *+5
       DEF MSNUM,I
       DEF NUMBR
       DEF ENTYP
       DEF MSPTR
* 
      LDA NUMBR     If set # came back
      SZA,RSS         as zero 
      JMP FFRE        bad Run Table.
* 
*  Get the address of the capacity in the DSCB (9th word) and save it 
*  in MSPTR.
* 
      LDA MSPTR 
      ADA AIRUN 
      ADA CAPAC 
      STA MSPTR 
* 
*  Now read serially through the data set searching for an empty record.
*  we need only the first word of each entry since it contains the entry
*  type flag (will be zero for an empty record).
* 
FFR1  JSB .DIS      Increment the record #. 
       DEF RECRD,I
      NOP 
* 
*  Check to see if the new record number is greater than the capacity.
*  If so, set the record number to 1 before we read it. 
* 
      DLD MSPTR,I 
      JSB .DCO
       DEF RECRD,I
      RSS           Record # = capacity.
      RSS           Record # > capacity.
      JMP FFR2      Record # < capacity.
* 
      CLA 
      CLB,INB 
      DST RECRD,I 
* 
FFR2  DLD START 
      JSB .DCO
       DEF RECRD,I  If same as starting record
       JMP FFRE       we've completely wrapped
       NOP            around data set.
* 
      JSB EREAD     Read the first word of the record.
       DEF *+7
       DEF MSDCB,I
       DEF ERROR
       DEF ENTYP
       DEF D1 
       DEF DUMMY      (merely a place holder) 
       DEF RECRD,I
* 
      SSA           Did we get an error?
      JMP MSTR        Yes - pass the error to the user. 
* 
*  Here on a successful read, check the entry type in ENTYP.  If it is
*  zero - we've got the record we want, pass it back to the caller. 
* 
      LDA ENTYP 
      SZA 
      JMP FFR1
* 
FFR4  JMP DBFFR,I 
* 
*  Error return point - no empty record found.
* 
FFRE  CCB 
      CCA 
      DST RECRD,I 
      JMP FFR4
* 
*  Constants and variables
* 
D1    DEC 1 
CAPAC DEC 8 
START BSS 2 
ENTYP NOP 
ERROR NOP 
NUMBR NOP 
DUMMY EQU NUMBR 
MSDCB NOP 
MSPTR NOP 
      END 
          