;*************************** AMUS Program Label ******************************
; Filename: HASH.SBR                                        Date: 06/12/89
; Category: DISK         Hash Code: 644-125-730-247      Version: 1.0(102)
; Initials: AMI          Name: AMI BAR-YADIN
; Company: UNITED FASHIONS OF TEXAS                Telephone #: 5126312277
; Related Files:
; Min. Op. Sys.: NA                            Expertise Level: BEG
; Special:
; Description: Compute hash code of data in any size/type variable with
;       control over the number of bytes to be used and the number of
;       passes.  (Did you know DIR/H reads each file twice?)
;*****************************************************************************
;* Updated on 12-Jun-89 at 9:01 PM by ; edit time: 1:13:22 *;
; HASH.SBR
;
; syntax:
;       xcall hash,XVAR,RESULT {,SIZE {,FLAG }}
; where:
; XVAR,X        input data to compute a hash total of.
;               Must be even number of bytes or the LAST byte is not used
; RESULT,S  or  hash total is returned in ASCII (octal) aaa-bbb-ccc-ddd
; RESULT,B,4 or hash total is returned as a longword
; RESULT,X,4    hash total is returned as 4 bytes
; SIZE,F        optional, number of bytes in XVAR to use
;               must be even or will be rounded UP (1 byte added if odd)
;               if zero, or not given, all of XVAR is used
; FLAG,F        optional, number of passes for hash algorithm.
;               if zero, or not given, two passes are done.
;               The standard (DIR/H) uses two passes.
;
;
; portions (c) by Alphamicro systems.  (the actual hash algorithm)
; (c) 1989 by Ami Bar-Yadin
;
;-All commercial rights reserved, etc.
;-No warranties and/or guarranties of any kind, etc.
;-Not responsible for damages resulting from the use of this program, etc.
;-My employer (United Fashions) has nothing to do with this program and
; should not be blamed for it.
;
; I can be reached at:
;               United Fashions of Texas, Inc.
;               200 Ash Ave.
;               McAllen, TX  78501
;               (512) 631-2277
;               8am-6pm
;

VMAJOR=1
VMINOR=0
VEDIT=102.

       SYM
       MAYCREF
       OBJNAM  .SBR
       SEARCH  SYS
       SEARCH  SYSSYM
       RADIX   16.
       DEFAULT VEDIT,1
       DEFAULT $$MFLG,PV$RSM
       DEFAULT $$SFLG,PH$REE!PH$REU
       PHDR    -1,$$MFLG,$$SFLG

       DEFINE  BTYPE N,DEST
1$$     =       2+^D10*<N-1>
       CLR     DEST
       MOVW    1$$(A3),DEST
       ENDM

       DEFINE  BADRS N,DEST
1$$     =       4+^D10*<N-1>
       MOVL    1$$(A3),DEST
       ENDM

       DEFINE  BSIZE N,DEST
1$$     =       8+^D10*<N-1>
       MOVL    1$$(A3),DEST
       ENDM


HASH:
       CMPW    @A3,#2
       JLO     ERR1
       MOV     #2,D2                   ; default two passes
       BADRS   1,A2                    ; index source data
       MOV     A2,D6                   ; trap odd address
       BTST    #0,D6
       JNE     ERR2
       BSIZE   1,D0                    ; get input data size in bytes
       CMPW    @A3,#3                  ; is SIZE present?
       BLO     20$                     ; no
       BADRS   3,A0                    ; index 3rd arguent: SIZE
       FFTOL   @A0,D7                  ; get SIZE
       TST     D7                      ; is it zero?
       BEQ     20$                     ; yes.  use data size.
       BTST    #0,D7                   ; is it even?
       BEQ     10$                     ; yes.
       INC     D7                      ; no, round it UP.
10$:    CMP     D7,D0                   ; is it larger then data size?
       BHIS    20$                     ; yes.  use data size
       MOV     D7,D0                   ; no. use SIZE bytes
