;
; choices.options.sh
;
; Read options from an options chunk
;
;  1995-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.

;----- Overview -------------------------------------------------------------
;
; Functions provided:
;
;  options_read
;  options_write
;  optType_string
;  optType_integer
;  optType_literal
;  optType_enum
;  optType_bool
;  optType_version

		[	:LNOT::DEF:options__dfn
		GBLL	options__dfn

;+		LIB	sapphire:^.bsh.options

; --- options_read ---
;
; On entry:	R0 == chunk file handle
;		R1 == pointer to a chunk name
;		R2 == pointer to options definition
;		R3,R4 specify address of output block
;
; On exit:	--
;
; Use:		Claims the specified options chunk, and reads the data in
;		it into a binary block.  Because the output data might be
;		in a flex block, the two registers R3,R4 which define its
;		address work as follows:
;
;		R3 == address or offset of data
;		R4 == -1 if R3 is address, else flex anchor address

		IMPORT	options_read

; --- options_write ---
;
; On entry:	R0 == terminator character to write, 0 for none, or -1 for
;			quoting with 's
;		R1 == pointer to name to save
;
; On exit:	May return an error
;
; Use:		Writes out an option name, terminated with the character
;		given in R0 (which will normally be a space or an `=' sign).

		IMPORT	options_write

; --- optType_string ---
;
; Flags:	--
;
; Data:		(word) buffer size of string
;
; Use:		Handles string data.  The binary representation is a ctrl
;		terminated string.  The textual representation is a sequence
;		of characters, which is always output in single quotes,
;		although this is not necessary for the input.  The string
;		will be truncated to fit in the buffer during reading.

		IMPORT	optType_string

; --- optType_integer ---
;
; Flags:	bit 8 == use given default base
;
; Data:		(word) default base, if bit 8 set
;
; Use:		Handles integer data.  The binary representation is a 32-
;		bit integer value.  The textual representation is the normal
;		RISC OS style of numbers (i.e. the base_value notation is
;		supported).  Numbers are always output in the default base
;		given (or in decimal if there is none given).  Numbers
;		being read may always have a sign; numbers will only be
;		output with a sign if the default base is decimal.  Uppercase
;		letters will be used for output, but any case is acceptable
;		for input.
;
;		Special prefixes allowed are `%' for binary and `&' for hex.
;		Such numbers are always output with these prefixes.

		IMPORT	optType_integer

; --- optType_literal ---
;
; Flags:	--
;
; Data:		(string) data to write out (*null* terminated)
;
; Use:		Reads nothing; leave the name blank.  Writes out the data
;		literally.  Note that an extra linefeed is added to the
;		end, so don't overdo it.

		IMPORT	optType_literal

; --- optType_enum ---
;
; Flags:	bit 8 == quote output string
;		bit 9 == don't put an `=' sign in output
;
; Data:		See below
;
; Use:		The data is a collection of ctrl-terminated strings, itself
;		terminated by a zero-length entry.  The textual
;		representation is one of these strings, or an abbreviation
;		of one.  The binary representation is a word containing the
;		index into the list.

		IMPORT	optType_enum

; --- optType_bool ---
;
; Flags:	bit 8 == make flag active low
;		bit 9 == use `on'/`off' rather than `true'/`false'; also
;			suppresses the `=' sign
;
; Data:		(word) bit mask to OR or BIC within word
;
; Use:		Handles a boolean option.  It will translate between the
;		strings `true' or `false' and a bit (or set of bits) within
;		a word.

		IMPORT	optType_bool

; --- optType_version ---
;
; Flags:	--
;
; Data:		--
;
; Use:		Converts between version number strings (of the form
;		<int>[.[<digit>[<digit>]]]) and integers.  The version
;		number is stored multiplied by 100.

		IMPORT	optType_version

		]

;----- Data structures ------------------------------------------------------

; --- Options definition block ---

		^	0
opt_flags	#	4			;Flags for this item
opt_length	#	4			;Size of this table entry
opt_offset	#	4			;Offset in block of data
opt_type	#	4			;Address of type handler
opt_name	#	0			;Name of this option

; --- Option block flags ---

optFlag_last	EQU	(1<<0)			;This is the last block
optFlag_ignore	EQU	(1<<1)			;Don't read this option

; --- Integer type flags ---

intFlag_base	EQU	(1<<8)			;Default base specified

; --- Enumeration type flags ---

enumFlag_quote	EQU	(1<<8)			;Quote the output string
enumFlag_noEq	EQU	(1<<9)			;Don't output an `=' sign

; --- Boolean type flags ---

boolFlag_cpl	EQU	(1<<8)			;Flag is complemented
boolFlag_onOff	EQU	(1<<9)			;Use `on'/`off' notation

; --- Type handler reason codes ---
;
; All enter with:
;
;  R0 == reason code
;  R7 == flags read from table
;  R8 == address of option name
;  R9 == address of type-specific data
; R10 == address of binary option

		^	0
optReason_read	#	1			;Read from option string
						;R1 == pointer to string

optReason_write	#	1			;Write data to xsave file

;----- Macros ---------------------------------------------------------------

		GBLA	opt__f
		GBLA	opt__c
opt__c		SETA	0
		GBLL	opt__p
opt__p		SETL	{FALSE}

; --- Macro: OPTION ---
;
; Arguments:	offset == offset of data into options block
;		type == name of data type
;		name == name of option tag
;
; Use:		Starts building an entry in the options table.

		MACRO
$label		OPTION	$offset,$type,$name
		ALIGN

		[	opt__p
opt__sz$opt__c	EQU	{PC}-opt__a$opt__c
		]
opt__f$opt__c	EQU	opt__f
opt__c		SETA	opt__c+1
opt__p		SETL	{TRUE}

$label

opt__f		SETA	0
opt__a$opt__c

		DCD	opt__f$opt__c
		DCD	opt__sz$opt__c
		DCD	$offset
		DCD	$type
		DCB	"$name",0
		ALIGN

		MEND

; --- Macro: OPTFLAG --
;
; Arguments:	bit == bit to set
;
; Use:		Sets a bit in the flags word for the current option.

		MACRO
		OPTFLAG	$bit
opt__f		SETA	opt__f :OR: $bit
		MEND

; --- Macro: OPTEND ---
;
; Arguments:	--
;
; Use:		Terminates an options block.

		MACRO
		OPTEND
		OPTFLAG	optFlag_last
		ALIGN
		[	opt__c<>0
opt__sz$opt__c	EQU	{PC}-opt__a$opt__c
		]
opt__f$opt__c	EQU	opt__f
opt__c		SETA	opt__c+1
opt__p		SETL	{FALSE}
		MEND

; --- Macro: OPTSTR ---
;
; Arguments:	offset == offset into block to write integer
;		name == tag for option
;		size == buffer size for string
;
; Use:		Adds a `string' option.

		MACRO
$label		OPTSTR	$offset,$name,$size
$label		OPTION	$offset,optType_string,$name
		DCD	$size
		MEND

; --- Macro: OPTINT ---
;
; Arguments:	offset == offset into block to write integer
;		name == tag for option
;		base == (optional) default base to use
;
; Use:		Adds an `integer' option.

		MACRO
$label		OPTINT	$offset,$name,$base
$label		OPTION	$offset,optType_integer,$name
		[	"$base"<>""
		OPTFLAG	intFlag_base
		DCD	$base
		]
		MEND

; --- Macro: OPTLIT ---
;
; Arguments:	--
;
; Use:		Writes out the following text to the options chunk.

		MACRO
$label		OPTLIT
$label		OPTION	0,optType_literal,""
		OPTFLAG	optFlag_ignore
		MEND

; --- Macro: OPTENUM ---
;
; Arguments:	offset == offset into block to write integer
;		name == tag for option
;
; Use:		Adds an `enumeration' option.  Follow by null-terminated
;		list of null-terminated strings.

		MACRO
$label		OPTENUM	$offset,$name
$label		OPTION	$offset,optType_enum,$name
		MEND

; --- Macro: OPTBOOL ---
;
; Arguments:	offset == offset into block to write flags
;		name == tag for option
;		flag == flag bit to set
;
; Use:		Adds a `boolean' option.

		MACRO
$label		OPTBOOL	$offset,$name,$flag
$label		OPTION	$offset,optType_bool,$name
		DCD	$flag
		MEND

; --- Macro: OPTVSN ---
;
; Arguments:	offset == offset into block to write integer
;		name == tag for option
;
; Use:		Adds a `version number' option.

		MACRO
$label		OPTVSN	$offset,$name
$label		OPTION	$offset,optType_version,$name
		MEND

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

		END
