* 4/25/72 -- 15:00 (7F)
* MODULE NAME: TAG
* NUMBER: 7
* PURPOSE: PROVIDE VARIOUS TAG SERVICES
*
* ENTRY POINTS:
         DEF      S07CHHDR          MOVE OR DELETE HEADER RECORD
         DEF      S07HDOCC          CHANGE HEADER RECORD OCCURENCE
         DEF      S07TGOCC          CHANGE TAG RECORD OCCURENCE
         DEF      S07RDTAG          READ TAG RECORD
         DEF      S07DTAG           DELETE TAG RECORD
         DEF      S07MVTAG          MOVE TAG OCCURENCES
         DEF      S07HASH           CALC. TAG KEY HASH TOTALS
*
         REF      S27RHDR,S27WHDR,S27DRHDR   READ/WRITE/DELETE HDR RCDS
         REF      S29STD            PRINT ERROR MESSAGES
*
*
         SYSTEM   TEXTDEF
         SYSTEM   ITEMDEF
            INVWSSTA
            INVHDRSTA
            INVTAGSTA
*
         DEF      7P,7D
7P       EQU      %
         DATA     X'07'             MODULE NUMBER
         DATA     X'042572'         DATE
         DATA     X'1500'           TIME
*
         TITLE    '** TAG(7) **'
         PAGE
*
* S07CHHDR -- DELETE OR MOVE HEADER RECORD
*
* ENTRY PARAMETERS:
*        AC1 = OLD KEY
*        AC2 = NEW KEY (ZERO FOR DELETE)
*
S07CHHDR EQU      %
         SAVRTN
         LCI      2                 SAVE INPUT PARAMS:
         STM,AC1  OHDRKEY               OLD KEY, NEW KEY
*
         LI,BUF2  BA(HDRSTA)        GET ADDR OF HEADER RECORD BUFFER
         LI,AC1   SZHDRSTA*4        SIZE OF BUFFER (IN BYTES)
         LW,AC2   OHDRKEY           OLD KEY
         BAL,SRTN S27RHDR           READ HEADER RECORD
         CI,AC1   0                 TEST FOR NO RECORD
         BE       RTNCHHDR              SIZE ZERO, RETURN
*
         STW,AC1  HDRSZ             SAVE RECORD SIZE
         JEZ,D1   HDR:NTAGS,DHDRREC TEST NUMBER OF TAG OCCURENCES
         STW,D1   TAGINDX           SAVE IF NON-ZERO
*
         LI,BUF1  WA(STDPRBUF)      GET BUFFER TO READ TAG
         STW,BUF1 TAGBUF            SAVE TAG BUFFER ADDR
         STW,AC2  MAXSZ             SAVE MAX SIZE
*
*
         PAGE
*
CHTAGLP  EQU      %
         LW,X1    TAGINDX           GET NEXT OCCURENCE POINTER
         GET,D1   HDR:TAGKEY,X1     GET NEXT TAG OCCURENCE
         LI,X1    0                 SET TAG COUNT TO ZERO (KEY USED)
         LW,AC2   D1                GET TAG KEY
         BAL,SRTN S07RDTAG          GO READ TAG RECORD
*
         LW,AC1   OHDRKEY           GET OLD OCCURENCE KEY
         LW,AC2   NHDRKEY           GET NEW OCCURENCE KEY
         LW,X1    TAGINDX           GET INDEX
         GET,AC3  HDR:TAGDISP,X1    GET DISP IN LINE
         BAL,SRTN S07TGOCC          GO CHANGE TAG OCCURENCE
         MTW,-1   TAGINDX           DECREMENT OCCURENCE INDEX
         BGZ      CHTAGLP           GO CHANGE NEXT OCCURENCE
*
DHDRREC  EQU      %                 DELETE OR MOVE ACTUAL HEADER RECORD
         LW,AC2   OHDRKEY           GET OLD KEY
         BAL,SRTN S27DRHDR          GO DELETE RECORD
         LW,AC2   NHDRKEY           GET NEW KEY
         BEZ      RTNCHHDR              ZERO, RETURN
         LI,BUF3  BA(HDRSTA)        GET ADDR OF HEADER RECORD BUFFER
         LW,AC1   HDRSZ             GET SIZE OF BUFFER
         BAL,SRTN S27WHDR           GO WRITE NEW KEY
