;* ;* JAVA STRING POOL MANAGER FOR 6502 ;* ;* ;* THE STRING POOL CONTAINS ALL THE STRING CONSTANTS USED BY THE JVM. A HASH TABLE AIDS ;* IN THE LOOKUP OF THE STRING CONSTANTS. A STRING IS DEFINED BY ITS LENGTH AND ;* CONTENTS. THESE MAP INTO A UNIQUE HANDLE. TWO STRINGS ARE EQUAL IF THEIR HANDLES ARE ;* EQUAL. THE STRING POOL DOES NOT CONTAIN STRING OBJECTS. STRING OBJECTS SIMPLY CONTAIN ;* A HANDLE TO THEIR STRING VALUE. ;* ;* THE HASH VALUE OF A STRING IS CALCULATED BY XORING THE NEXT CHARACTER ;* INTO A ROTATED TOTAL. E.I. HASH = CHARACTER ^ ROL(HASH); ;* .INCLUDE "global.inc" .IMPORT INIT_START,INIT_END .IMPORT PRBYTE,CROUT,PUTS,PUTSLN,PRSTR,PRSTRLN,MEMSRC,MEMDST,MEMCLR,MEMCPY .IMPORT HMEM_ALLOC,HMEM_ALLOC_FIXED,HMEM_FREE .IMPORT HMEM_LOCK,HMEM_PTR,HMEM_REF_INC,HMEM_REF_DEC .EXPORT HSTR_INIT,HSTR_HASH,STR_HASH,HSTRPL_ADD,HSTRPL_DEL .SEGMENT "INIT" ;* ;* CREATE EXTERNAL LINKEAGE ;* HSTR_INIT: LDA #HSTRPL_ADD STA LINK_HSTRADD+1 LDA #HSTR_HASHL AUXZP_ACCESS_ON JSR MEMDST LDA #$00 LDX #$02 JSR MEMCLR AUXZP_ACCESS_OFF RTS .CODE ;* ;* ADD A STRING CONSTANT TO THE POOL. RETURN A HANDLE TO THE STRING CONSTANT. IF ;* A MATCHING STRING ALREADY EXISTS, RETURN ITS HANDLE AFTER INCREMENTING THE REF COUNT. ;* HSTR_HASH: JSR HMEM_PTR STR_HASH: STA STRPTR ; HASH STRING STX STRPTR+1 LDY #$00 LDA (STRPTR),Y BEQ STR_EXIT TAY LDA #$00 : CMP #$80 ; COPY MSB INTO CARRY ROL EOR (STRPTR),Y DEY BNE :- STR_EXIT: RTS ;* ;* ADD A STRING TO THE POOL ;* ENTRY: AX = POINTER TO STRING ;* EXIT: AX = HANDLE TO STRING IN POOL ;* Y = HASH ;* HSTRPL_ADD: JSR STR_HASH STA STRHASH ; SAVE HASH FOR LATER TAY AUXZP_ACCESS_ON LDA HSTR_HASHL,Y LDX HSTR_HASHH,Y AUXZP_ACCESS_OFF BEQ STRNEW ; EMPTY LIST, STRING NOT FOUND STRMATCH_LOOP: STA HSTR STX HSTR+1 JSR HMEM_PTR STA STRMATCHPTR STX STRMATCHPTR+1 LDY #$00 ; COMPARE STRING LENGTHS LDA (STRPTR),Y CMP (STRMATCHPTR),Y BNE STRMATCH_NEXT+2 ; NO NEED TO SET Y TO $00 AGAIN TAY ; COMPARE STRINGS BEQ STRMATCH ; CASE OF NULL STRING : LDA (STRPTR),Y CMP (STRMATCHPTR),Y BNE STRMATCH_NEXT DEY BNE :- STRMATCH: LDA HSTR ; STRING EXISTS, INC REF CNT LDX HSTR+1 JSR HMEM_REF_INC LDY STRHASH RTS STRMATCH_NEXT: LDY #$00 ; NEXT HANDLE AT END OF STRING LDA (STRMATCHPTR),Y CLC ADC STRMATCHPTR STA STRMATCHPTR BCC :+ INC STRMATCHPTR+1 : LDY #$02 LDA (STRMATCHPTR),Y ; GET NEXT STRING IN LIST DEY TAX LDA (STRMATCHPTR),Y CPX #$00 BNE STRMATCH_LOOP ; BEQ STRNEW ; END OF LIST, STRING NOT FOUND STRNEW: LDY #$00 ; ALLOC MEM FOR STRING ... LDA (STRPTR),Y LDX #$00 CLC ADC #$03 ; ... AND HANDLE TO NEXT STRING IN LIST BCC :+ INX : LDY #$01 JSR HMEM_ALLOC STA HSTR STX HSTR+1 JSR HMEM_PTR STA STRMATCHPTR STX STRMATCHPTR+1 LDY #$00 ; COPY STRING LENGTH OVER LDA (STRPTR),Y STA (STRMATCHPTR),Y TAY ; COPY STRING CHARACTERS BEQ STRINSRT : LDA (STRPTR),Y STA (STRMATCHPTR),Y DEY BNE :- STRINSRT: LDA (STRMATCHPTR),Y ; INSERT NEW HANDLE AT HEAD OF HASH LIST INY CLC ADC STRMATCHPTR STA STRMATCHPTR BCC :+ INC STRMATCHPTR+1 : LDX STRHASH AUXZP_ACCESS_ON LDA HSTR_HASHL,X AUXZP_ACCESS_OFF STA (STRMATCHPTR),Y INY AUXZP_ACCESS_ON LDA HSTR_HASHH,X AUXZP_ACCESS_OFF STA (STRMATCHPTR),Y LDY STRHASH LDA HSTR+1 AUXZP_ACCESS_ON STA HSTR_HASHH,Y AUXZP_ACCESS_OFF TAX LDA HSTR AUXZP_ACCESS_ON STA HSTR_HASHL,Y AUXZP_ACCESS_OFF RTS ;* ;* DECREMENT REFERENCE COUNT OF STRING FROM THE POOL. DELETE IT IF COUNT IS ZERO. ;* ENTRY: AX = HANDLE TO STRING ;* HSTRPL_DEL: STA HSTR STX HSTR+1 JSR HMEM_LOCK JSR STR_HASH STA STRHASH LDY #$00 LDA (STRPTR),Y INY CLC ADC STRPTR STA STRPTR BCC :+ INC STRPTR+1 : LDA (STRPTR),Y INY STA HSTRNEXT LDA (STRPTR),Y STA HSTRNEXT+1 LDY STRHASH AUXZP_ACCESS_ON LDA HSTR_HASHL,Y LDX HSTR_HASHH,Y AUXZP_ACCESS_OFF BEQ STRBAD ; EMPTY LIST, STRING NOT FOUND CMP HSTR BNE HSTRFIND_NEXT CPX HSTR+1 BNE HSTRFIND_NEXT LDA HSTRNEXT LDX HSTRNEXT+1 ; LDY STRHASH ; UNLINK FROM HEAD OF LIST AUXZP_ACCESS_ON STA HSTR_HASHL,Y TXA STA HSTR_HASHH,Y AUXZP_ACCESS_OFF LDA HSTR LDX HSTR+1 JMP HMEM_FREE HSTRFIND_LOOP: CMP HSTR BNE HSTRFIND_NEXT CPX HSTR+1 BNE HSTRFIND_NEXT LDY #$01 ; UNLINK STRING FROM LIST LDA HSTRNEXT STA (STRMATCHPTR),Y INY LDA HSTRNEXT+1 STA (STRMATCHPTR),Y HSTRFREE: LDA HSTR ; FREE STRING MEMORY LDX HSTR+1 JMP HMEM_FREE HSTRFIND_NEXT: JSR HMEM_PTR STA STRMATCHPTR STX STRMATCHPTR+1 LDY #$00 ; NEXT HANDLE AT END OF STRING LDA (STRMATCHPTR),Y CLC ADC STRMATCHPTR STA STRMATCHPTR BCC :+ INC STRMATCHPTR+1 : LDY #$02 LDA (STRMATCHPTR),Y ; GET NEXT STRING IN LIST DEY TAX LDA (STRMATCHPTR),Y BNE HSTRFIND_LOOP STRBAD: .IFDEF DEBUG PERR "BAD STRING HANDLE" JMP HSTRFREE .ELSE BEQ HSTRFREE ; END OF LIST, STRING NOT FOUND, FREE IT ANYWAY .ENDIF .IFDEF DEBUG_STRPOOL ;* ;* PRINT OUT STRING POOL DETAILS ;* .EXPORT HSTRPL_DUMP HSTRPL_DUMP: JSR CROUT PSTRLN "STRING POOL STATE" PSTRLN "=================" LDY #$00 STY STRHASH HSTR_HSHDUMP: LDY STRHASH AUXZP_ACCESS_ON LDA HSTR_HASHL,Y LDX HSTR_HASHH,Y AUXZP_ACCESS_OFF CPX #$00 BEQ HSTR_HSHNEXT STA HSTR STX HSTR+1 PSTR "HASH LIST: $" LDA STRHASH JSR PRBYTE JSR CROUT LDA HSTR LDX HSTR+1 HSTR_LSTDUMP: JSR HMEM_PTR STA STRPTR STX STRPTR+1 JSR PRSTRLN LDY #$00 ; NEXT HANDLE AT END OF STRING LDA (STRPTR),Y INY CLC ADC STRPTR STA STRPTR BCC :+ INC STRPTR+1 : LDA (STRPTR),Y ; GET NEXT STRING IN LIST INY PHA LDA (STRPTR),Y TAX PLA BNE HSTR_LSTDUMP HSTR_HSHNEXT: INC STRHASH BNE HSTR_HSHDUMP RTS .ENDIF