20$:    CMPW    @A3,#4                  ; FLAGS present?
       BLO     30$                     ; no.
       BADRS   4,A6                    ; index 4th argument:  FLAGS
       FFTOL   @A6,D7                  ; get FLAGS
       TST     D7                      ; is it zero?
       BEQ     30$                     ; yes. use default
       AND     #0F,D7                  ; par is down to 15
       MOV     D7,D2                   ; use FLAGS passes.
30$:    CLR     D3                      ; clear hash code totals
       CLR     D4
       LSR     D0,#1                   ; compute number of words in data
       BEQ     50$                     ; if zero, EXIT
       DEC     D2                      ; pre-dec for DBx
40$:    CALL    CLCHSH                  ; one hash code pass
       DBF     D2,40$                  ; loop for all passes
50$:    CMPW    @A3,#3                  ; is SIZE present?
       BLO     60$                     ; no
       FLTOF   D0,@A0                  ; yes, return number of words.
60$:    BADRS   2,A2                    ; index 2nd argument: RESULT
       BSIZE   2,D2                    ; get size of RESULT
       BTYPE   2,D1                    ; get type of RESULT
       AND     #0F,D1
       BEQ     80$                     ; unformatted(X): 4 bytes
       CMPB    D1,#4                   ; float(F): 32-bit signed
       BEQ     90$
       CMPB    D1,#6                   ; binary(B): 4 bytes
       BEQ     80$
       CMP     D2,#16.                 ; string(S): 15-chars plus null
       JLO     ERR3
       CALL    PRTHSH                  ; output hash in std ascii format
70$:    RTN
; output hash in lsb..msb order (basic B,4)
80$:    CMP     D2,#4                   ; make sure we have 4 bytes
       JLO     ERR3
       MOVW    D3,D7                   ; d3-lo word
       MOVB    D7,(A2)+                ; d3-lo
       RORW    D7,#8.
       MOVB    D7,(A2)+                ; d4-hi
       MOVW    D4,D7                   ; d4-hi word
       MOVB    D4,(A2)+                ; d4-lo
       RORW    D7,#8.
       MOVB    D7,(A2)+                ; d4-hi
       JMP     70$
; output byte a basic float
90$:    MOVW    D4,D7                   ; get HI word
       SWAP    D7                      ; swap words
       MOVW    D3,D7                   ; get LO word
       FLTOF   D7,@A2                  ; output to float
       JMP     70$

;---
; compute hash code of data @A2, D0 words long
; D3,D4-in/out hash code totals
;
CLCHSH: SAVE    D0,D2,A2
       CLR     D7
10$:    MOVW    (A2)+,D2
       ADDW    D2,D3
       ADDXW   D7,D4
       SUBW    D0,D4
       ADDXW   D7,D3
       ADDW    D3,D4
       ADDXW   D7,D3
       LSLW    D3,#1
       ROXLW   D4,#1
       ADDXW   D7,D3
       DEC     D0
       BNE     10$
       REST    A2,D2,D0
       RTN

;---
; HASH TOTALS
;
PRTHSH: SAVE    D1,D2,D3,D4,A2
       JOBIDX
       PUSHW   JOBTYP(A6)
       PUSH    A6
       ANDW    #^CJ.HEX,JOBTYP(A6)
       CLR     D1
       MOVW    D4,D1
       OCVT    3,OT$MEM
       MOVB    #'-,(A2)+
       RORW    D1,#8
       OCVT    3,OT$MEM
       MOVB    #'-,(A2)+
       MOVW    D3,D1
       OCVT    3,OT$MEM
       MOVB    #'-,(A2)+
       RORW    D1,#8
       OCVT    3,OT$MEM
       CLRB    @A2
       POP     A6
       POPW    JOBTYP(A0)
       REST    A2,D4,D3,D2,D1
       RTN


;-------
; Fatal error messages
;
ERR1:   TYPE    <?Not enoght args for>
       BR      ERREXT
ERR2:   TYPE    <?Odd DATA address passed to>
       BR      ERREXT
ERR3:   TYPE    <?RESULT too short for>
;       BR      ERREXT
ERREXT: TYPECR  < XCALL HASH>
       EXIT
;
;
       END