*
RTNCHHDR EQU      %                 RETURN
         RETURN
*
         PAGE
*
* S07HDOCC -- CHANGE OR DELETE HEADER RECORD TAG OCCURENCE
*
* ENTRY: AC1 = KEY FOR OLD OCCURENCE
*        AC2 = KEY FOR NEW OCCURENCE
*        AC3 = KEY FOR HEADER RECORD
*
S07HDOCC EQU      %
         SAVRTN
         LCI      3
         STM,AC1  OLDOCC            SAVE ENTRY PARAMS
*
         LI,BUF2  BA(HDRSTA)        GET ADDR OF HEADER STATUS BUFFER
         LI,AC1   SZHDRSTA*4        GET SIZE (IN BYTES)
         LI,AC2   3
         STB,AC2  HDRKEY            SET BYTE 0 OF KEY FOR COUNT
         LW,AC2   HDRKEY            GET HEADER KEY
         BAL,SRTN S27RHDR           READ HEADER RECORD
         STW,AC1  HDRSZ             SAVE SIZE
*
         GET,X1   HDR:NTAGS         GET NUMBER OF TAGS FOR THIS HEADER
         STW,X1   HNTAGS            SAVE
         LI,AC1   0
         STB,AC1  OLDOCC            SET BYTE 0 OF OLD OCCURENCE FOR KEY
*
*
         PAGE
*
*
GETOCCLP EQU      %
         GET,D1   HDR:TAGKEY,X1     GET NEXT TAG KEY FOR THIS HEADER
         CW,D1    OLDOCC            COMPARE WITH OLD OCCURENCE
         BE       HDROCC                EQUAL, OCCURENCE FOUND
         BDR,X1   GETOCCLP          GET NEXT OCCURENCE
         B        RTNHDOCC
*
HDROCC   EQU      %
         LW,D1    NEWOCC            GET NEW OCCURENCE
         BEZ      DELHOCC               ZERO, DELETE OLD OCCURENCE
         PUT,D1   HDR:TAGBASE,X1    PUT IN HEADER RECORD
         B        WRNWHDR           GO RE-WRITE HEADER
*
*
         PAGE
*
*
DELHOCC  EQU      %
         LW,AC2   HNTAGS            GET OLD NUMBER OF TAGS
         SW,AC2   X1                SUBTRACT CURRENT POINTER
         BEZ      DECRCNT           IF LAST, GO DECREMENT COUNT
         AI,X1    :ADEO(HDR:TAGBASE)              ADD WA OF TAG BASE
*
DELOCCLP EQU      %
         LW,D1    1,X1              GET NEXT MOVE WORD
         STW,D1   0,X1              MOVE TO ONE LESS
         AI,X1    1                 INCREMENT POINTERS
         BDR,AC2  DELOCCLP          DECREMENT COUNT AND GET NEXT
*
DECRCNT  EQU      %
         LW,D1    HNTAGS            GET OLD NUMBER OF TAGS
         AI,D1    -1                DECREMENT
         BEZ      DELHDR            IF ZERO, DELETE HEADER RECORD
         PUT,D1   HDR:NTAGS         PUT NEW COUNT IN RECORD
         MTW,-4   HDRSZ             DECREMENT RECORD SIZE BY 4 BYTES
*
         PAGE
*
*
WRNWHDR  EQU      %
         LI,BUF3  BA(HDRSTA)        GET ADDR OF HEADER REC
         LW,AC1   HDRSZ             GET SIZE
         LW,AC2   HDRKEY            GET KEY
         BAL,SRTN S27WHDR           WRITE NEW HEADER RECORD
         B        RTNHDOCC          RETURN
*
DELHDR   EQU      %                 DELETE HEADER RECORD
         LW,AC2   HDRKEY            GET KEY
         BAL,SRTN S27DRHDR          GO DELETE RECORD
