;*; Updated on 17-Sep-92 at 5:55 AM by James A. Jarboe I V; edit time: 0:13:42
; 	
; TBXHS1 - Demonstrates bug in TOOLBX  hashing routine,
;
; This program will create a hash for a number and then compare that
; hash against a sequence of hashes for all numbers between that number
; and a maximum number. This program uses ESP style hashing.
;
; If a match is found withing that sequence then the bell will ring and
; the number will be output in low intensity.
;
; The bright number is the one we are checking against.
;
; [100] 17-Sep-92 by James A. Jarboe IV  


	SEARCH	SYS
	SEARCH	SYSSYM


DEFINE	PRTTAB	ROW, COL
	MOVW	#<ROW_8.+COL>, D1
	TCRT
ENDM

	VMAJOR	=	1
	VMINOR	=	0
	VEDIT	=	100.		; 17-Sep-92

	S..BOT	=	10000.		; Starting number
	S..TOP	=	20000.		; Top number.

; impure storage area.
;
.OFINI
.OFDEF	TT.HSH, 4			; Saved hash value.
.OFDEF	TT.NEW, 4			; New hash value.
.OFDEF	TT.NUM, 12.			; String.
.OFDEF	TT.OCR, 4			; Number of matches.
.OFSIZ	TT.SIZ				; Impure size.

; Really Demonstrate TOOLBX hashing problem.
;
START:
	PHDR	-1,0,PH$REE!PH$REU
	GETIMP	TT.SIZ, A5

	PRTTAB	-1,0			; Clear screen
	TYPECR	<Testing TOOLBX Hashing routine to demonstrate bug.>
	TYPECR	<Using ESP style hashing.>
	CRLF				; Bump line

	TYPECR	<String   Hash            Hash >
	CRLF

	MOV	#S..BOT, D3		; Set starting number.

; Loop for string to check against.
;
5$:	CTRLC	QUIT			; Quit on ^C.
	CRLF				; Bump line
	INC	D3			; Bump number 
	CMP	D3, #S..TOP		; Greater than top?
	JEQ	QUIT			; Yes..quit.
	PRTTAB	-1,12.			; Set bright.
	MOV	D3, D1			; Set number to convert.
	LEA	A2, TT.NUM(A5)		; Index buffer.
	DCVT	0,OT$MEM		; Make ASCII.
	LEA	A6, TT.NUM(A5)		; Index first string.
	MOV	#5, D6			; Set number of chars.
	CALL	DO.IT			; Do hashing and display.

	MOV	#S..BOT, D4		; Set starting number.

; Loop to create hash for all numbers between s..bot & s..top to compare
; against number we are checking.
;
10$:
	CTRLC	99$			; Exit on ^C
	INC	D4			; Bump count.
	CMP	D3, D4			; Same as number we are checking.
	BEQ	10$			; Try another.
	CMP	D4, #S..TOP		; At top yet?
	BEQ	99$			; Then stop and do next.
	MOV	D4, D1			; Set number/
	LEA	A2, TT.NUM(A5)		; Index buffer.
	DCVT	0,OT$MEM		; Make ascii.
	CLRB	@A2			; Clear end of buffer.
	LEA	A6, TT.NUM(A5)		; Index number.
	MOV	#5., D6			; Set number of char.
	CALL	TBXHSH			; Call hashing.
	MOV	D6, TT.NEW(A5)		; Save number.
	CMP	D6, TT.HSH(A5)		; Same as number we are testing?
	BNE	10$			; No..try next.
	PRTTAB	-1,11.
	LEA	A6, TT.NUM(A5)		; Yes..index buffer.
	MOV	#5, D6			; Set size.
	CALL	DO.IT			; Display hash match.
	MOV	#7, D1			; Ring bell.
	TTY
	ADD	#1, TT.OCR(A5)		; Bump match count.
	BR	10$			; Try again.

99$:
	JMP	5$			; Try next number sequence.


QUIT:	CRLF
	TYPE	<Total Duplicates = >
	MOV	TT.OCR(A5), D1
	DCVT	0,OT$TRM
	CRLF
	EXIT


; Do hashing and display.
; 
; Incoming:
;		D6 =: Number of chars to hash
;		A6 -> Indexes buffer of string to hash.
; Outgoing:
;		D6 =: Hash total of string.
;		A6 -> Indexes end of buffer.
;
DO.IT:
	PUSH	A6			; Save buffer address.
	CALL	TBXHSH			; Call hashing routine.
	MOV	D6, D1			; Save hash total
	MOV	D1, TT.HSH(A5)		; Save hash total.
	POP	A6			; Restore buffer address.
	TTYL	@A6			; Output string.
	TYPE	< = >			; Output seperator.
	DCVT	0, OT$TRM		; Output in decimal.
	TAB				;  
	OCVT	0,OT$TRM		; Output in current base.
	CRLF				; Bump line.
	RTN				; Return to caller.


; What appears to be TOOLBX's Hashing routine.
;
; Incoming:
;		D6 =: Number of characters to hash.
;
;		A6 -> Indexes buffer to hash.
;
; Outgoing:
;		D6 =: Hash total of field.
;		A6 -> Indexes end of buffer.

TBXHSH:

; It appears that the first step is to save the number of char in a field
; in the high byte of the low word and then save the total ASCII value
; of the string in the low byte of the low word, then save all of that
; in the high word.

	MOV	D6, D7			; Save number of chars.
	BEQ	99$			; Opps..none there..quit.
	SUB	#1, D7			; Dbf adjust count.
	ASL	D6, #8.			; Mul * 256. 
	SAVE	A6, D7			; Save address of buffer & count.
10$:	ADDB	(A6)+, D6		; Add ascii value byte to number.
	DBF	D7, 10$			; For all chars.

; The following code represents what appears to be adding in 
; the ESP field's Read and Write security level.
;
;  Which for most of the time is a constant unless it is changed in
;  an ESP screen. While changing this value would create a different
;  hash total than a previous one with different field security levels, it
;  would create the same hash total on the next pass if the values for Read
;  and Write security remain the same. Soooo for this example we assume
;  that the Read and Write security is 0. Thus we comment it out because
;  any number + 0 is still that number.

;;	ADDB    22(A3), D6	        ; Add read security value.
;;	ADDB    23(A3), D6	        ; Add Write security value.

	REST	A6, D7			; Restore buffer address & count.
	SWAP	D6			; Swap Words.

20$:	CLR	D1			; Preclear hasher.
	MOVB	(A6)+, D1		; Get next char.
	XORW	D1, D6			; Shake it.
	ROLW	D6, #1			; Roll it.
	DBF	D7, 20$			; And try again.
99$:	RTN				; Return to caller.

	END