;
; libOpts.s
;
; Allow options for library units to be declared
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sapphire library.
;
; Sapphire is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Sapphire is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Sapphire.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

		GET	libs:stream

;----- External dependencies ------------------------------------------------

		GET	sapphire:sapphire
		GET	sapphire:suballoc

;----- Main code ------------------------------------------------------------

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- libOpts_register ---
;
; On entry:	R0 == address of an options block
;
; On exit:	--
;
; Use:		Adds the block given to the library options.

		EXPORT	libOpts_register
libOpts_register ROUT

		STMFD	R13!,{R0,R1,R12,R14}	;Save some registers
		WSPACE	lo__wSpace		;Locate my workspace

		BL	sub_init		;Awaken suballoc just in case
		MOV	R1,R0			;Look after the block addr
		MOV	R0,#8			;Allocate a small link block
		BL	sub_alloc		;Try to allocate memory
		LDMVSFD	R13!,{R0,R1,R12,PC}^	;If it failed, don't bother

		STR	R1,[R0,#0]		;Remember this block pointer
		LDR	R14,lo__head		;Load the current list head
		STR	R14,[R0,#4]		;Save this as the next link
		STR	R0,lo__head		;And save new list head
		LDMFD	R13!,{R0,R1,R12,PC}^	;And return to caller

		LTORG

; --- libOpts_find ---
;
; On entry:	R0 == magic marker word
;
; On exit:	CS if found, and
;		  R0 == address of options block
;		else CC, and
;		  R0 corrupted
;
; Use:		Tries to find an option with the given marker, which will
;		normally be a four-character text string.  The first match
;		found will be returned.  The options blocks are searched in
;		reverse order of registration (i.e. blocks registered later
;		will override blocks registered reviously).

		EXPORT	libOpts_find
libOpts_find	ROUT

		STMFD	R13!,{R1-R3,R12,R14}	;Save some registers away
		WSPACE	lo__wSpace		;Find my workspace
		MOV	R2,R0			;Look after the marker
		LDR	R1,lo__head		;Load the list head block

		; --- Scan through the list ---

10libOpts_find	CMP	R1,#0			;Reached the end yet?
		BEQ	%50libOpts_find		;Yes -- return to caller
		LDMIA	R1,{R0,R1}		;Load the block ptr and link

		; --- See if we can find it in here ---

20libOpts_find	LDMIA	R0!,{R3,R14}		;Load marker and size word
		CMP	R2,R3			;Does this match up?
		BEQ	%40libOpts_find		;Yes -- found it then
		CMP	R3,#-1			;Is this the block end?
		ADDNE	R0,R0,R14		;No -- move on to next item
		BNE	%20libOpts_find		;And loop round again
		B	%10libOpts_find		;Try the next options block

		; --- Found a match ---

40libOpts_find	LDMFD	R13!,{R1-R3,R12,R14}	;Restore registers
		ORRS	PC,R14,#C_flag		;Return successfully

		; --- Failed to find a match ---

50libOpts_find	LDMFD	R13!,{R1-R3,R12,R14}	;Restore registers
		BICS	PC,R14,#C_flag		;Return unsuccessfully

		LTORG

lo__wSpace	DCD	0

;----- Workspace ------------------------------------------------------------

		^	0,R12
lo__wStart	#	0

lo__head	#	4			;Base of the options list

lo__wSize	EQU	{VAR}-lo__wStart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	lo__wSize
		DCD	lo__wSpace
		DCD	0
		DCD	0

;----- That's all, folks ----------------------------------------------------

		END