*
RTNHDOCC EQU      %                 RETURN
         RETURN
*
*
         PAGE
*
* S07TGOCC -- CHANGE TAG OCCURENCE  (REPLACE,ADD,OR DELETE)
*
* ENTRY: TAGBUF,OCCBASE,NUMOCC SET FOR THIS TAG
*        AC1 = OLD OCCURENCE (0 IF ADD NEW OCCURENCE)
*        AC2 = NEW OCCURENCE (0 IF DELETE OLD OCCURENCE)
*        AC3 = DISPLACEMENT FOR NEW OCCURENCE
*
* EXIT:  SR3 = 0 IF OLD OCCURENCE FOUND
*            = 1 IF OLD OCCURENCE NOT FOUND
*
S07TGOCC EQU      %
         SAVRTN
         LCI      3
         STM,AC1  OLDOCC            SAVE ENTRY PARAMETERS
         LI,AC1   0                 SET BYTE 0 TO 0
         STB,AC1  OLDOCC
         STB,AC1  NEWOCC
*
         MTW,0    OLDOCC            TEST FOR OLD OCCURENCE
         BEZ      ADDNWOCC              ZERO, ADD NEW OCCURENCE
         LW,X1    NUMOCC            GET NUMBER OF OCCURENCES
*
*
         PAGE
*
*
OLDOCCLP EQU      %
         GET,D1   *TAG:OCCKEY,X1    GET NEXT OCCURENCE KEY
         CW,D1    OLDOCC            COMPARE WITH OLD KEY
         BE       OCCFND                EQUAL
DECROLDO EQU      %
         BDR,X1   OLDOCCLP              NOT EQUAL, GET NEXT
         B        NTFNDRTN          NOT FOUND, ERROR RETURN
*
OCCFND   EQU      %
         GET,D1   *TAG:OCCDISP,X1   GET DISPLACEMENT
         CW,D1    NEWDISP           TEST
         BNE      DECROLDO             NOT EQUAL, GET NEXT
*
DELOCC   EQU      %                 DELETE OCCURENCE (NEWOCC=0)
         LW,AC1   NUMOCC            GET NUMBER OF OCCURENCES
         SW,AC1   X1                SUBTRACT OLD OCCURENCE NUMBER
         BEZ      DECROCC              LAST ONE DONT MOVE
         AW,X1    OCCBASE           GET WA OF OLD OCCURENCE
*
         PAGE
*
MVOLP    EQU      %
         LW,AC2   1,X1              GET OCCURENCE +1
         STW,AC2  0,X1              STORE IN OLD OCCURENCE
         AI,X1    1                 INCREMENT OCCURENCE POINTER
         BDR,AC1  MVOLP             GET ALL OCCURENCES
*
DECROCC  EQU      %
         MTW,-1   NUMOCC            DECREMENT NUMBER OF OCCURENCES
         MTW,-4   TAGRECSZ          DECREMENT TAG RECORD SIZE
*
ADDNWOCC EQU      %                 ADD NEW OCCURENCE
         MTW,0    NEWOCC            TEST FOR NEW KEY
         BEZ      FNDRTN               NO, RETURN
         LW,X1    NUMOCC               YES, GET CURRENT NUMBER
         BEZ      STNWOCC
*
NWOCCLP  EQU      %
         GET,D2   *TAG:OCCKEY,X1    GET OCCURENCE KEY
         CW,D2    NEWOCC            COMPARE TO NEW OCC.
         BL       STNWOCC              LESS, STORE NEW
         BE       TSTDISP              EQUAL, TEST DISP.
*
DECRNWLP EQU      %
         BDR,X1   NWOCCLP           GET NEXT OCC.
         B        STNWOCC           STORE NEW OCC.
*
TSTDISP  EQU      %
         GET,D2   *TAG:OCCDISP,X1   GET DISP.
         CW,D2    NEWDISP           COMPARE TO NEW DISP
         BG       DECRNWLP             LESS, GET NEXT
*
*
         PAGE
