; ; strBucket.s ; ; String bucket handling ; ; © 1995 Straylight ; ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sh.anchor GET sh.mem ;----- Main code ------------------------------------------------------------ AREA |TermScript$$Code|,CODE,READONLY ; --- strBucket_init --- ; ; On entry: -- ; ; On exit: -- ; ; Use: Initialises the string bucket. EXPORT strBucket_init strBucket_init ROUT STMFD R13!,{R0-R2,R14} ;Save some registers ; --- Allocate the string bucket block --- MOV R0,#1024 ;Start off nice and big BL mem_alloc ;Allocate the block MOV R1,#256 ;Reserve space for the table MOV R2,#1024 ;Remember starting size ADR R14,tsc_bucket ;Find the workspace part STMIA R14,{R0-R2} ;Save this information away ; --- Now initialise the bucket table --- LDR R0,[R0] ;Load actual block address MOV R1,#64 ;We have 64 buckets to handle MOV R14,#0 ;Clear them all to zero 00 STR R14,[R0],#4 ;Save the initial value SUBS R1,R1,#1 ;Decrement the counter BNE %00strBucket_init ;And loop LDMFD R13!,{R0-R2,PC}^ ;Now return to caller LTORG ; --- strBucket_alloc --- ; ; On entry: R0 == size of string to allocate ; ; On exit: R0 == pointer to area to use (length at [R0,#-1]) ; R1 == offset to that (for storing) ; ; Use: Allocates space for a string of the given size. EXPORT strBucket_alloc strBucket_alloc ROUT ; --- Quick optimisation --- SUBS R1,R0,#0 ;Is this a null string? MOVEQS PC,R14 ;Yes -- return zero then STMFD R13!,{R2,R3,R14} ;Save some registers MOV R2,R0 ;Look after length ; --- Find the actual block length --- ADD R3,R2,#4 ;Add 1 byte for len, and... BIC R3,R3,#3 ;...word align LDR R0,tsc_bucket ;Find the bucket anchor LDR R14,[R0] ;WimpExt? Bollocks more like LDR R1,[R14,R3] ;Load the free list head CMP R1,#0 ;Is this empty? LDRNE R0,[R14,R1] ;Load the link from this blk STRNE R0,[R14,R3] ;And stuff it in list head ADDNE R0,R14,R1 ;No -- work out address BNE %20strBucket_alloc ;And skip ahead ; --- Need to allocate more space --- ADR R14,tsc_bktPtr ;Find the free pointer LDMIA R14,{R1,R14} ;Load free ptr and size ADD R1,R1,R3 ;Add on the space we need STR R1,tsc_bktPtr ;Store modified pointer SUB R3,R1,R3 ;Look after old offset CMP R1,R14 ;Do we have enough? BGT %50strBucket_alloc ;No -- get some more then 10 MOV R1,R3 ;Find start of string space LDR R0,[R0] ;This is getting IRRITATING ADD R0,R0,R1 ;Get string block address ; --- Set up the string ready for caller --- 20 STRB R2,[R0],#1 ;Save the length byte ADD R1,R1,#1 ;Bump the offset on LDMFD R13!,{R2,R3,PC}^ ;And return to caller ; --- Extend the bucket area --- 50 MOV R14,#&FF ;Build up 1023 ORR R14,R14,#&300 ADD R1,R1,R14 ;Add on chunking size BIC R1,R1,R14 ;And align nicely BL mem_realloc ;Reallocate the area STR R1,tsc_bktSize ;And save the new size B %10strBucket_alloc ;And leap back again LTORG ; --- strBucket_free --- ; ; On entry: R0 == offset of string to free ; ; On exit: -- ; ; Use: Frees the memory the string took up. EXPORT strBucket_free strBucket_free ROUT CMP R0,#0 ;Is this a bogus offset MOVEQS PC,R14 ;Yes -- ignore it then STMFD R13!,{R0-R2,R14} ;Save some registers LDR R1,tsc_bucket ;Load the bucket anchor LDR R1,[R1] ;Spotted the pattern yet? SUB R0,R0,#1 ;Find the actual start offset LDRB R2,[R1,R0] ;Load the length byte ADD R2,R2,#4 ;Add length byte and align BIC R2,R2,#3 LDR R14,[R1,R2] ;Load the list head STR R14,[R1,R0] ;Save this in freed block STR R0,[R1,R2] ;And make this the new head LDMFD R13!,{R0-R2,PC}^ ;And return to caller LTORG ;----- That's all, folks ---------------------------------------------------- END