
%if 0

lDebug isvariable? function strutures and macros

Copyright (C) 2008-2025 E. C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif


	struc ISVARIABLESTRUC
ivName:		resw 1		; -> name (up to 13 bytes, but actually only 11)
				;  (search for ivfNameLengthLimit for limit)
				;  (length given by ivFlags & ivfNameLengthMask)
	; The ivName pointer is only used for more-byte names. It actually
	;  contains the trailer of the name, excluding the prefix formed by
	;  the first two bytes. This suffix can be the empty string if the
	;  variable in question has a two-byte name.
	; (For one-byte names this field is unused and contains zero.)
ivFlags:	resw 1
ivAddress:	resw 1		; default -> variable
	; The ivAddress field is used by default_variable_setup as the base
	;  address for the variable(s). It is also used by var_ext_setup as
	;  the ELD code section offset to transfer control to. Otherwise, it
	;  is usually set to zero and unused.
ivSetup:	resw 1		; -> set up code (in expr code section)
	; INP:	ax = array index (0-based)
	;	di = 0
	;	cl = default size of variable (1..4)
	;	ch = length of variable name
	;	bx -> ISVARIABLESTRUC structure
	; CHG:	ax, bx, cx, dx, si, di
	; OUT:	NC if valid,
	;	 bx -> var, di = 0 or di -> mask
	;	 cl = size of variable (1..4)
	;	 ch = length of variable name
ivArrayLast:	resb 1		; 0 if no array, FFh = 256 entries
	; The ivArrayLast field is used by the dispatcher to determine
	;  whether to support array index expressions. It is checked
	;  before decrementing the index if ivfArrayOneBased is set.
ivArrayBetween: resb 1		; how many bytes to skip for each index
	; The ivArrayBetween field is only used by default_variable_setup.
	endstruc

ivfNameLengthMask:	equ 15	; gives name trailer length, 0 to 11
ivfNameLengthLimit:	equ 13
ivfVarLengthShift:	equ 4
ivfVarLengthMask:	equ 3 << ivfVarLengthShift
				; gives default variable size minus 1
ivfReadOnly:		equ 80h	; variable cannot be written at all
ivfArrayOneBased:	equ 100h; first array entry is 1 not 0 (ivArrayLast > 0)
ivfArrayOptional:	equ 200h; array index expression is optional
ivfSeparatorSpecial:	equ 400h; used for RIxxP/L/S/O

%define ISVARIABLESTRINGS db "",db ""
%define IVS_ONEBYTE_NAMES ""
%define IVS_MOREBYTE_NAMEHEADERS ""
%assign IVS_HAVE_ONEBYTE 0
%assign IVS_SINGLE_ONEBYTE 1

		; %1 = name string
		; %2 = default variable length, 1 to 4
		; %3 = flags to set (except name length and var length)
		; %4 = ivAddress value
		; %5 = ivArrayLast, defaults to 0 (no array)
		; %6 = ivArrayBetween, defaults to 0 (immediately consecutive)
		; %7 = ivSetup, defaults to default_variable_setup
	%macro isvariablestruc 4-7.nolist 0, 0, default_variable_setup
%push
%strlen %$namelength %1
%if %$namelength > ivfNameLengthLimit
 %error Expected at most 13-byte name (or adjust isvariable? code)
%endif
%if IVS_ONEBYTE && %$namelength != 1
 %error Expected a one-byte name
%elif ! IVS_ONEBYTE && %$namelength < 2
 %error Expected at least a two-byte name
%endif
%if IVS_ONEBYTE
 %define IVS_SINGLE_ONEBYTE_NAME %1
 %if IVS_HAVE_ONEBYTE
  %assign IVS_SINGLE_ONEBYTE 0
 %endif
 %assign IVS_HAVE_ONEBYTE 1
 %assign %$namelength 0
 %xdefine IVS_ONEBYTE_NAMES IVS_ONEBYTE_NAMES, %1
 %%name equ 0
%else
 %assign %$namelength %$namelength - 2
 %substr %$nametrailer %1 3,-1
 %substr %$nameheader %1 1,2
 %xdefine IVS_MOREBYTE_NAMEHEADERS IVS_MOREBYTE_NAMEHEADERS, %$nameheader
 %xdefine ISVARIABLESTRINGS ISVARIABLESTRINGS, %%name:, {db %$nametrailer}
%endif

%assign %$varlength %2 - 1	; 0 means one byte, 1 means two bytes,
				;  2 means three bytes, 3 means four bytes
	istruc ISVARIABLESTRUC
at ivName,		dw %%name
 IV_NAME_RELOCATION
at ivFlags,		dw %$$namelength | (%$$varlength << ivfVarLengthShift) | %3
at ivAddress,		dw %4
 IV_ADDRESS_RELOCATION
at ivSetup,		dw %7
 IV_SETUP_RELOCATION
at ivArrayLast,		db %5
at ivArrayBetween,	db %6
	iend
%pop
%ifndef SECTION_OF_%7
 %error Unknown target section for symbol %7
%elifnidni %[SECTION_OF_%7], _EXPR_SECTION
 %error Wrong section for symbol %7: section_of=SECTION_OF_%7, expr=_EXPR_SECTION
%endif
	%endmacro

%define IV_NAME_RELOCATION
%define IV_ADDRESS_RELOCATION
%define IV_SETUP_RELOCATION

	%macro isvariablestrings 2-*.nolist
%rep %0
 %1
 %rotate 1
%endrep
	%endmacro