*
*
STNWOCC  EQU      %
         AI,X1    1                 INDEX FOR NEW OCC.
         LW,X2    NUMOCC            CURRENT NUMBER OF OCC.
*
TSTOCCX  EQU      %
         CW,X2    X1                COMPARE TEST WITH NEW
         BL       MVNWOCC              LESS, MOVE NEW OCC.
         GET,D1   *TAG:OCCBASE,X2   GET OCC.
         AI,X2    1                 MOVE TO 1 HIGHER
         PUT,D1   *TAG:OCCBASE,X2
         AI,X2    -2                GET NEXT ONE TO MOVE
         B        TSTOCCX           TEST NEXT
*
MVNWOCC  EQU      %
         LW,D1    NEWOCC            GET NEW KEY
         PUT,D1   *TAG:OCCKEY,X1    STORE IN TAG
         LW,D1    NEWDISP           GET DISP
         PUT,D1   *TAG:OCCDISP,X1   STORE IN TAG
*
         MTW,1    NUMOCC            INCREMENT OCC. COUN
         MTW,4    TAGRECSZ          INCREMENT TAG RECORD SIZE
         B        FNDRTN            RETURN
*
*
         PAGE
*
*
NTFNDRTN EQU      %
         LI,SR3   1                 SET ERROR RETURN
         B        RTNTGOCC          RETURN
*
FNDRTN   EQU      %
         LW,D1    NUMOCC            GET NEW NUMBER OF OCCURENCES
         BEZ      DELTAG               ZERO,DELETE TAG
         PUT,D1   *TAG:NOCC         STORE IN TAG RECORD
         LW,BUF3  TAGBUF            GET ADDR OF TAG BUFFER
         SLS,BUF3 2                 CALC BYTE ADDR
         LW,AC1   TAGRECSZ          GET RECORD SIZE
         LW,AC2   TAGKEY            GET TAG KEY
         BAL,SRTN S27WHDR           GO WRITE NEW TAG RECORD
*
NOERRTN  EQU      %
         LI,SR3   0                 SET ERROR RETURN TO ZERO
*
RTNTGOCC EQU      %                 RETURN
         RETURN
*
DELTAG   EQU      %
         BAL,SRTN S07DTAG           GO DELETE THIS TAG RECORD
         B        NOERRTN           RETURN
         PAGE
*
* S07RDTAG -- READ TAG RECORD GIVEN ACTUAL TAG OR KEY
*
* ENTRY PARAMETERS:
*        X1 = COUNT/BYTE ADDR OF TAG
*    OR:
*        AC2= KEY FOR TAG RECORD
*
* EXIT PARAMETERS:
*        AC1= NUMBER OF CHARS IN TAG (ZERO IF NOT FOUND)
*        TAGBUF,OCCBASE,NCTAG,NUMOCC,TAGKEY,TAGSZ,LSTKEY,NXTHASH
*                 SET FOR THIS TAG
*
*
S07RDTAG EQU      %
         SAVRTN
*
         STW,X1   TAGBA             SAVE BA OF TAG
         STW,D1   TAGTYPE           SAVE TAG TYPE
         STW,D2   TLEVEL            AND TITLE LEVEL
         STW,AC2  TAGKEY            SAVE TAG KEY
         LB,AC1   TAGBA             GET NUMBER OF TAG CHARS
         STW,AC1  TAGCHARS          SAVE NUMBER OF CHARS
         LI,AC1   0
         STW,AC1  LSTKEY            INITIALIZE LAST KEY
         STB,AC1  TAGBA             SET BYTE ZERO OF POINTER TO ZERO
*
*
         PAGE
*
*
TSTSZTAG EQU      %
         LW,AC1   TAGCHARS          GET SIZE OF TAG
         BLEZ     RDTAGKEY             ZERO, READ KEY
         LW,X1    TAGBA                >0, GET ADDR OF TAG
         BAL,SRTN S07HASH           NOW CALC HASH TOTAL
         STW,AC2  TAGKEY            SAVE HASH KEY
         STW,AC2  HASHKEY
*
RDTAGKEY EQU      %
         LW,BUF2  TAGBUF            GET ADDR OF TAG BUFFER
         SLS,BUF2 2                 CALC BYTE ADDR
         LI,AC1   #STDBUFSZ         MAX SIZE
         LI,AC2   3
         STB,AC2  TAGKEY            SET BYTE ZERO OF KEY TO 3
         LW,AC2   TAGKEY            GET KEY FOR READ
         BAL,SRTN S27RHDR           GO READ TAG RECORD
         CI,AC1   0                 SAVE SIZE OF RECORD
         BE       TAGNTFND          TEST FOR NOT FOUND
         STW,AC1  TAGRECSZ              NOT FOUND, RETURN
         GET,D1   *TAG:NCTAG        GET NUMBER OF CHARS
         MTW,0    TAGCHARS          TEST FOR TAG TO COMPARE
         BEZ      TSTOVFL               NO, USE THIS ONE
         CW,D1    TAGCHARS          COMPARE NUMBER OF CHARS
         BNE      RDNXTAG               NOT EQUAL, READ NEXT TAG
*
*
         PAGE
*
*
         GET,D2   *TAG:TYPE         GET TAG TYPE
         CW,D2    TAGTYPE           TEST FOR INPUT TYPE
         BNE      RDNXTAG              NO, READ NEXT
         CI,D2    3                 TEST FOR TITLE TYPE
         BNE      CBST                 NO, SKIP TITLE LEVEL TEST
         MTW,0    TLEVEL            TEST TITLE LEVEL
         BLZ      CBST                 -, DONT CHECK
         GET,D2   *TAG:TLEVEL       GET TITLE LEVEL
         CW,D2    TLEVEL            TEST INPUT TLEVEL
         BNE      RDNXTAG           NO, READ NEXT
*
CBST     EQU      %
         LW,X1    TAGBA             GET ADDR OF COMPARE TAG
         LW,X2    TAGBUF            GET ADDR OF TAG BUFFER
         SLS,X2   2                 CALC BYTE ADDR
         AI,X2    #TAGDISP          ADD DISP. OF TAG IN RECORD
         STB,D1   X2                STORE COUNT FOR MBS
         CBS,X1   0                 COMPARE TAGS
         BE       TAGFND                FOUND
*
*
         PAGE
*
*
RDNXTAG  EQU      %
         STW,AC2  LSTKEY            STORE LAST KEY
         JEZ,D2   *TAG:NXTHASH,TAGNTFND TEST FOR OVERFLOW RECORD
         STW,D2   TAGKEY            SAVE NEW KEY
         B        RDTAGKEY          GO READ OVERFLOW
*
TAGNTFND EQU      %                 TAG NOT FOUND
         LI,AC1   0                 SET TAG SIZE TO ZERO
         LW,AC3   HASHKEY           GET HASH KEY
         LW,AC2   LSTKEY            AND LAST KEY
         BEZ      RTNRDTAG             ZERO,RETURN
         B        GTAGPARS          GO GET PARAMS
*
TAGFND   EQU      %
         LW,AC1   D1                GET NUMBER OF CHARS IN TAG
*
*
         PAGE
*
*
GTAGPARS EQU      %
         STW,D1   NCTAG             SAVE NUMBER OF CHARS
         SLS,D1   -2                CALCULATE BASE ADDR FOR OCCURENCES
         AI,D1    2
         AW,D1    TAGBUF
         STW,D1   OCCBASE           SAVE
*
         GET,D1   *TAG:NOCC         GET NUMBER OF OCCURENCES
         STW,D1   NUMOCC            SAVE
         GET,D1   *TAG:NXTHASH      GET NEXT HASH TOTAL KEY
         STW,D1   NXTHASH           SAVE
         LW,AC3   TAGRECSZ          GET TAG SIZE
*
RTNRDTAG EQU      %                 RETURN
         RETURN
*
*
         PAGE
*
*
TSTOVFL  EQU      %
         CW,AC2   L(#OVFLKEY)       TEST FOR OVERFLOW TAG
         BL       TAGFND               NO, TAG FOUND
         STW,D1   NCTAG                YES, SAVE TAG SIZE
         LW,X1    TAGBUF            GET ADDR OF TAG RECORD
         SLS,X1   2                 CONVERT TO BYTE ADDR
         AI,X1    #TAGDISP          ADD TAG DISPLACEMENT
         LW,AC1   NCTAG             GET TAG SIZE
         BAL,SRTN S07HASH           GET HASH-TOTAL KEY
*
TSTNXT   EQU      %
         LI,BUF2  BA(MSGBUF)        GET SMALL BUFFER FOR NEXT HASH
         LI,AC1   8                 MAX SIZE (2 WORDS)
         BAL,SRTN S27RHDR           READ HEADER RECORD
         CI,AC1   0                 TEST FOR NONE
         BLE      RTNOVTST             ZERO, RETURN
         LW,D1    MSGBUF+1          GET NEXT HASH
         BLEZ     RTNOVTST             ZERO, RETURN
         CW,D1    TAGKEY            TEST FOR POINTER TO TAG
         BE       SETLST               FOUND, SET LAST KEY
         LW,AC2   D1                   NOT FOUND, GET NEXT
         B        TSTNXT
*
SETLST   EQU      %
         STW,AC2  LSTKEY            SET POINTER KEY
RTNOVTST EQU      %
         LW,D1    NCTAG             GET TAG SIZE AGAIN
         B        TAGFND            TAG FOUND
*
*
         PAGE
*
* S07DTAG -- DELETE CURRENT TAG RECORD
*
*
S07DTAG  EQU      %
         SAVRTN
*
         LW,AC2   LSTKEY            TEST LAST KEY IN CHAIN
         BNEZ     RDLSTKEY              NON-ZERO, GO READ LAST KEY
         LW,AC2   NXTHASH           TEST NEXT HASH TOTAL
         BNEZ     RDNXTKEY              NON-ZERO, GO READ NEXT KEY
         LW,AC2   TAGKEY            GET THIS KEY FOR DELETE
         B        DELKEY            GO DELETE KEY
*
RDLSTKEY EQU      %                 LAST KEY NON-ZERO
         LW,AC1   NXTHASH           SAVE NEXT HASH FOR THIS RECORD
         STW,AC1  TMPHASH
         LW,AC1   TAGKEY            SAVE TAG KEY FOR THIS RECORD
         STW,AC1  TMPKEY
         LI,X1    0                 SET TAG CHARS TO ZERO
         BAL,SRTN S07RDTAG          GO READ LAST TAG RECORD
*
         LW,D1    TMPHASH           GET NEXT HASH FROM DELETED RECORD
         PUT,D1   *TAG:NXTHASH      STORE IN TAG RECORD
         LW,AC2   TAGKEY            GET CURRENT KEY TO RE-WRITE RECORD
         B        WRTAGREC          GO WRITE RECORD
*
*
         PAGE
*
*
RDNXTKEY EQU      %                 LAST KEY=0, NEXT HASH NON-ZERO
         LW,AC1   TAGKEY            GET CURRENT TAG KEY
         STW,AC1  TMPKEY            SAVE KEY FOR RE-WRITE
         LI,X1    0
         BAL,SRTN S07RDTAG          GO READ NEXT HASH KEY
         LW,AC2   TMPKEY            GET CURRENT KEY
         BAL,SRTN S07MVTAG          GO MOVE OCCURENCES (HEADER RECORDS)
         LW,AC2   TAGKEY            GET KEY FOR DELETE
         XW,AC2   TMPKEY            GET KEY FOR RE-WRITE, SAVE DEL KEY
*
WRTAGREC EQU      %
         LW,BUF3  TAGBUF            GET ADDR OF TAG BUFFER
         SLS,BUF3 2                 CALC BYTE ADDR
         LW,AC1   TAGRECSZ          GET RECORD SIZE
         BAL,SRTN S27WHDR           GO WRITE TAG RECORD
         LW,AC2   TMPKEY            GET DELETE KEY
*
DELKEY   EQU      %                 DELETE TAG RECORD, KEY IS IN AC2
         BAL,SRTN S27DRHDR
*
RTNDTAG  EQU      %
         RETURN
*
*
         PAGE
*
* S07MVTAG -- CHANGE KEYS IN HEADER RECORDS FOR NEW TAG KEY
*
* ENTRY PARAMETERS:
*        AC2 = NEW KEY FOR TAG RECORD
*
S07MVTAG EQU      %
         SAVRTN
         STW,AC2  NEWKEY            SAVE NEW KEY
*
         LW,X1    NUMOCC
         STW,X1   TMPINDX
*
MVOCCLP  EQU      %
         GET,AC3  *TAG:OCCBASE,X1
         LB,AC1   AC3               GET DISP FOR OCC.
         STB,AC1  NEWKEY            STORE IN NEW KEY
         LW,AC1   TAGKEY
         LW,AC2   NEWKEY
         BAL,SRTN S07HDOCC
*
         MTW,-1   TMPINDX
         BLEZ     RTNMVTAG
         LW,X1    TMPINDX
         B        MVOCCLP
*
RTNMVTAG EQU      %
         LW,AC2   NEWKEY            RESTORE ARGUMENT
         RETURN
*
*
         PAGE
*
* S07HASH -- CALCULATE HASH TOTAL FOR TAG KEY
*
* ENTRY PARAMETERS: X1 = BYTE ADDR OF TAG
*                   AC1= NUMBER OF CHARS
*
* EXIT PARAMETER:   AC2= HASH KEY(STARTING AT X'03A00000')
*
S07HASH  EQU      %
         SAVRTN
*
         STW,AC1  TAGCHARS          SAVE NUMBER OF CHARS
         LI,AC3   1                 INITIALIZE NUMBER OF CHARS USED
         LI,X3    6                 INITIALIZE SIZE OF SHIFT
         LI,AC1   0                 INITIALIZE HASH TOTAL TO ZERO
SHFTLP   EQU      %
         LI,D1    1                 SET SPECIAL U.C. ADD CHAR
         CW,AC3   TAGCHARS          TEST FOR MAX CHARS
         BLE      GETCHAR               NO, GET NEXT TAG CHAR
         LI,AC2   0                     YES, USE ZERO
         B        SHFTNUM           GO SHIFT INTO KEY
*
GETCHAR  EQU      %
         LB,AC2   0,X1              GET NEXT TAG CHAR
         AI,X1    1                 INCREMENT TAG POINTER
         CLM,AC2  LCLIM             TEST FOR LOWER-CASE
         BCR,9    LCFND                YES
         CLM,AC2  UCLIM             TEST FOR UPPER-CASE
         BCR,9    UCFND                YES
         CLM,AC2  NUMLIM            TEST FOR NUMBER
         BCR,9    NUMFND               YES
*
*
         PAGE
*
*
SPCHFND  EQU      %                 SPECIAL CHARACTER
         CI,AC2   #BLANK            TEST FOR BLANK
         BNE      SPCHHASH             NO
         LI,AC2   0                    YES, SET HASH=0
         B        SHFTNUM           NOW GO SHIFT
SPCHHASH EQU      %
         LI,AC2   63                SET HASH=63 FOR SP. CHARS
*
LCFND    EQU      %
         AI,AC2   X'40'             CONVERT TO UPPER-CASE
         LI,D1    0                 RESET SPECIAL U-C ADD CHAR
*
UCFND    EQU      %
         CLM,AC2  JRLIM             TEST FOR A-I,J-R,S-Z
         BCR,9    UCJTOR               J-R
         BCS,8    UCSTOZ               S-Z
         AI,AC2   -'A'+1               A-I (HASH=1-9)
         B        UCRTN             GO SET-UP SHIFT
*
UCJTOR   EQU      %
         AI,AC2   -'J'+10           HASH = 10-18
         B        UCRTN             GO SET-UP SHIFT
*
UCSTOZ   EQU      %
         AI,AC2   -'S'+19           HASH = 19-26
*
UCRTN    EQU      %
         SLS,AC2  1                 MULTIPLY BY 2
         SW,AC2   D1                SUBTRACT SPECIAL U-C CHAR
         B        SHFTNUM           GO SHIFT HASH
*
NUMFND   EQU      %
         AI,AC2   -'0'+53           HASH = 53-62
*
         PAGE
*
*
SHFTNUM  EQU      %
         SLS,AC2  26                LEFT-JUSTIFY IN AC2
         SLD,AC1  0,X3              SHIFT INTO HASH-TOTAL REG.
*
         AI,AC3   1                 INCREMENT CHAR COUNTER FOR TAG
         CI,AC3   2                 TEST FOR MORE THAN TWO
         BLE      SHFTLP                NO, CONTINUE SHIFT
         LI,X3    5                     YES, ONLY USE 5 BITS
         CI,AC3   4                 TEST FOR 4 CHARS USED
         BLE      SHFTLP                <=4, CONTINUE SHIFT
*
SHFTFIN  EQU      %                 SHIFT FINISHED, HASH TOTAL FOUND
         AW,AC1   L(#TAGKEY)        ADD LOWEST POSSIBLE TAG KEY
         LW,AC2   AC1               SET RETURN PARAMETER
         RETURN
*
*
         BOUND    8
LCLIM    DATA     LC('A'),LC('Z')   LOWER-CASE LIMITS
UCLIM    DATA     'A','Z'           UPPER-CASE LIMITS
NUMLIM   DATA     '0','9'           NUMBER LIMITS
JRLIM    DATA     'J','R'           J-R LIMITS
*
*
         PAGE
*
* LOCAL VARIABLES FOR TAG SERVICES
*
7D       CSECT    0                 START OF LOCALS
*
OHDRKEY  RES      1                 INPUT PARAMS FOR S07CHHDR:
NHDRKEY  RES      1                     OLD KEY/NEW KEY
*
OLDOCC   RES      1                 INPUT PARAMS FOR S07HDOCC,S07TGOCC:
NEWOCC   RES      1                     OLD OCCURENCE/NEW OCCURENCE
HDRKEY,NEWDISP RES  1                   HEADER KEY,NEW DISPLACEMENT
*
OLDTAG   RES      1                 INPUT PARAMS FOR S07CHTAG:
NEWTAG   RES      1                     OLD TAG/NEW TAG
*
TAGCHARS RES      1                 INPUT PARAMS FOR S07RDTAG:
TAGBA    RES      1                     NUMBER OF CHARS/BYTE ADDR
TAGKEY   RES      1                     TAG KEY
TAGTYPE  RES      1                 TAG TYPE
TLEVEL   RES      1                 TITLE LEVEL
*
NEWKEY   RES      1                 INPUT PARAM FOR S07MVTAG: NEW KEY
*
*
         PAGE
*
*                                   TAG RECORD PARAMETERS (SET BY RDTAG)
NCTAG    RES      1                     NUMBER OF CHARS IN TAG
NUMOCC   RES      1                     NUMBER OF OCCURENCES
TAGRECSZ RES      1                     SIZE OF TAG RECORD (IN BYTES)
LSTKEY   RES      1                     LAST KEY IN TAG RECORD CHAIN
HASHKEY  RES      1                 HASH TOTAL KEY
NXTHASH  RES      1                     NEXT KEY IN TAG RECORD CHAIN
*
HDRSZ    RES      1                 SIZE OF HEADER RECORD (IN BYTES)
TAGINDX  RES      1                 INDEX POINTER FOR TAG OCCURENCES
MAXSZ    RES      1                 MAX SIZE OF TAG BUFFER
HNTAGS   RES      1                 NUMBER OF TAGS IN HEADER RECORD
*
*                                   TEMP VARIABLES
TMPKEY   RES      1                     KEY
TMPBUF   RES      1                     BUFFER ADDR
TMPOCC   RES      1                     OCCURENCE BASE
TMPHASH  RES      1                     NEXT HASH TOTAL
TMPINDX  RES      1                     INDEX
*
*
         USECT    #PLOC
         END
